Sunday, June 11, 2006

Solving Method Contract Problems

In these last days an interesting discussion about the final Java keyword took place in many sites and blogs: take a look here and here.

I don't want to add my opinion about that because everything has been already discussed.
What caught my attention was the following statement in this very interesting blog post by Elliotte Rusty Harold:


It is a general principle of object oriented programming that an instance of the subclass can be used anywhere an instance of the superclass is expected. This is the very
definition of polymorphism. This means that the subclasses must maintain the class invariants and postconditions of their superclasses because client code might be depending
on those invariants and postconditions. Failure to do so is a contract violation. For example, if a Clock class promises that the getHours() method always returns a value
between 1 and 12, then this must still be true for a MilitaryClock subclass’s getHours() method. The MilitaryClock subclass can add a different getMilitaryHours() method that
returns a value between 0 and 23. However it must not violate the rule that getHours() always returns a number between 1 and 12.


I'm a huge fan of Design By Contract principles and agree with Elliotte in many points.
However, what I disagree with is how he solves the problem of maintaining the correct post-conditions on the getHours() method of Clock, that is, adding a getMilitaryHours() to MilitaryClock.

Why do I disagree?

Say you have a Display object for displaying time information through a Clock object, thanks to a displayTime(Clock c) method.
If Display.displayTime(Clock c) calls c.getHours() for obtaining the right hour time, it will not work with a 24 hours based MilitaryClock, because it will always display a 12 hours based Clock even if the actual Clock instance is a MilitaryClock!
Following Elliotte solution, Display should call getMilitaryHours(), but how?
Display doesn't know the actual type of Clock!
Moreover, adding a getMilitaryHours() method doesn't stop the client to use the standard getHours() method! Is this correct? Does the 12 hours based method make some sense for a MilitaryClock?

So, I see two solutions.

The first one: designing a Clock interface and two concrete implementations: StandardClock and MilitaryClock.
The Clock interface will have a getHours() method documenting the weaker applicable post-conditions, that is, an hour value between 0 and 23.
The StandardClock will strengthen the post-condition, outputting only values between 0 and 12.
The MilitaryClock will leave the post-condition as is.
This is safe and doesn't break any contract.
Elliotte could answer that interfaces are bad because don't let you verify conditions, forcing you to simply document them, and implementors to read your documentation.
I should write a whole blog post about this, but for now let me simply say that the value of interfaces is worth the price to pay. Surely.

The second solution: suppressing the getHours() method and implement a Clock.display() method, assigning to clock the responsability of displaying itself whatever time format it use, and let Display.displayTime(Clock c) call c.display().

Maybe Elliotte example was oversimplified, or his solution referred to a situation where you cannot change the base class (Clock), but simply saying that the solution to a "contract conditions problem" is adding another method, is IMHO a bit misleading.

My two euro cents.

What's your opinion about this?

7 comments:

Anonymous said...

Perhaps another solution would be to use "Chain of Responsibility" pattern, that is have different Display handlers that know how to handle a particular type of a Clock. For example:

DisplayDispatcher implements Display {

private List displays = new LinkedList Display();

public void setDisplays(List displays) {
this.displays = displays;
}

public boolean displayTime(Clock c) {
for(Display d: this.displays) {
boolean canHandle = d.displayTime(c);
if(canHadle) {
return canHandle;
}
return false; //or throw an exception
}

...

public class MilitaryTimeDisplay implements Display {

public boolean displayTime(Clock c) {
if(c.getClass() != MilitaryClock.class) {
return false}
((MilitaryClock)c).getMilitaryHours();
}
}

....

etc. for different types of Display "handlers"

Sergio Bossa said...

Hi Dmitriy,

thanks for your answer.

> Perhaps another solution would be
> to
> use "Chain of Responsibility"
> pattern, that is have different
> Display handlers that know how to
> handle a particular type of a
> Clock.
> For example: [CUT]

I see your point, but I think that the "Chain of Responsibility" pattern is better suited for dispatching different responsabilities to a chain of different objects, like what happens with servlet filters.

If you want to implement a "dispatcher" like approach, the Visitor pattern is IMHO a lot more appropriate.

public class Display {

public void display(Clock c) { c.acceptAndDispatch(this); }

public void displayClock(StandardClock c) { //... }

public void displayClock(MilitaryClock c) { //... }
}


public class StandardClock {
public void acceptAndDispatch(Display d) {
// ...
d.displayClock(this);
}
}


public class MilitaryClock {
public void acceptAndDispatch(Display d) {
// ...
d.displayClock(this);
}
}


What do you think about this?

Sergio Bossa said...

Errata:

Obviously, StandardClock and MilitaryClock both implement the Clock interface!

Anonymous said...

Sergio,

Visitor works, but I feel (only my personal opinion) that Visitor is a complex pattern and might introduce unwanted complexity for the problems that are not complex to solve themselves. The example of CoR that I showed deviates from the classic "GoF" structure and uses simpler "Dispatcher" that handles the "chain" itself.

The main point though is that the main principle that I use is: "code to interfaces" where ever possible.

Sergio Bossa said...

Dmitriy said ...

> Visitor works, but I feel (only my
> personal opinion) that Visitor is
> a complex pattern and might
> introduce
> unwanted complexity for the
> problems
> that are not complex to solve
> themselves.

Yes, I agree, it might be more difficult to implement, even if I think its major drawback is that you have to change the Display interface/implementation every time you add a new Clock (but this could be solved using Java reflection).

> The main point though is that the
> main principle that I use is:
> "code to interfaces" where ever
> possible.

Yes, I fully agree ;)

Thank you Dmitriy.
Cheers,

Sergio B.

Anonymous said...

Hi Sergio,

for the interfaces weak constraints in documentation, I agree they are good but maybe not enough, but that's the most we can have actually :-)

For what regards the example of Clock and Display, as long as we don't have a displayTime method which does if/else on the possible concrete type of the Clock paramater, it could be just a matter of taste :-) Regarding the fact we have MilitaryClock and MilitaryDisplay, and StandardClock and StandardDisplay, maybe an AbstractFactory could be a solution.

What do you think?

Sergio Bossa said...

Hi Alessio,

thanks for your answer.

> Regarding the fact we have MilitaryClock
> and MilitaryDisplay, and StandardClock
> and
> StandardDisplay, maybe an
> AbstractFactory
> could be a solution.

Using an AbstractFactory gives you a different solution for a different usage context.

When you have a single Display class and many Clocks, you can display many clocks without changing your display object.

If you have an AbstractFactory with different families of Display / Clock objects, you have to change your display in according to your clock.

So, it depends on the way you want to use your objects, and probably on your "business".

However, given it is acceptable for your business, my answer is yes, an AbstractFactory could be IMHO a solution.

Cheers,

Sergio B.