11/20/2019

Your code is too complex! - How to choose the right technical solution from complexity point of view?

Introduction
As software developers we all know that every problem has several solutions. It is always up to the situation which solution will be implemented. For example a student at an exam will implement most likely the fastest solution, since a programmer at a multinational company will choose a much more complex solution for the same problem, which is prepared for all possible corner cases. Let’s take a look at the possible solutions and figure out how to choose the optimal one.

Expectations from the code

There can be thousands of expectations against a piece of code, like: it should reuse the already implemented code, it should be reusable by other components, it should work properly in every corner cases and in every possible environment, it should be easy to understand the code, it should be easy to extend or modify the code, it should be testable, it should be fast, it shouldn’t use too much memory, it should follow the style of the programming language etc.
But all of these points are relative, like “it should be easy to modify”. What does easy mean? Easier than what? Or it should be reusable by other component. On which level? It’s full functionality? Each of its classes separately? Etc.
It can also be that some points are absolutely irrelevant. Like a student at the exam knows well that no one else will reuse or change that code anymore, so they really don’t care about all these points, that’s how they can reach quite good functionality in several hours. But the software usually have a lot of bugs, it can not handle the corner cases, it is running only in one dedicated environment etc. To reach the same functionality at a big company may take weeks or even months. But at big companies it is always the goal to reuse the already existing code and make your code reusable, make your code readably and adaptable etc.
If you really consider all these points and you really try to write a code which is fulfilling all of them you can find yourself in the situation that you are building the spaceship (something very very complex), even though it should do only something really easy.

The dark side of building a spaceship

To build a spaceship is really difficult. 99.99% of the humans is not able to build one. Luckily 99.999% of humans doesn’t need it is the same in case of software development.
Once I had a colleague. He was supposed to write a simple database layer, to store some data, nothing special. It could have been done by adding 3 SQL tables and adding maximum 5 simple functions which can add and remove data.This is something could be done in one hour. This guy disappeared at this point for three weeks and came back with a solution which was prepared for everything, really for everything. It has a lot of tables and index tables and a complex library over that to be able to use it. It was basically a small data handling system.
At the end none of its user was happy.
The very first problem: why did it take so long to implement it? Yes, time is a very important factor in software business. Don’t waste your time.
On the other hand its interface was far too complex, no one could figure it out how to use it, and just to add a new element took at least 5 lines. And I still didn’t mention the amount of bugs in that implementation.
At the end he thought he did something great, but everyone else had a different opinion.
This example shows why not to implement a solution which is prepared for everything, especially for situations which will never happen:
It will take a lot of time, it will be complicated to use it, people won’t understand what you are doing, higher complexity means a higher chance for bugs etc.
In a lot of cases, even if your code is technically reusable noone will reuse it, because it is too complicated to use and understand it, so it takes more time to reuse it, than doing your own implementation.

Finding the middle way

The right solution is always up to the task. The points mentioned as expectations are very often contradicting with each other: the faster code usually uses more memory, the code which is optimized for runtime and memory consumption is very often nor reusable, neither readable etc.
So you should think point by point what is relevant in your case: is it critical to optimize its runtime or memory consumption? Will anyone reuse your module in the future? Is it something for long term (so that it should be easy to maintain)? Will it be used in different environments? Figure out what are the real needs and implement your software in that way, nothing more, nothing less.
So the university student at the exam does it well: no one will ever work with his code in the future, so it makes no sense to think about points like readability, maintainability or reusability. Only the functionality is important and the given time frame is tight.
The software developer at the big multinational company does it also well: most likely his code will be used several years long, it will be touched by many developers, used by several users in different environments and there’s a high chance that it will be reused somewhere else (in other software or other software components. So it really makes sense to come up with a solution which fulfills all these non-functional requirements, even if it takes much more time, than implementing the raw functionality.

Always think about the situation of your software and come up with a solution based on that.

No comments:

Post a Comment

How I prepared my first online course

Since long I didn't publish anything here. It's because I was busy with some other topics, but now it's time to share the result...