Funny thing is that project management doesn’t operate with such a category like “hard,” “easy,” “complex,” or “simple.” It’s about effort, functionality, and quality. It’s also about risks, timing, and sequencing among the tricky path of reaching the project goals and delivering some unique results at the end; however, that’s less important side for us now.
Despite that, we hear this term all the time when it comes to software development. So, what exactly this “complexity” means, and how it relates to project management stuff?
What does “complex software” means?
Thing which is intuitively perceived as “complex” can also be defined as “something big and messy”.
“Big” is just about the raw size, which for the case of the software can be measured in SLOCs (“Source Lines of Code”). “Messiness” (when comparing the code of equal size), from another hand, is an intuitive measure of overall effort required to understand what the code does. Many factors contribute to that, which includes objective factors, such as code coupling or amount of test cases required to cover it (cyclomatic complexity), as well as subjective factors (reader’s familiarity with concepts behind the code, naming, styling, etc.).
Because of that subjective factors, what seems as “messy” to one developer might look okay to another one, but for both, it will take more time to understand the bigger amount of code. More interesting thing about size is that larger code quickly tends to become the messy one, as it starts to be harder for the developer to keep all the moving parts in mind. Thus, the size itself is the source of complexity.
Excessive complexity increases an effort required for every feature delivery, reduces quality as an amount of bugs is also increased, and reduces functionality we can deliver in the same time frame. In the worst case, it might become the major source of project risks, and even starts to dictate tasks sequencing.
If you do not control the complexity, it starts to control you.
So, how can we control the complexity? There are three general ways of doing it:
- We split the mess to smaller parts, which we can handle. We try to reduce coupling between the parts, making them clearly interconnected.
2. We’re taking repetitive code or functionality patterns, which look close or similar, and trying to abstract them out reducing the total code size.
3. To address subjective complexity factors when working in a team, we’re following some common agreements on style guidelines, design patterns, and the technology stack. Thus, we can easily understand the code of each other.
I don’t distinguish architectural and project management decisions. For me, they are integral parts of each other.
However, that was actually the boring part. The fun starts when we apply this understanding to the situation around web front-end frameworks and React in particular.
Let me show you some example first. Interesting thing is that both pictures below have an equal number of moving parts, performing identical movements relative to each other. So, it the equivalent mechanical systems, with the same inherent complexity. But…
Amazing, isn’t it? An only difference between these pictures is the framework, which is used to describe the system. It dictates what you’re putting at the center.
Now, let me be a bit more specific. It’s very hard to compare different frameworks in an objective way. But fortunately for us, there is exactly the same system, making the identical movements, which is implemented with many different approaches. It’s TodoMVC.
It would be impossible to read and analyze the code for all of them, but do you remember about the link between complexity and size? So hold your breath, folks. We’re going to measure TodoMVC solution size.
When you’ll be told that “all frameworks are the same,” don’t believe it. As the set of application design rules, they are very different in the way they propose to handle the complexity. Even when within the same technology spectrum — look at the React solutions, for instance.
If you are concerned, the best thing to do would be to look inside, and try to understand why the size is that different, and wouldn’t that reasons affect your program too. Take for example the following. Four React solutions have the same JSX size (so you can assume they follow more or less the same approach), but one (NestedReact) is twice smaller. Why?
Because it does something inside, which is significantly different. It uses two-way data binding with Value Links. Which helps to remove repetitive patterns out of the code, reducing its size by half.
P.S.: Not only the size itself is the source of complexity, but it’s also the fairly good predictor of development effort, if you do it statistically correct. Much better than naive guesses, at least. The major problem with SLOC metric, however, is that SLOC itself is not easily predictable. Just like time :). But that’s a completely different story.