Martin Fowler's Blog, page 31
November 30, 2015
Role of an Enterprise Architect in a Lean Enterprise

Many software projects that use agile and lean approaches have difficulties with
enterprise architects, whose role changes significantly in this context. Kevin
Hickey has been working with enterprise architecture groups with our clients and
shares his observations on how enterprise architects can engage successfully in this
context by building a vision and building bridges between groups to help realize
that vision.
November 21, 2015
photostream 92
Lightroom Lua script to select a repeating annual date range
I need to find all the photos that I've taken in November over the last few
years. I can't express this query easily in Lightroom, so I figured out how to write
a Lua script that would make this query. These notes describe what I did, as someone
who had never before programmed with Lua, nor used the scripting environment in
Lightroom.
November 19, 2015
Second installment of refactoring code into data

I now move onto the second, more awkward, section of the
imperative code to refactor to an adaptive model. This shows how
I need to massage both the imperative code to make it fit the
model's structure better, and the model to support more
capabilities. I then finish by comparing the imperative and
active model approaches.
November 11, 2015
Refactoring Code into Data

Our regular programming languages are where we usually like
to keep our logic, but there are times when it's useful to embed
logic into a data structure. Logic in a JSON file can remove
duplication when that same logic has to run on multiple
platforms that use different languages. This essay looks at how
to refactor logic from imperative code into such a data structure.
October 31, 2015
photostream 91
October 19, 2015
Remote versus Co-located Work

In the software industry we hear a lot of discussion about
the pros and cons of remote work, and a recent outbreak of that
finally got me to write my thoughts down. I point out that
there's distinct patterns of remoteness, which yield different
trade-offs and varied techniques to make them work. I recognize
that we lack any conclusive evidence on effectiveness, but sense
that most people are more productive when co-located, but even
so organizations can build more productive teams with a remote
working structure.
October 17, 2015
photostream 90
October 13, 2015
Refactoring Module Dependencies

As a program grows in size it's important to split it into
modules, so that you don't need to understand all of it to make a
small modification. Often these modules can be supplied by
different teams and combined dynamically. In this refactoring
essay I split a small program using Presentation-Domain-Data
layering. I then refactor the dependencies between these modules
to introduce the Service Locator and Dependency Injection
patterns. These apply in different languages, yet look different,
so I show these refactorings in both Java and a classless
JavaScript style.
October 12, 2015
Bliki: RequiredInterface
A required interface is an interface that is defined by the
client of an interaction that specifies what a supplier component needs to do so
that it can be used in that interaction.
A good example of required interface is an interface commonly
referred to as “comparable”. Such an interface is usually required
by a sort function. Imagine I have a set of albums, and I want to
sort them by title, but ignoring articles such as "The", "A", and
"An". I can arrange them to be sorted in this way by implementing
the required interface for any sort functions.

In Java it would look
something like this.
class Album...
public class Album implements Comparable<Album> {
private String title;
public Album(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
@Override
public int compareTo(Album o) {
return this.sortKey().compareTo(o.sortKey());
}
private String sortKey() {
return ignoreSortPrefixes(title).toLowerCase();
}
private static String ignoreSortPrefixes(String arg) {
final String[] prefixes = {"an", "a", "the"};
return Arrays.stream(prefixes)
.map(s -> s + " ")
.filter(s -> arg.toLowerCase().startsWith(s))
.findFirst()
.map(s -> arg.substring(s.length(), arg.length()))
.orElse(arg)
;
}
In this case Comparable is the required interface of
the various Java sort functions. More complicated examples can have
a richer interface with several methods defined on it.
Often people think about interfaces as a decision by the supplier
about what to expose to clients. But required interfaces are
specified (and often defined) by the client. You often get more
useful interfaces by thinking about what clients require - leading
towards thinking about RoleInterfaces.
Using an Adapter
A common problem comes up if I want to plug together two modules
that have been defined independently. Here we can run into
difficulties even if we get names that match.
Consider a task list with a required interface of tasks.
class TaskList...
private List<Task> tasks;
private LocalDate deadline;
public LocalDate latestStart() {
return deadline.minusDays(tasks.stream().mapToInt(t -> t.shortestLength()).sum());
}
}
interface Task…
int shortestLength();
Let's imagine I want to integrate it with an Activity
class I got from a different supplier.
class Activity…
public int shortestLength() {
…
Even though the activity has a method whose signature happens to match the
required interface's, I (rightly) can't create a
task list of activities because the type definitions don't match. If
I can't modify the activity class I need to use an adapter.
public class ActivityAdapter implements Task {
private Activity activity;
public ActivityAdapter(Activity activity) {
this.activity = activity;
}
@Override
public int shortestLength() {
return activity.shortestLength();
}
}
In the software world we use the term adapter pretty freely, but
here I'm using strictly in the sense of the Gang of
Four book. In this usage an adapter is an object that maps one
object to the required interface of another.

In this case, I don't need an adapter if I'm using a dynamic
language, but I do if the activity class used a method with a
different signature.
Acknowledgements
Alexander Zagniotov and Bruno Trecenti commented on
drafts of this post.
Share:



if you found this article useful, please share it. I appreciate the feedback and encouragement
Martin Fowler's Blog
- Martin Fowler's profile
- 1099 followers
