(In the context of .NET for what its worth)
I tend to not use inheritance and rarely use interfaces. I came across someone who thinks interfaces are the best thing since spit. He uses them everywhere. I don't understand this and hence the questions that follow. I just want a check on my understanding of interfaces.
If you are using interfaces everywhere, I'm assuming you can predict the future, your app requirements are nailed down and nothing will ever change in your app. For me, during early development especially, interfaces become a drag. The app is very dynamic through its life. If you need to subtract or add members to the interface, lots of stuff will break. The guy above says he creates another interface to handle the new member(s). Nothing breaks.
Isn't that composition? Why not use composition without interfaces? More flexible.
How does he handle the case where a member must be subtracted from the interface? Basically he doesn't. Things just break and that is great because now you can see all of the affected areas and fix them. Instead of figuring out more elegantly where all of the related code paths are, we should just rip out parts of classes through brute force?
I think of a software application as a graph. A complete graph is the worst case, having n(n-1)/2. This means every class talks to every class. A confusing spider web. n-1 is the best, in which their is a strict hierarchy of communication. Adding another interface just to compensate for a new needed member adds a vertici to the graph, which means more edges and a stronger realization of the n(n-1)/2 equation. Composition without interfaces is more like mixins. Only select classes use particular methods. With an interface, all classes are forced to use members, even if they don't need them. The composition/mixin approach doesn't add new unneeded edges.
"The guy above says he creates another interface to handle the new member(s). Nothing breaks.
Isn't that composition? Why not use composition without interfaces? More flexible."
You seem to be thinking of composition in terms of inheritance, as in, "I'll inherit all of these capabilities into this one object to do this job." That's a bad way to write code. It's like saying, "I want to build a skyscraper, so I'll learn every job there is to know, from how to create the blueprints on down to how to poor the foundation and install the lighting..."
Think of composition instead in terms of separate objects that each perform a single task. To do a complex job, I can now rely on these separate objects to perform their individual tasks. It's like hiring the architect and construction crew to build the skyscraper. I don't need to know in great details how they each do their job, just that they can do it. In code, this means injecting dependencies into an object to perform a complex tasks instead of inheriting.
So where to interfaces fit in? They're the contract between the individual objects. They allow you the ability to not care about individual, concrete implementations. They allow you to speak a common language with a bunch of objects that share the same responsibility, but may actually have different implementation. The interface becomes an abstraction to the object performing the task. I don't need to know how every single guy with a hammer works, just that he knows how to HitNail().
When you begin to compose complex system of code with lots of small classes that have single responsibilities, then you soon learn that you can run into serious problems if you rely too much on the concrete implementation of a given class, and that class begins to change... So instead of relying on the concrete implementation, we create an interface - an abstraction. And we say, "I don't care how you do JobX, only that you do it."
There are other benefits to interfaces like testing, mocking, etc... But those are not the reason to code to an interface. The reason is to create a system of code that isn't dependent on specifics and thus highly coupled to each other. This is why, with your graph thinking brain, you should be afraid of coupling a bunch of concrete classes to each other. Because changes in one of those classes will cause a ripple-effect.
When you couple yourself to an abstraction instead of a concrete class, you limit the coupling. You say, I"m only going to be coupled to the contract we both agree on, and nothing else." And if the class implementing that contract changes its internal way of completing its task, you don't care, because you aren't relying on a non-contract property or method. You're relying only on the agreed-upon contract.
The primary use of an interface is to allow the variation of implementation allowing code to be switched at runtime. There are a number of reasons/rationale for doing this.
In the past some have argued that every class in the system should have an interface, but this is widely recognized as overkill. Interfaces are now used where instances of classes either can change as part of the system operation (to represent state): GoF patterns like Strategy and Command capture this use, and/or parts of the system need to be replaced for testing (ie. dependency injection). If developers are following test-driven development practices the key infrastructure objects will have interfaces. This allows tests to make "mocks" of these objects to test the system's flow-of-control. There is a relationship between this use of interface and the Liskov Substitution Principle (one of the principles of OO design)
A further use for interfaces which is less concerned with what is available to the caller, is the marker interface. Which is a way of associating metadata with the class definition. This may affect how the system views the object (for example allow it to be Serialized) or it might just serve as documentation.
Interfaces don't force classes to use methods. They force implementing classes to implement all methods, but that's a different matter.
I like the way that interfaces separate out API from implementation. Admittedly this is also done with access modifiers, but interfaces make it clearer. More importantly, interfaces also make mocking easier - which means that you can unit test the classes which depend on the interface even before you've ever implemented it.
And yes, this means I often end up with an interface which only has a single production implementation. That isn't a problem in my view, because I've gained testability.
On the other hand, I don't write an interface for every class. I like to write interfaces where an object is essentially providing a service - authentication, data access etc. Plain data objects (even with significant behaviour) aren't as useful in terms of interfaces, IME.
If you want to understand when to use interfaces, and what is their use, I think you should take a look at the book: Head First Desing Patterns.
This is the book that really helped me understand what is so cool about interfaces.
Before reading this book, I knew what an interface was, but I had absolutely no idea about when should I use them.
I think that you describe there top-down design method.
You don't have to do it, but sometimes he really help.
Interfaces make the most sense to me in the context of dependency injection and IoC frameworks. I like the idea that you can define a set of behaviors (methods) and "guarantee" those behaviors through the implementation of an interface. Now you can plug whole new functions into an existing system with a single assembly and a config file update.
Effective design of interfaces does require a good deal of forward planning, and I find they are most useful in the context of large systems and frameworks. When they're useful they're really useful. A few of my favorite:
IComparable
(YOU decide how your objects compare against each other)IQueryable
(LINQ anyone?)IDisposable
(keep yourusing
statement handy)