I’ve been thinking a lot about interfaces lately. When I’m writing code, I often find myself slipping back and forth between several ways of thinking about interfaces. And if I’m not careful the result is a big mess!
The first way of thinking is “interface as contract”, and the second is “interface as behavior”, which is what we’re usually thinking of when we’re using interfaces to do modeling. The third way is “interface as marker”. (This brings new meaning to the phrase “overloaded interfaces!”)
Anyone who has used a C# or Java compiler is familiar with the first way of thinking about interfaces. Basically, if a class implements an interface, then it must provide implementations for any of the methods defined in that interface, so the interface functions as a sort of contract to code.
The second way of thinking about interfaces is related by an assumption. If you think that OO is a good paradigm for program design, then the choice of members in your interfaces will correspond to the behavior of the system that you’re modeling. In other words, the contracts specified by your interfaces will be organized by “is-a” and “has-a” relationships in the real world system.
The third way of thinking about interfaces is less often discerned, but there’s a great example in Java. If you want to mark a particular class as being serializable in Java, you make the class “implement” the java.io.Serializable interface. I always thought that was really funny, because you don’t actually have to implement any methods; in fact, there are no members defined in the interface at all! It’s just there to signal to a marshaling service that it’s OK to serialize instances of the class.
So if the first way of thinking about interfaces is really just about the mechanics of code writing, and the second way has to do with modeling, then what exactly is this third way? The Java example has no contracts and has no use in modeling; just ask your friendly neighborhood banker if their computerized account tracking system has serializable customers if you don’t believe me.
From this point of view, I really like what they did with serialization attributes in C#! Instead of implementing an interface, to make a class serializable you mark it with the
[serializable] attribute. I think that is potentially much less confusing. If I am playing multiple roles in a project, I sometimes catch myself putting service interfaces in my models, much to the puzzlement of colleagues (and of myself six months later), but it made perfect sense at the time because “of course a customer has to be ISavable to the IDatabase.” Ugh. Try telling that to a banker.
An interesting article on the performance of using interfaces versus using attributes to mark methods can be found here: http://www.ddj.com/dept/windows/184407888. It is a bit dated already, and I intend to repeat the experiment to see if the results still hold, but it basically boils down to the familiar problem: interfaces as annotations are probably faster than attributes because attributes are potentially much more flexible and thus naturally come along with a bigger search space to loop over. I wonder though if they couldn’t implement some fast lookup tables from attributes to attribute targets.