This post originated from an RSS feed registered with .NET Buzz
by Udi Dahan.
Original Post: On the factoring of interfaces
Feed Title: Udi Dahan - The Software Simplist
Feed URL: http://feeds.feedburner.com/UdiDahan-TheSoftwareSimplist
Feed Description: I am a software simplist. I make this beast of architecting, analysing, designing, developing, testing, managing, deploying software systems simple.
This blog is about how I do it.
Chris Mackenzie's take on "Implementing an Interface in the UI, or the 7-layer system" is based on having an interface for each of our entities in the system. His example focuses on a Person entity, thus having an IPerson interface. Now, the issue of having UI elements implement these interfaces is interesting, but secondary. First, we have to take a look back at what separating an interface from an implementation entails.
A "Person" is more than just their data - our IPerson interface should also contain methods for manipulating Person objects. I would even go so far as to say that we should avoid using the "set" part of properties - all manipulation should be entirely method based. I know that this is OO zealotry, but I've found that, more often than not, large blocks of code are written behind "set" properties. This can be easily taken too far.
So, what I propose is to refactor our IPerson interface into 2: an IPersonInfo interface which contains the data-only aspect of a Person as property "get"s only, and an IPerson interface which inherits IPersonInfo and contains the behavioral aspects of a Person - the methods.
What is the good for?
Well, for those cases where we will want UI controls to implement our IPerson interface, it would seem odd to have such a control need to implement a "GiveTwoWeeksNotice" method.
Also, since the IPersonInfo is, in essence, read-only data, we can safely pass it anywhere without worrying that the data in our object will be corrupted somehow.
There is one thing to watch out for, though. The IPersonInfo is really a data transfer object, something of an anti-pattern within a given application boundary. We need to make sure our application doesn't regress into procedural manipulation of the data. I don't think there will be too much danger of that for developers used to separating interface from implementation.
So, to end on a positive note, the IPersonInfo can also be effectively used at application boundaries - between client and server for instance. As well, when it comes to persistence, all we're really interested in is the data - no need to use an IPerson when an IPersonInfo will suffice; but one can consider persistence to databases (and the like) as a kind of application boundary too.