Managing software complexity
Software systems generally tend to become more complex and difficult to maintain over time.
As the complexity increases, developing new features takes longer, and introducing bugs becomes increasingly easier.
Obviously, our goal should therefore be to reduce complexity whenever we can and create software systems that are simple to understand and maintain.
How can we approach this?
Complexity usually builds up through hundreds and thousands of small changes over time.
Often complexity is also the consequence of technical debt that was never paid back.
The engineering team has to know when introducing technical debt is a valid option and has to revise those shortcuts
as soon as possible in order to not impact the overall complexity and health of the code base.
You may have already heard of the broken window theory.
It basically states that visible signs of disorder create an environment that encourages further disorder.
Although this may sound exaggerated, I strongly believe that this theory also applies to code bases.
Especially, if chaotic solutions are introduced by the more experienced developers of the development team.
In my experience this is true, because new colleagues tend to derive their quality standards justifiably from
their mentor, team, and the existing code base.
If the code base is already a mess and no one seems to take action against it or care about it...
Do you think that new colleagues will be eager to change that and actually enjoy working with it?
What can we do about it?
First of all, we have to act and work towards a simpler and healthier code base ourselves.
As stated above - why should anyone bother if we also do not act how we want others to act?
Before we start, we should think about what complexity actually means. The simplest definition of complexity for
software systems that you can find on the internet is the following:
A complex software system is difficult to understand, modify, and maintain.
Complexity itself can manifest in various ways.
If you ever had to perform a seemingly simple task just to find out that you not only have to adjust the thing you
actually intended to change but also had to change several other things along with it, this is probably one indication of a complex system.
Complexity in software systems is mostly the consequence of dependencies and obscurities.
Minimizing those makes our systems easier to change and understand.
To achieve this, the most experienced developers have to guide the rest of the team and provide support wherever they can.
This requires clear a communication about why someone should even care about such practices and how those practices can be achieved.
From my experience, showing anonymized real-world examples of what went wrong followed by an open discussion and checking
if the suggested practices could have avoided this, works best and keeps things fact-oriented and open for feedback and improvements.
Also share your own mistakes and what you have learned from them, whenever you can.
Encourage an attitude to leave the system in a better state than it was before modifying it.
This attitude will also help to make everyone a better developer at the end of the day as well as keep the code base enjoyable to work with,
and hopefully get you back some time for developing the interesting features that your company needs instead of spending too much time on support and
figuring out what the system does.
It is generally useful to optimize code for reading instead of writing.
This can be as simple as using descriptive names for variables, enforcing formatting in the code base, documenting
your thought process instead of what the code does, or introducing shared standards and guidelines in general.
Those practices reduce the cognitive load of your colleagues when they work with your code and helps them reason about
what the code is intended to do more easily.
So... why isn't this how everyone approaches development tasks?
Developers who are new to the industry might not know about that and might feel pressured to implement features
as quickly as possible to prove to their superiors that they are a good fit and can get things done.
Who doesn't want to deliver the newly requested features as fast as possible and get praise for doing so?
Unfortunately, those encouraging this behavior do not always know how those features are implemented this quickly,
since they might not have a technical background.
It is also not their job to ensure quality standards in the code base in the first place. It's fair for them to expect
the feature to be implemented in a sustainable way so that the system can grow over time as new requirements arise.
Since the code quality is in our hands, we obviously have to factor in the required time to maintain it when making estimations.
This should not be taken too lightly, since we are most certainly the only ones that can actually know if the system
is in a healthy state and what its limitations are.
Clearly communicating the state and problems of the system to superiors, outlining the problems that could arise
in the future when implementing certain features or the defined product roadmap, and coming up with alternative sustainable suggestions is also part of the job.