Excellent series of images from Derick Bailey. Here’s an example:
Single Responsibility Principle
Just because you can, doesn’t mean you should.

RT @Jtf
Working software daily
Notes on the craft of programming
Excellent series of images from Derick Bailey. Here’s an example:
Just because you can, doesn’t mean you should.

RT @Jtf
I was chatting with Keith about what the Software Craftsmanship event should really be about, in the context of a discussion of whether some of Jason Gorman’s list of guitar heroes are actually worth listening to (you still with me?) 1.
The next obscure piece of evidence is Maurice Murphy’s YouTube masterclass. For those who don’t know, Maurice Murphy has been Principal Trumpet in the London Symphony Orchestra for years (nerds without an interest in orchestral music will nonetheless have heard him on the Star Wars sound tracks). What’s interesting about the video is that what they emphasise most is being musical, making sense of the melody. They have no interest in pyrotechnics and assume that the student knows the basics.
The (barely sustainable) link with master-level coding and performance, we realised, is that both are about being expressive. The master coder/performer has a point of view and they use their considerable technical skills to get it across. The code that really impresses me is almost entirely about the domain, it just reads well. Most of the code most of us see, however, is stuck a level below, I have to read through the implementation to get to the meaning.
Years ago an old friend of mine said that when she first started going to conferences she wouldn’t be impressed by some of the big names because what they said was obvious. Later, she learned that being obvious can be really hard.
There’s a common pattern where an object is constructed with a Context object that carries all the dependencies the new object might need. It’s often used, for example, with classes that package up domain behaviour based on lower-level services, something like this:
public class PriceReconciler {
private final Context context;
public PriceReconciler(Context context) {
this.context = context;
}
public boolean isAvailable(Item item, Price price) {
Location location =
context.getLocationFinder().findLocationFor(item);
SKU sku = location.lookup(item);
return context.getCurrencyConverter()
.compare(price, sku.cost()) < 0;
}
// and so on...
}
Over time the Context gets used in more and more places, and acquires more and more contents to carry around. It starts to feel like Mary Poppins’ carpet bag (there’s an old cultural reference) that contains a roomful of furniture. When everything is available everywhere then developers will use what they have in scope and, pretty soon, there are implicit dependencies all over the domain layer.
A while ago, I was working with a class that used one of these context objects. The class was quite large so, to help us understand it, my pair and I extracted the services it used into fields:
public class PriceReconciler {
private final LocationFinder locationFinder;
private final CurrencyConverter currencyConverter;
private final LooseChangeCollector looseChangeCollector;
public PriceReconciler(Context context) {
this.locationFinder = context.getLocationFinder();
this.currencyConverter = context.getCurrencyConverter();
this.looseChangeCollector =
context.getLooseChangeCollector();
}
// and so on...
}
Doing this made clear that the class used only three of the many services available on the context. More interesting, it showed that the looseChangeCollector was only used once, in a method that turned out to be referenced just once—by a class that also had access to the context. Our extraction highlighted that this behaviour was in the wrong place, it didn’t really have a relationship with the rest of PriceReconciler, so we moved it to its calling object and simplified the PriceReconciler. With just two dependencies, our
next step was to set them directly in the constructor
public class PriceReconciler {
private final LocationFinder locationFinder;
private final CurrencyConverter currencyConverter;
public PriceReconciler(LocationFinder locationFinder,
CurrencyConverter currencyConverter)
{
this.locationFinder = locationFinder;
this.currencyConverter = currencyConverter;
}
// and so on...
}
which made the PriceReconclier just a little easier to reuse since we’d narrowed its dependencies.
Kent Beck wrote recently about this tension between being concrete and abstract parameters. There obviously isn’t a single answer, except to note that when two or three objects keep turning up together, there’s probably a missing intermediate concept where some of the behaviour really belongs. The trick, when turning that concept into a type, is to give it a meaningful name so that it’s hard to add features that don’t belong.