I get it – pun intended
Going back to The Getter Setter Debate, I knew that, like most things you learn in software, you don’t really get it until you do it. And seeing examples that are convenient, simple, and complex enough to illustrate a situation is nice for reference, but, for me, it doesn’t stick until I have to use the new knowledge in my own situation.
You might remember such gems as these:
account.appendTransactionTo(statement); |
statement.appendTransactionsFrom(account); |
Money total = …; Money amount = …; total.increaseBy( amount ); |
What they all have in common is that they read like English sentences: “Hey account, append transaction to statement”. They surely get the point across to the reader, but like writing a compiler, until you do it yourself, you don’t get it.
The epic Martin Fowler book, Refactoring, was the second required reading in the course that also introduced me to Evans’ Domain-Driven Design and changed the way I think about software. While not as impactful on the impressionable me of a mere year ago, the Fowler book is brimming with code examples.
One code smell, among many, to which I have since become cognizant, is the Message Chain smell:
You see message chains when a client asks one object for another object, which the client then asks for yet another object, which the client then asks for yet another object, and so on. You may see these as a long line of getThis methods, or as a sequence of temps. Navigating this way means the client is coupled to the structure of the navigation. Any change to the intermediate relationships causes the client to have to change.
Coupling? getThis? Ding ding ding. This smell sounds like it can guide me in recognizing where I can eliminate the use of getters as much as possible. The remedy Fowler prescribes is to Hide Delegate:
The move to use here is Hide Delegate (157). You can do this at various points in the chain. In principle, you can do this to every object in the chain, but doing this often turns every intermediate object into a middle man.
Ah – this can hopefully help me limit getters in my real world projects that aren’t perfectly simple, complex, convenient, and plain just right like the examples that are given.
In my recent re-implementation of core parts of The Project in C#, I unconsciously wrote code like this:
IEnumerable query = from d in db
where d.getTitleForInfra().Contains(title) &&
d.getLifecycleCommentsForInfra().Contains(comments) &&
d.getLifecycle().Contains(lifecycle) &&
d.getDirectorForInfra().Contains(director)
select d;
|
and this:
public bool isIn(Room r)
{
return this._history.getRoomForInfra().Equals(r);
}
|
One night, like the Satanic hallucinations the Marine in Doom 3 experiences, the vision came to me:
IEnumerable query = from d in db
where d.titleContains(title) &&
d.lifecycleCommentsContain(comments) &&
d.lifecycleContains(lifecycle) &&
d.directorContains(director)
select d;
|
public bool isIn(Room r)
{
return this._history.roomEquals(r);
}
|
I grant you that these improvements are relatively minor, but the benefits are the same: clients are now coupled to only the class they are using. Also, these lines of code kind of read like sentences too: “… where d’s title contains the title”. If I had made prodigious and conscious use of my variable names, the English would be even more pleasing.
As far as keeping the server objects from becoming middle men, I don’t run that risk here. In the first example, d is of type DVD, which is a domain object. Similarly, _history in the second example is of type EquipmentHistory, also a domain object. They both contain useful domain knowledge, so they aren’t mere forwarders of messages.
Know your refactoring catalog. Many seemingly hot design debates in the industry might actually be recycled from yesterday, and we can all use a reminder. It seems that fashion and bad design are both cyclical.
This entry was posted on July 8, 2008 at 7:38 pm and is filed under Design Issues with tags .NET, C#.NET, code smell, getter, getters and setters are evil, hide delegate, martin fowler, message chains, middle man, programming, refactoring, setter, software engineering. You can follow any responses to this entry through the RSS 2.0 feed You can leave a response, or trackback from your own site.