There is a well-known proverb in programming theory which states that writing a program is as
complicated as the problem itself that we are writing it about. At the ASH Software House, we
usually create software solutions for extremely complex problems. There is also the clean code
which is very useful and everyone uses it. It helps a lot to make a better quality software
product in less time. However, incorporating its elements into everyday work and grinding it
smoothly is a lengthy process. It also includes the “trial luck factor”! You need to try and
analyze which element can best be lifted, and what modifications need to be made to make it
work optimally. By now we achieved that this is the foundation of all our development. So how
do we use the principles of clean code to best fit into our workflows?
The clean code can be thought of as a bouquet of recommendations. A huge big bouquet that
called the programming experience accumulated over the decades to be kneaded into a unified
and digestible form. It has a lot of elements, I would highlight a few of them.
Readability. Perhaps the most important one. A well-written code is self-documenting.
We can even ignore the comments, as a clear, easy-to-follow guideline is outlined for
everyone, making even the most difficult parts easy to digest.
Simplicity. No frills. A program should be purposeful and concise.
One object one function. We can also interpret it for methods, this is the principle of
“pure function”. This is perhaps the most difficult recommendation to follow,
we also often struggle with it, too. However, we never let go of one thing: no building
block that gets into our work can contain a side effect. We break it down into smaller
subunits until we achieve it.
Premature optimization. Also a difficult part to handle. A given program should contain as
much and only as much code as it needs to meet a user or a business need. Which, in turn, is
constantly changing and transforming! So somehow it has to be taken into account. It helps a lot
if the not hard-wired, making it easier to shape and modify. It is important to program on
interfaces as long as possible to avoid the introduction of specific classes. It is also not desirable
for components to manage their dependencies themselves, instead it is more appropriate to use
frameworks or factory models that implement DI (dependency injection).
Avoid duplications. It also sounds simpler than it is to implement, although it is one of
the easier principles to incorporate. Avoiding duplication can introduce other bugs, like
possible side effects in functions. Sometimes it’s hard to decide what’s more important.
Write two functions, which differ only in one line, or break the principle of one function
one responsibility. However there are patterns that can help here, for example, function
overloading , or polymorphism for class methods.
These are perhaps the recommendations we definitely incorporate into our daily work. But
how do we organize the workflow itself?
The most important aspect is reusability. One of the main priorities at all our projects is to
make the most of the elements and structures we have dreamed be ready for following works.
This is how the time invested pays off. To do this, we need to build our data structures with this
in mind from the start. As a rule, an object should only implement one function, but that one
function should produce the same result in different environments. So we need to analyze all
the big work that has already been done and is expected in the future and look for common
atomic parts in it. Only units that can be assigned a function that produces idempotent results
in any environment that occurs in the course of our work are eligible. This is the hardest part.
This is followed by thorough testing and then arranging these building blocks into a unit. Then
the integration tests.
What helps to find the aformentioned atomic particles? Of course, we have methods for this that
I cannot reveal here in their entirety, just a few details.
Strong DDD (domain driven design) approach. Sometimes it’s more helpful to look at things
from the other side, the business domain side. The excellent harmony of project managers and
experienced programmers is a key!
TDD (test driven design) approach. Unfortunately, this is not always the doable, but where we
can use it. Which object aspirates for the role of “atomic building block” can be subjected to
identical, relevant and simple tests regardless of the project.
Importance of names. Sounds trivial, but can’t be stressed enough!
Of course, we use a lot more. I don’t want to list them all here, because everyone blows them from the
outside :)! For those who haven’t, here are some useful things to read:
Erich Gamma: Design patterns.
Joshua Bloch: Effective java
Robert C. Martin: The Clean Coder: A Code of Conduct for Professional Programmers
Robert C. Martin: Clean Code: A Handbook of Agile Software Craftsmanship
Robert C. Martin: Agile Software Development: Principles, Patterns and Practices