Software object systems, are a collection of objects, connected by relationships. Typically, objects are connected by structural relationships. I can think of a dozen real-world analogies when I'm writing code. When I think of these analogies, I'm thinking about the physical structure of the buildings, cars, engines, books, anything really, that inspires my software design. This is why object-oriented software uses the object as the fundamental unit, not the behaviour. We don't focus on the behaviour of our software when we're designing it. At least it isn't the first thing we consider when starting a new project. I don't think “what are the major behavioural components of this system”? The first thing that comes to mind when building from scratch is something along the lines of “what are the fundamental data structures I'll need to make this work?”. Maybe this approach is backward.
Emphasis on the data structures taking precedence over how the software works – the moving parts of the system – is hard to overcome because we're so used to making analogies to real-world objects and their properties. This is an essential feature of our brain – if you cannot distinguish between dangerous objects and irrelevant objects or beneficial objects, your chances of survival are slim to say the least. We differentiate between objects in the real-world based on their attributes – the things we can see. We recognize objects by nothing more than their physical attributes – their shape, their colour. My desk I work at everyday stands out relative to every other desk in the office because of its attributes. The monitor, the coffee mug, the unsorted pile of paper – all things that make the desk unique and recognizable.
This isn't to say that we don't make analogies with regard to how things function, the way they move or produce output. My desk, of course doesn't do anything very interesting, or anything at all for that matter. It just sits there – I have no real need to compare what it does to anything else. My car, on the other hand, has several interesting characteristics other than its less-tangible attributes. I can use these to make comparisons - to other cars, or other objects. The car moves – hopefully in more than one direction. It has a maximum speed and it turns. I could go on, but that would be overkill. Clearly, we're capable of making behavioural analogies too. The question is, why do we favour the structural when it comes to software design?
As we know, software is a host of objects connected to one another. I'm not sure there is as much a distinction between structural and behavioural aspects as we might think. The structure of software objects is like glue - it prevents an objects from becoming unraveled and going rogue in the system. When we're thinking abstractly, we're thinking that structure equals order. If we could only build the perfect foundation, we could add the required functionality on top. Everything will work better than it would had we not built a solid base. I'm not sure this is the correct view to take.
My reasoning is simple – interfaces describe what an object does, and suggests some structural attributes the object might have, based on its name. Interfaces are concrete in their behavioural descriptions and tentative in their structural descriptions. This is because interfaces give all the necessary details for implementing the interface methods – the behaviour. If the interface has a good, descriptive name, you can glean some potential attributes that support the implementation. The objects attributes aren't part of the interface contract whereas the operations are. This is important, I think, for at least some degree of implementation freedom. Whats really important with interface connections is that clients get what they expect from their suppliers.
Suppose we've got an IReader interface that requires a read() method be implemented by any objects that provide the interface. The read() method is supposed to return data. How it does this, exactly, is up to the implementation. Maybe the data is read from a file, maybe from an attribute stored in memory, maybe from a network connection. These are all implementation concerns, not that of the interface. The interface serves as a connector, putting the emphasis on what that implementing object does. The client object knows what it needs, in the case of the IReader interface, it needs an object that can read data.
So how does thinking in interface connections result in better software? I think it takes the focus away from the structural properties of objects and places it on the behavioural descriptions. Objects still have attributes, even when we're emphasizing the interface connections. However, these are more closely tied to the implementation than the design. Connecting objects by what they do is how you connect objects by design instead of by implementation.