SOLID
Single responsibility
The single responsibility principle[Robert C. Martin] describes a way of developing your software,
specifically in the object orientated world, what a module should do or 'who the module should effect'.
If we follow the separation of concerns[Dijkstra], which essentially means to break a class or module
into 'what it concerns', then the next issue is what do we mean by concerns?
Robert C. Martin
brings in the notion of the principle being about people.
In the highly modular, large and unbelievably complex software of today at no other time has this principle become so important. I could not put it better than the following
from Robert C. Martin:
You want to isolate your modules from the complexities of the organization as a whole, and design your systems such that each module is responsible (responds to) the needs of just that one business function.
This is the reason we do not put SQL in JSPs. This is the reason we do not generate HTML in the modules that compute results.
Gather together the things that change for the same reasons. Separate those things that change for different reasons.
Open/closed
This principle originally comes from
Bertrand Meyer
who stated:
Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification...
this now seems a little outdated with the undertanding being that a module
should be open for expanding (having new properties, functions...) but closed when
management had 'signed off' and the module could no longer be altered.
This seems a little counter-intuitive and is the restrictive Waterfall method.
Robert C. Martin
argues :
You should be able to extend the behavior of a system without having to modify that system.
He, also, argues that the many coding authors write pluggins for Minecraft, Visual Studio, Eclipse etc and that they have proved that
it is possible to write code that can follow the open/closed principle.
A beautiful example, by
Robert C. Martin
which shows the modern approach, which is to abstract any definites so as to ensure they can be altered without changing any of the
existing code.
Therefore, when your team lead says to refactor (then it's too late!) and when you refactor create an abstraction for your current requirements
with 'an eye for the future' and ensuring that you could add to you abstraction without changing any of the existing code.
Liskov substitution
The
Liskov substitution principle
is defined as:
If S is a declared subtype of T, objects of type S should behave as objects of type T
are expected to behave, if they are treated as objects of type T.
The Liskov substitution principle takes a little time to understand but in essence a function or method of a module should
not do something unexpected.
For example: if a base module with an Add function was implemented without throwing an exception, then all the
clients of the base module don't expect an expection to be thrown. But, if I decide it's good practice to throw an
expection in my implementation, then I've broken the Liskov principle and the existing clients won't know about my 'perfect'
implementation and will not have catered for the exception. The results disasterous the application will break somewhere else
and in a large application the trouble-shooting of the problem could take a lot of resources and time. The 'fix' may cause
other problems as the developers don't know where the actual problem lies and may refactor existing code, which, well,
has now also broken the open/closed closed principle!
Interface segregation
The interface segregation principle is simply:
Clients should not be forced to depend on methods that they do not use.[Robert C. Martin]
I'm as guilty as any developer of writing 'fat interfaces' and it's sometimes not easy to concoct an interface that doesn't
become non-cohesive.
Martin Fowler
brings in the notion of the
RoleInterface
which quite succintly solves the problem but requires writing interfaces for every role.
Robert C. Martin
requires multiple inheritence or the use of the Adapter pattern which can turn out quite ugly.
This is one of the most obvious of the SOLID design principles but seems, the hardest to achieve, with no really solution
apart from (I suppose) try to keep you interfaces relevant (to the role) and as small as possible.
Dependency injection
The final principle, dependency injection has implications structurally from the open/closed and Liskov substition principles.
From
Robert C. Martin
...The structure [open/closed and Liskov substition] that results from rigorous use of these principles can be generalized into a principle all by itself.
I call it 'The Dependency Inversion Principle'...
The principle is an effort to prevent 'Bad Design', which are:
- Rigidity: The inabilty to change the system.
- Fragility: When a change is made, the system breaks in unexpected places.
- Immobility: Repeatablity of any part of the application isn't possible without disentangling a mess of code.
- High level modules should not depend upon low level modules. Both should depend upon abstractions.
- Abstractions should not depend upon details. Details should depend on abstractions.
Summary
After writing this short article I realised that the HTML formating and background PHP that produce this page have violated
most of SOLID. It would take a little effort to correct this and sometimes I find myself in overwhelming pressure from
customers to finish a project as quickly as possible. They have no care for what patterns, principles or methods I use,
they want they're software system up-and-running as soon as possible. These days it's so easy to copy (ctrl C) and paste (ctrl V)
and refactor. I've even been told by some large high-tech banks to copy and paste someones code into whatever I'm working on.
Sometimes I argue, that it violates SOLID which is one of the questions they asked me to land this contract but they look at
me non-plussed and instruct me to 'get on with it' (I've even been threatened!).
The long and the short of it is, that if customers want good, scalable and stable software then they have to agree to use SOLID
and the inherit extra resources and time it takes.
References
wiki
Single responsibility wiki
Single responsibility Robert C. Martin
Dijkstra
Parnas
Open/closed wiki
Open/closed Uncle Bob
Open/closed Robert C. Martin
Liskov wiki
Liskov ppt
Interface segregation principle
Interface segregation Robert C. Martin
Interface segregation David Hayden
Cohesion wiki
RoleInterface Martin Fowler
Dependency inversion wiki
Dependency inversion Robert C. Martin
Dependency inversion Aspiring Craftsman
Robert C. Martin
Bertrand Meyer
Martin Fowler
Barbara Liskov