Recently, I heard a
statement: “We hired a consultancy to make a code review for our
team and they said our code has a lot of technical debt, because it
is not SOLID.”
The SOLID principles
(Single Purpose, Open-Closed, Liskov Substitution, Interface
Segregation, Dependency Inversion) are five basic principles of
Software Engineering. However, there is a reason why they are
“principles” and not “laws”.
The small picture: Never “Done”
I will assume for a
minute that our team has a DoD stating “Code must be SOLID”. Now,
we are in a mess. Suppose I write a mere “Hello World” program.
My first draft will have a static main printing “Hello World” to
the screen. But that's not Single Purpose: Text and screen output are
in one method. Let's separate them. Oh wait – I have another
problem now, my print method depends on an implementation of my text
method – fixed. Let's add an abstraction layer. Oh wait – we have
a problem now. I need to extract the interface. … I think you get
the idea. Give me any piece of source code and I can both tell you
which principles it violates and also which principles will be
violated when you “fix” the violations. But: Where is the value
in that? Is our goal to make perfect code or to deliver Customer
value? You should be “Done” when the product meets its purpose,
not when you think it looks perfect.
The medium picture: SOLID != Clean Code
Let us start by
clearing out a basic misunderstanding first. Clean Code is code that
is easily comprehensible, easily maintainable and easily adjustable.
SOLID is a set of principles to keep in mind to reach this objective.
But SOLID is not the only thing you must do.
To make code easily
comprehensible, you may need code conventions and syntax checkers –
and you will definitely need a well written, readable tests.
To make a product
easily maintainable, you need Continuous Integration, not just as a
tool, but as a mindset. You should be working on a usually Green
Master that is sufficiently robust to give developers rapid, useful
feedback. This, of course, requires lots of thought put into your
test suite – potentially more than you'd put into your productive
code.
To make a product
easily adjustable, you need to think not only about your source code,
but also about architecture and design. This, in turn, means that you
must refactor not only on code level, but also on infrastructure
level.
The big picture: Agility
Inexperienced agile
teams may be tempted to add “Code is SOLID” to their
Definition of Done. While it is a good idea to produce clean code,
SOLID is not a desirable purpose in itself. First and foremost, why do we strive
for Clean Code?
Behind Clean Code is the 4th agile value
“Responding to Change over following a plan”. At the same time,
you have the 1st Agile Principle: “Our highest priority
is to satisfy the customer through early and continuous delivery of
valuable software” and 10th Agile principle: “Simplicity
– the art of minimizing the amount of work done – is essential!”
Clean Code has the objective of making code easily workable, with the
goal of creating a flexible product that can be adjusted
incrementally without ever slowing down in pace. To reach this
objective, we must be able to minimize the effects of change. This
requires changes to be elementary and good automated test coverage.
And this is where SOLID comes into play: When you need to invest a
lot of effort, either into making the change itself or validating
that change, your code is not good. SOLID gives you a simple set of
rules, not only how to add a change, but how to structure your code
so that you can change it later.
Agility neither
advocates keeping SOLID principles nor disregarding them. Much
rather, SOLID is a tool to minimize overall work done – both now,
and in the future. When you know with a high amount of certainty that
the amount of work you will invest on a piece of code in the future
is lower than the amount of work you would invest into SOLIDifying
your code now – then don't. That's not in the spirit of agile
software development, because SOLID is not a customer value: Working
software is.
Summary
Whenever you make a
change to the code, you should make this change in a fashion that
will not purposefully reduce the quality of your code, and that
means: Future comprehensibility, maintainability and adaptability
should not deteriorate below their current stage. When changing code,
think about refactoring before you leave.
In refactoring,
remember: Minimize the total amount of work done. Do not
apply “SOLID” when it's simply a waste of effort. On the other
hand, apply SOLID when you know for certain that you will get back to
a code segment.
No comments:
Post a Comment