Showing posts with label interface. Show all posts
Showing posts with label interface. Show all posts

Sunday, August 15, 2010

Version-ed interfaces to refine a product specification?

Warning! This is just an idea. You will have to prove its value yourself!

Interfaces as product specifications
Nothing new here.
An interface defines some behavior that can be implemented by one or more classes.

Interface methods and properties
  • define inputs and outputs (interfaces as arguments and return types),
  • may have annotations (attributes that means something), and
  • have documentation (e.g. with references to specifications and/or examples).
Version-ed interfaces
Here comes the first idea.
Lets say that a product release of some features are to be version 1.
Here is what a (wacky) coder could have produced to materialize one of those features:

The 1st idea is to name the interface with a version number.

"Thats just insane! Why would you do that! ....."

Usually we don't change the name of the interfaces and it works fine, but lets see the next Foo specification:

This certainly is a bit strange. Apparently, now a Foo does not drink stuff from the bar, but only buys it. Definitely, strange.

This version 2 interface is renamed, specializes the previous interface by inheriting it and redefines the Bar method by using the new keyword.

Thats 3 things that you normally do not see:
  • The rename: It will have no effect on existing version 1 implementation, but require your implementation to be changed when it is to support version 2.
  • The specification inheritance: This is a very explicit way of tracking the specification history that might suite coders just fine.
  • The redefine with new: The Bar signature did not change, but the textual specification did. If the interface was named IFoo and the text just changed between version 1 and 2, then the compiler would eat everything just fine, but the version 1 implementation would still make Foo drunk whenever he went to the bar.
Implementation changes
Here is how a version 1 implementation could look:

The version 2 could be:

A tiny difference, but a fatal one when on a date!


Wednesday, June 3, 2009

Feel the bliss of the design pattern InstanceRegistry

The InstanceRegistry pattern values loose coupling between objects. This pattern is as simple as the Singleton pattern, but with the InstanceRegistry pattern your objects stay simple, replaceable and testable - even you manager objects.


Your choice: Tightly or Loosely?

"Until somone changes my mind, I will always use Pete Bong for plumbing, Tira Donk for carpentry and Rolli Streak for decorations." - Foo

Above statement from object Foo raises the following dependency concerns:  
  • Foo's abilities cannot be tested without Pete Bong, Tira Donk and Rolli Streak,
  • Foo's abilities cannot be used without Pete Bong, Tira Donk and Rolli Streak, and
  • Foo needs to changed, if Pete Bong, Tira Donk or Rolli Streak needs to be replaced.

"Whenever I need handywork done, I just lookup an available plumber, carpenter or decorator."  - Bar

In constrast to Foo, above statement tells us that Bar has the following dependency strong points:
  • Bar's abilities can be tested with any plumber, carpenter and decorator,
  • Bar's abilities can be used with any plumber, carpenter and decorator, and
  • Bar is satisfied to use an externally defined plumber, carpenter and decorator.

Now, should you at this point be in doubt which object to prefer - Foo or Bar - then I fear that the rest of this entry does not have more to offer. On the other hand, if you now are thinking in the lines of 'I like a Bar, but how expensive is it?' then hang on for the bliss...

Your Battle: Foo vs Bar

Imagine Foo would have code that looked something like this:
PeteBong plumber = (PeteBong) PeteBong.getInstance();
plumber.buildSomething();
This kind of code is pretty common, causes the previously mentioned concerns, but also has the very nice feature that the reference to PeteBong is fetched when needed. Last mentioned feature is possible, since PeteBong is globally available as a static reference via the Singleton pattern. 

Now a Bar version of this code uses the InstanceRegistry pattern:
IPlumber plumber = (IPlumber)InstanceRegistry.getInstance('IPlumber');
plumber.buildSomething();
or even better
IPlumber plumber = instanceRegistry.getInstance<IPlumber>();
plumber.buildSomething();
Here Bar is tightly coupled to an InstanceRegistry that is basically just a map between ids and object instances. Whether this id is a string or a type is up to you, but in the later version you have the ability ensure loosely coupled objects by only accepting interfaces as ids. Please note that the getInstance method simply looks up a reference to an object that has registered itself in the InstanceRegistry and, thus, become globally available to other objects. The InstanceRegistry does NOT create new instances.

Since Bar is using the InstanceRegistry pattern it has the following properties:
  • Bar can be tested with mock up implementations of its dependent interfaces e.g. IPlumber,
  • Bar can be used with any implementation of its dependent interfaces e.g. IPlumber, and
  • Bar is designed work with objects that may change implementation, but not specification. 
Your Exercise: An InstanceRegistry implementation

Here are some considerations to do when creating an InstanceRegistry implementation. I hope the missing implementation details will become some nice discussion subjects, and that you will have fun making this pattern yours.
  • Decide whether to make an InstanceRegistry interface or not, and imagine how it would be used,
  • Decide how to pass your InstanceRegistry implementation reference around,
  • Decide on methods and arguments for adding and removing the object instances that can be be fetched via the getInstance method, and
  • Decide on other useful methods that the InstanceRegistry might have.
Enjoy the bliss, give feedback and start discussions.

Thanks!