We're trying to design an API that will go out to external customers. I've jumped into a new API product that has been 80-90% designed and written, and I'm trying to decide whether or not to keep the few interfaces that have been written. I'm wrestling with the 'program to an interface, not an implementation' issue.
FYI, my perspective is keep it simple, concrete, program to what you know now, don't have interfaces where there is only one implementation, etc. In the last couple years I have repeatedly inherited projects that seem to me to be very overly complicated in their design. We refer to these as 'atomic baloney slicers' when all you need is a simple knife. So I am leaning towards eliminating the interfaces and keeping the single concrete implementations we have.
On the other side, there is the difficulty of trying to plan for an unknown future (version 2?) and unknown usage by the customers. For instance, our concrete implementation is MyProduct. They may want to create a FooCompanyProduct class, and then handle FooCompanyProduct and MyProduct objects together. But the problem is, we don't know how to define the contract of the Product interface in that scenario. Right now, it seems like ALL the methods we think should be in the proposed Product interface, are already in the MyProduct class.
After our last design session, we decided to get rid of the interface, push a lot of the methods in the MyProduct class into an AbstractProduct class, which the customer can then extend. Another facet of the issue is that the custom classes the customer may want to make, must be composed of our components. Maybe that will help explain the decision on the AbstractProduct class. It's hard to explain it w/out getting into trouble divulging company secrets and all that.
I've been reading design articles on this issue and have just been going round and round on it. Honestly, a lot of those articles are hard for me to fully digest in an abstract sense, even with examples. I think I understand the benefits of interfaces with multiple implementations. Maybe I just need to learn the hard way by doing it wrong, but I'm trying to avoid that.
Hope that didn't ramble too much. Thoughts? I wish there was a preview option on these forums
Right now, it seems like ALL the methods we think should be in the proposed Product interface, are already in the MyProduct class.[/QB]
Interface-Segregation Principle (ISP): Clients should not be forced to depend on methods that they do not use.
Look at your class and ask yourself: "Does every object that is a client of MyProduct need to know about all the methods on MyProduct?" If your class has multiple categories of client objects, then each client should manipulate MyProduct through an interface that is tailored to the client so that the client knows as much and as little as it needs to. MyProduct then needs to implement all those interfaces (i.e. there could be more than one).
Dependency-Inversion Principle (DIP): a. High-level modules should not depend on low level modules. Both should depend on abstractions. b. Abstractions should not depend on details. Details should depend on abstractions.
DIP depends on interfaces/abstract classes. It cannot work without them. Unfortunately they have to be the correct interfaces going in the correct direction.
Open-Closed Principle (OCP): Software entities (classes, modules, function, etc.) should be open for extension, but closed for modification.
Without an interface your customers will have to inherit from MyProduct to create FooCompanyProduct. Using an interface (or more) also gives them the option of creating FooCompanyProduct from scratch, or (more likely) by containing a MyProduct instance and delegating to it (Refactoring: Replace Inheritance with Delegation).
Having an interface is not all about code reuseability. I have only a single implementation but still I have interfaces. This allows me to work on my program one section at a time. So while I am working on the db side, I can compile and compile again the db part but I never have to compile the other side. If I did not use interface, then i would have to compile everything.
I don't have interfaces with methods designed for the future. The interfaces only contain methods that are being used.
This also helps me to keep track of which methods called externally and which are called internally since there are considerations sometimes.
There are really a lot of benefits to this. If you cant see a reason to use an interface as opposed to passing your objects around, then perhaps there is no reason. But maybe you should look harder too. This is not something that is done for the sake of doing the right thing. It makes your life easier. But it is also true that sometimes you have to learn to appreciate this the hard way.