How spaghetti code finds its way back to our codebase - intro
Tags: cleancode, javascript, frontend
Published: 2020-05-04 16:59:28

Around 8 years ago when we first started reading **Clean Code** by Uncle Bob at work I remember having fighting with the C++ devs in our team about giving it a try or maybe writing their own unit tests: _"You are not going to convince us that we have to do double work! That’s why we have the QA team for!"_
Fast forward to 2020 and it is hard to find a job description without the mention of **clean code**, the **SOLID principles** or **unit test coverage**.

Yet horrible, horrible `spaghetti code` finds it way back to our codebases. This little series will be about the various ways of it. 

But first let's talk  briefly about...

## Why simplicity matters
Let's kick this off with an example from Victor Nakoryakov's [Two years of functional programming](https://hackernoon.com/two-years-of-functional-programming-in-javascript-lessons-learned-1851667c726) article:

**Example 1a:**
```javascript
// what does this do?
const format = R.converge(
  R.unapply(R.join(' ')),
  [
    R.always("Value"),
    R.nthArg(0),
    R.always("is not expected here. Possible variants are:"),
    R.compose(R.join(', '), R.nthArg(1))
  ]
);
```

Ah, OK, yeah, hmm. Now check out this:

**Example 1b:**
```javascript
function format(actual, expected) {
  const variants = expected.join(', ');
  return `Value ${actual} is not expected here. Possible variants are: ${variants}`;
}
```

This is a contrived example, I know, and probably _no one_ will ever write **1a**, however it is also a good one to argue about trade offs. 

### Correctness over simplicity
While I was researching for this series I have stumbled upon the notion of **correctness over simplicity**. It basically teaches to be _correct_ and _complete_ first and then be _simple_. Features must work correctly, right?

A contrasting solution was provocatively titled ["Worse is better"](https://en.wikipedia.org/wiki/Worse_is_better), which sacrifices _100% correctness and completeness_ for the sake of _simplicity_. Sounds like madness: why would _anyone_ want to sacrifice _correctness_?

### Correctness over productivity
Let's compare example **1a** with **1b**: while the first approach may be more _"correct"_ theoretically, it might also take 10 minutes to understand, while the second one only takes about ten seconds. And not just time matters, we usually don't talk about the fatigue associated with solving puzzles; not all 10 minutes of work count the same. So in reality a lot more energy is wasted.

At least we can say our code in **1a** is _so correct_ that we do not have bugs. But not all bugs are `null reference errors` (and they are usually pretty simple to fix) and there are multiple ways of catching them.

#### Bugs are caught by compilers, tests, customers and... your colleagues
This is the `code review factor`. If your code is so advanced that your colleagues do not understand it they will have two options:
1) make you rewrite using simpler solutions
1) being afraid of commenting about it because they do not want to look dumb (the ugly side effect of [Impostor syndrome](https://en.wikipedia.org/wiki/Impostor_syndrome))

Finding bugs in _code review_ relies on the reviewer's ability to understand the consequences of the pull request. Making it harder for the reviewer will inevitably lead to more bugs.

Therefore it is very easy to make the strong connection between _simplicity_ and _productivity_. This was true before the first edition of **Clean Code** came out and is true ever since. 

> The time you spend on understanding something that could have been written simple is time wasted from product work. 

## Choosing simple technologies
In software engineering we should start from the _product requirements_ and find the solutions for them and not the other way around. That means the _language and technology_ you love might not be the best for the problem at hand. 💔

I know it sounds funny, but I saw frontend projects in `groovy server pages` just because somebody was married to the language. _(Good luck for the recruiters!)_

### Strong guarantees, strong constraints and added complexity
There is **unavoidable complexity** though. There are products that need **strong guarantees**: writing code for a rocket or a pacemaker or an ✌️unhackable✌️ _OS function_ have to be different than code written for an _error reporting form_.

For the three former examples using **Rust** might be an excellent choice. For the latter you should use `JS` + `React` without even using the `immutable.js` library.

Now let's take a glance at `Rust`. `Rust` is amazing, solving great problems with elegant solutions _if you need to control memory, efficiency and threading_. It also introduces many-many complicated stuff: you can't just throw parameters around, you have to learn about `borrowing`, `copying`, `lifetime`, `mutability`, differences between the 'heap' and the 'stack', and then choosing the right one for the right task. Therefore...

> Writing a throwaway error reporting form in `Rust` is gonna be spaghetti code compared to an average `JS` `React` app regardless how skilled you are.

Simply because of the inherent complexity of the language. So if you don't need to have a refined control over any of those then choose a language and technology which is the simplest for the problem.

### What is simple to you might be spaghetti to others
_"Wait! But good developers understand hard stuff"_. That is true and why should we lower our standards? However there are many angles to this.

Most of us work in large companies with large number of devs of different backgrounds: code owned by **Team A** might get pull requests from **Team B** and **Team C**. **Team A** might have full stack devs who are only working on frontend code maximum a week per month, or it might have junior devs nervous about their own decisions.

> Therefore your solutions can't rely on hardcore experience in the given technology; you have to flow with the crowd, _you have to prepare_ the examples your colleagues will _copy-paste and modify_ just to get their feature work done.

#### Choosing the language is also choosing the talent pool
The last angle I will be talking about is the **talent pool** you might have. The "best" language might not have enough experienced devs to work with leading to, you can guess, _spaghetti code_.

I was once working with a team who had their code base in `Elm`: the team lead had one year experience of it and everyone else just started learning it. They soon became the bottleneck for a project with a 3 month deadline. We didn't have time to learn their language and recruiters could not hire people. It soon turned ugly, people shouting at each other during meetings, and so on.

Technical decisions do not exist outside of business and social circumstances.

-------

Thanks for reading my article!

### Did I use the wrong phrase? Did I make a typo?
I am not a native English speaker, any help regarding the right phrase, the right language, style is super welcome!