Monday, October 22, 2007

On IClass (anti-)pattern

I'd been re-reading this post by Sidu and the comments on it. I had to do exactly similar to IClass anti-pattern for one of the development effort. And I think having IWhatever completely makes sense for the current state of affairs in my development environment.

While it's unfortunate, most of the time, to have an Interface for just about every class in the code-base, It does have certain uses in some situations (apart from the (IoC) frameworks which mandate you to have them) like:
  • Support parallel development.
I will define parallel development as a situation where there are many components involved in developing a software and your component (or module or whatever..) and it's arbitrary version has to support other components (and their integration tests depending on your environment). For example, for something as important as (so called) service layer in an Enterprise application you need the Interface with single implementation at one time, it might just be a 'placeholder implementation' for a dependent component while the new version being developed parallely. It just makes sure that there is something to hold the place which can be tested easily. This is one more learning from distributed development, you're not alone developing it man!
  • When using Generative development methods
If you use code generators heavily, say, most of your code-base is generated out of models (UML, BPMN, BlahL ...) then depending on the generation pattern you'll find interface for just about every implementation (or other way around for EMF generator - one implementation for each interface). This is necessary as you might want to customize forward engineering by overriding parts of generated artifacts.

Most of the Eclipse code does have this pattern, for every class there's IClass. For Eclipse, In my opinion, it is justifiable (to some extent) to have them considering it is a development platform rather than just an application. However, I would be more than interested to know conceivable reasons to have those IInterfaces which I might be missing.


Ed Merks said...

To support multiple inheritance, interfaces are necessary. It also seems nice to use a factory pattern where the implementation classes are internal (and perhaps even private or inaccessible) while the APIs are public. In any case, EMF supports the "Suppress Interfaces" property in the GenModel for those folks who don't want separate interfaces and implementations.

Nirav Thaker said...

Thanks Ed,

Nice point! I totally missed that basic need. In Java, Interfaces are indeed needed to simulate multiple inheritance, Which might be bewildering to lot of developers developing in funky languages supporting multiple inheritance out of the box.

Sidu said...

While I agree with much of what you've said, Nirav, multiple inheritance is evil if you allow the inheritance of state from two or more classes to an inheriting class - which is why Java does not support multiple inheritance a la C++ style. You're best off doing mixin style multiple inheritance (Ruby modules, for example) where only behaviour is inherited - but Java interfaces provides a very half baked way of doing this.
So I'd say languages like C++ supporting the kind of multiple inheritance it does is a Bad Thing rather than a good one.

The other point I'd like to differ on is the use of IClass to help distributed development. I've been on plenty of distributed projects, one where the IClass was mandated by our customer's design guidelines. I've found no advantage to be had from it. If it's contracts you wish to define, I'd suggest doing so using unit tests instead of an interface and refactoring your way from implementation A to implementation B. Whether A's and B's implementations are changing in parallel or in sequence matters little so long as your build passes.