Intention Revealing Interfaces or Car.FuelInjectionSystem.FuelInjectionRate.Increase()
I was having a discussion with Josh Smith about my upcoming article in MSDN Magazine on enterprise patterns with RIA Services. It’s basically a deep-dive into the technology that goes beyond the Drag-n-Drop demos you’ve seen so far. Josh’s feedback was generally positive but he had one comment on my section on Domain Models and Intention-Revealing Interfaces. Here’s the section in question
…[quoting Eric Evans’ Domain Driven Design]
If a developer must consider the implementation of a component in order to use it, the value of encapsulation is lost. If someone other than the original developer must infer the purpose of an object or operation based on its implementation, that new developer may infer a purpose that the operation or class fulfills only by chance. If that was not the intent, the code may work for the moment, but the conceptual basis of the design will have been corrupted, and the two developers will be working at cross-purposes.[ (Evans, 2004) pg 246]
To put it simply, by explicitly naming the function for its purpose and encapsulating the logic (along with a few comments to make it clear what’s happening), I have made it easy for the next guy (even if the next guy is me 5 months from now) to determine what is happening before he even goes to the implementation.
Josh’s comment:
So what you’re saying is that I should name my functions according to what they do and write relevant comments? Seriously?
I had many similar moments when reading Eric Evan’s book where my response was “well d’uh”. But I got to thinking, how often have I seen code that doesn’t follow this simple rule. To make it patently obvious let’s look at some code that will make a car accelerate:
sCar.FuelInjectionSystem.FuelInjectionRate.Increase()
What’s that, you have an electric car okay:
switch(sCar.Engine.EngineType)
{
case(EngineType.InternalCombustion)
{
sCar.FuelInjectionSystem.FuelInjectionRate.Increase();
}
case(EngineType.Electric)
{
sCar.Motor.Battery.Amperage.Increase();
}
}
You’re on your own if you have a Mr. Fusion powered car. I have no idea how they work (although according to FuturePedia the Mr. Fusion doesn’t actually power the car only the Flux Capacitor). But I digress, as the consumer of the car API, I really don’t want to be concerned with fuel injection rates or battery amperages. Please don’t get technical on me and explain that it’s actually wattage that is adjusted on the battery not amperage or whatever snide remark you have regarding the accuracy of my functions. That’s the point of this post because of the car’s design I don’t have to know how it’s done. And neither should the consumer of your car’s API. It should be a simple call:
//look at that!
sCar.Go()

That is the point of the intention revealing interface. Instead of making your consumers have intimate knowledge of the innards of your system to make it work, provide them with a simple interface that tells them exactly how to make it do what they want to do.
It may be obvious when you read “explicitly name the function according to its purpose”, but following that advice tends to be less commonplace than it implies.