Originally posted by Fred Barnes:
Could someone explain the benefit of placing the lock and unlock methods in the DataInterface when they are only required for remote connections? Is there anything wrong with creating a DataInterface with all the public methods of Data except lock and unlock.
Yes. There is a lot wrong with that.
Let me answer your question by taking a step back and look at the nature of inheritance. (Don't despair, I will get to the point soon enough; this is important).
We all know that inheritance models an "IS-A" relationship. For example, a java.zoo.Cow "IS-A" java.zoo.Animal. A slightly more formal way to look at it is to say that a subclass should satisfy the
substitution principle: wherever you can use an instance of the base class,
you should be able to use an instance of the subclass. This applies to interfaces as well as classes.
All the rules of the
Java language with regards to inheritance, overloading, narrowing of exceptions in subclasses and so forth serve to satisfy the substitution principle on the language level. What is much less appreciated by developers is that
this is only part of the story.
YOU will have to satisfy that the substitution principle is satisfied on the implementation level as well as the language level. This is one of the prerequisites for good OO design.
In particular -- see, I'm coming to the point after all -- "RemoteDataInterface extends DataInterface" means that you should be able to substitute RemoteDataInterface implementation wherever you use DataInterface implementation.
But wait. To work properly with remote implementations, you need record locking! So, unless you add lock() and unlock() methods to DataInterface, you cannot possibly satisfy the substitution principle.
Let's look at it from a purely practical point of view. If you would do what you're suggesting and leave locking out of DataInterface, you would effectively end up with code like
It doesn't have to look this way at all, but it would boil down to this whatever you do. And it is horrid code.
Polymorphism was introduced exactly to do this kind of thing -- vary the implementation for an action (method) depending on the type. When the lock methods are in DataInterface, you would simply say
If db happens to be local, this call would do nothing. That's fine. You don't care. Polymorphism and the substitution principle ensure that the right thing happens when you call lock(), whatever the right thing might be.
A third way of looking at this -- and then I'll shut up -- is that you misunderstand the nature of DataInterface. It is not a "local database". After all, a "remote database" IS-
NOT-A "local database"; the inheritance is all wrong. DataInterface is the interface implemented by a "database of any kind". And, of course, as befits an interface which is completely agnostic about the type of database it implements, it has the lock() and unlock() methods that are needed in a networked multi-user implementation.
Let's verify the relationships: a "remote database" (RemoteDataInterface) IS-A "database of any kind" (DataInterface). Check. A "local database implementation" (Data) IS-A "database of any kind" (DataInterface). Check A "remote database implementation" (RemoteData) IS-A "remote database" (RemoteDataInterface). Check.
HTH
- Peter