This is the first in a series of posts I will call "quantum leap techniques" - simple counterintuitive things that you can do to step your coding game up to the next level.
When you are creating a system and laying out the way that you will organize its behavior and data, you will undoubtedly find yourself creating layers of objects. We can go over approaches to layering in certain contexts and the specific ways you may decompose a system at a later time.
For now we will cover one very specific aspect of layering - the interface between layers.
Every time one object interacts with another, there is a contract between them - the way that the two objects in the relationship "talk" to each other.
If the objects have a clearly thought out way of speaking with each other, it will be clearer what the responsibility of each object is. This in turn makes it easier for the next programmer who comes across this code to make a change. Because they will have a basic structure to follow, and less information that they will have to synthesize and keep in their short term memory.
If the relationship between two objects is allowed to become muddy, responsibilities will be less clear as well. This makes it much more difficult for future maintainers to modify.
Taken to the extreme - there are no lines of responsibility. In this case the fact that the two objects are separate is totally irrelevant - since we have given up any benefits we might have otherwise gotten. In fact having separate objects at this point just makes things more confusing.
So what's the solution??
I'm glad you asked.....the ultimate solution is ongoing diligence, making sure to keep responsibility clear between objects.
More concretely though - to keep the lines between objects clear and well defined really requires focus on the interface between objects.
Yet more concretely - lines between certain objects need more attention than others. For example, a very clear and controlled line should be drawn between display/presentation and business logic. In places like this where you would like to draw a clear line, or just anywhere you would like to make sure focus is placed on separation a useful tool is to code to an interface (the actual language construct).
That is to say, the client object should access the its dependencies only through an interface, avoiding any dependency on the interface's implementation(s).
Why this helps is because the exercise of writing an interface focuses attention on the method signatures - that is it is more difficult to be distracted by implementation.
The result of this is more clarity around separation and placement of responsibilities.