3

Perhaps I should have picked a better title, but anyway...

Basically what to do with two or more implementations that have the same public interface, but they are meant for slightly different purposes having a slightly different behavior?

For example let's say a proxy class that uses the same public interface of the original class but with important changes in its behavior.

interface MyTest
{
    getSomething() : MySomething;
}

interface MyTestImmutable (extends MyTest ?)
{
    // same interface, but in this case the following method
    // is supposed to return a clone of the stored MySomething instance
    getSomething() : MySomething;
}

Thanks

  • I realized already that this has a very obvious solution :D but answers are welcome anyway – user131689 Jul 15 '14 at 5:52
2

The point of interfaces is to hide the implementation differences between different ways of achieving the same visible result.

In my view, if two methods do the same thing, but one is slow and reliable while the other is fast and unreliable, or if one returns a clone and the other always returns the same object, etc., then those are not the same things. They should more often be two different methods on the same interface. You can express the degree of relatedness by choosing similar names, e.g. something like getProbablePrime(int bits) vs. getPrime(int bits), but if the difference is something that the caller has to take into account, then you shouldn't hide it.

2

Interface design should be primarily governed by the need of the user, not capabilities of the implementation. And the user does not want to care about the implementation details. Code using the interface should be able to use either implementation without special-casing for "variants" of the interface.

If on the other hand there are disjoint sets of users for each implementation, they probably shouldn't be using the same interface. They can't use the other implementation anyway, so they can just use the concrete type and YAGNI applies to having an interface at all.

If there is code that may use either and some code that only works with one implementation, than the interface should only cover the needs of the universal code and the specific code should use the concrete classes. Or subinterfaces if there is still some genericity. Or desire to mock the implementation for tests (It often isn't worth mocking each and every class, just those that interact with outer world. And not always even those. I rarely mock anything as in my domain it is usually easier to just prepare suitable environment for the tests).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy