At first glance your application is made up by methods, many in number and diverse in functionality. It is that diversity that has us make them “huddle up” in teams that share the same purpose, that satisfy the same end goal, or more simply put, that work together to get the “same job done”. Thus we bundle up our methods in Classes since “birds of a feather flock together”. For most programmers, this is pretty much it, but you can go a bit further down and work up a more thorough design.
Creating Flexible Interfaces is the way to go about it.
In Object Oriented Languages, your application is made up of methods grouped up in classes but is defined by messages. The Classes you write control the source code but the messages passed around represent the “living, breathing” application.
When you create your interface take care and separate the Public parts from the Private parts. And the way you do this is by learning what code goes where and why
The Public Interface of you class – just like the name suggests – is composed of all the bits and pieces that you are not afraid to show the world. In other words these methods:
- Expose the application’s intent, or more simply put it’s primary responsibility.
- Are stable and thus are made to be invoked by others.
- Are safe enough for others to depend on them.
- Will not change aleatory.
- Are safeguarded by a “bulletproof” test suite.
The Private Interface on the other hand is composed by all the other methods and as such they:
- Handle all the detailed parts of implementation.
- Can change for any foreseeable or unforeseeable reasons, but do so without breaking your code.
- Are unsafe & unstable and as such others cannot depend on them.
- Are not expected to be sent by other objects.
- Do not require to be documented in the tests.
When you think about the Public Interface, it is the part of the Class that articulates and as such sheds light on the whole responsibilities of your Class. These Class responsibilities should work together to fulfill the single purpose of the Class. The better the methods work seamlessly together, the higher level of “cohesion” is achieved. Code cohesion is good since it helps attain code robustness, reliability & reusability and also increases understandability.
There is no way I can teach you how to discover the public interface of your code. No way to help you decipher a clean-cut way to always identify your “public parts”. It just comes with practice, but that being said there are some guide lines that you could use to help you in your future coding endeavors.
What you want to do is to retain maximum flexibility (or better put – future changeability). And one way to achieve this is by writing only enough code to satisfy today’s requirements. Simpler put – never code forward. Do not try to anticipate what will be necessary in the future.
Why is anticipating bad? Well, in the off chance that you are right (and we almost never are) and “hit the nail on the head” with your prediction, nothing bad happens. On the contrary, the heavens will split wide open, champagne will fall from the sky and we’d be the world’s fastest and most productive developers.
But on the almost certain chance that we are wrong, well now you are limited in your working choices. You either a). undo what you did – which is easier said than done since chances are that other elements of your code might depend on it; or b). try and roll with it – which is almost always a recipe for disaster.
You can also focus on the messages passed between objects and not the objects themselves. And the absolute best way to do this is by drawing up sequence diagrams. Sequence diagrams force you to contour the whole interaction & relationship between your objects – this including the messages they send each other. This will have you take a shift of perspective from asking “O.k, I have this Class, what are it’s responsibilities?” towards “O.k, I have this message, who should I send it to?”
Shifting to a message based focus will lead to the creation of more flexible applications since it changes your perspective from:
Knowing you need a specific Class and then racking your brain trying to decide what that Class should do towards
Knowing you have a specific message to send and figuring out who needs to receive it.
Establish messages that ask for what the sender desires rather than messages that tell the sender how to behave. This has to do with the context that objects expect. The simpler the context the easier are the objects to use and to test since they expect few things from their “surroundings”.
Think about objects like you would think about a mushroom farm. Keep them in the dark as much as possible. This way they will expect few things from their surroundings. It’s this “low expectation” that increases you’re flexibility and choices.
Objects that have low expectations of their collaborators operate on a trust bases. They have a “I trust that you can give me what I want” attitude.
An Interface is all about the “actions” that are allowed. It does not focus on data or how the actions are implemented.
All methods in the public interface are public by design since the whole point of the interface is to be know to the world. Make them stable and dependable.
Employing Polymorphism in declaring interfaces.
Polymorphism – from the greek words “poly” meaning plural, or many and “morphe” meaning shape or form.
In programming, when we say polymorphism we refer to the ability of using methods in more than one way and for more than just one object or data type. To be able to do so we need good, concise, SOLID, abstract methods.And these are just the type of methods you want to find in your interface.
Interfaces are good because they allow you to be more abstract when referencing objects. And abstract objects are scalable objects. They can be easily extended based on future change needs.
They force you to write specific methods that are expected in the implementing class when it implements the interface.
What is does is it extracts the “like minded behaviour” in a group of objects (whether a pair or a whole set) and places it in the “higher level” of that group. This acts as a signal to indicate that these objects should be treated based on the abstract high level commonalities rather than the specific parts.
Design explicit interfaces. Be obvious in your intent. Chances are that other people will want to invoke your methods. They will need to know on which methods they can depend on. Operate on the presumption that all of you class code is public with the exception of what you specifically declare as “private”.