Simplicity & Reliability in Complex Software: “No Silver Bullet”

Balraj Singh - Feb 9 '23 - - Dev Community

In today’s era, we as Software Developer have been in a mode of delivering gobs and gobs of features in shorter sprints. This practice has taken us away from one of our core responsibility as Software Developer that is writing Simpler, Reliable and Anti-Fragile Software. We use “easy” frameworks and tools, without giving the problem due thought. That we confuse easiness, with simplicity.
This blog is a reflection of my thought and understanding about writing simpler code. I went through a few articles and videos about software complexity and how to deal with it. All these Articles and Videos and much more content available on the internet talks about 1 underlining concern.

How to make our ever growing Complex Systems more Simple & Reliable?

There is no Silver Bullet to achieve Simplicity & Reliability in Complex Software. To do so let’s start by understanding:-

  • What do we mean by Simple vs Easy?

  • Identify types of Complexity and what all we can try to solve

  • How can we reduce Complexity in our software and make it more Reliable?

Simple vs Easy

As Rich Hickey defined in his talk about Simple and Easy:-

Simple:
Simple means having one of something, one braid, one fold, one role, one concept, one task, one dimension.
Simple can involve many things, but not having interleaving.
Simple is an objective notion.

Easy:
Near, at hand.
Near to our understanding–being familiar.
Near to our capabilities.
We are far to interested in things being easy. This is to our detriment.
Easy is relative (unlike “simple”).

In Software development, simple things have one of something: one role, one task, one concern, one concept, one dimension. This is very similar to “S” in SOLID, the single-responsibility principle.
Easy means something which is familiar, recognizable. The MVC pattern is easy once you’ve done it. Local Notification in an iOS application is easy to use and understand. But at times easy to do things comes with inherited complexity. Local Notification can solve a lot of communication problems within the app easily but this soon leads to the interleaving of many independent modules. Hence becoming a source of Complexity in the app.

Types of Complexities:-

Brooks defined difficulties of “essence” as those inherent in the nature of software and classified the rest as “accidents”. We will use the term in the same sense.

Essential Complexity — This type of complexity is inherited in, and the essence of, the problem (as seen by the users).
Accidental Complexity — Rest of the complexity comes under Accidental complexity. This is the complexity with which development team doesn’t have to deal with an ideal world.

With these classifications of Complexity, we can summarise our understanding by saying the term essential we will mean strictly essential to the users’ problem (as opposed to — perhaps — essential to some specific, implemented, system, or even — essential to software in general). The term “accident” will mean “something non-essential which is present”.

The complexity in which we are interested in is the complexity which we can solve as a software developer or which doesn’t exist in an ideal world. We hence see essential complexity as “the complexity with which the team will have to be concerned, even in the ideal world”. So that leaves us with “accidental” complexity to solve.
Given that in the real world not all possible ways are practical, the implication is that any real development will need to contend with some accidental complexity. But this means we should try to identify these accidental complexities and reduce it to an extent possible.

Simplicity & Reliability

Simplicity is a prerequisite for reliability — Dijkstra said

I certainly agree with this. We need to build simple systems if we want to build good systems. I don’t think we focus enough on that.
With a simpler system, we get the advantage of reasoning and with the ability to reason we get the advantage of predicting the reliability of our system.
I’m just talking about informal reasoning, the same kind of reasoning we use every day to decide what we’re going to do. We do not take out category theory and say, “Woo,” you know. We actually can reason without it.

Rich in his talk “Simple made Easy” makes a very good point about fixing bugs. He says, when you have a bug, that bug got past your tests. And now what? Now you have to find the bug. And if the system isn’t simple, that’s not going to be easy.

He’s right of course. Many of us may argue by saying that we can use approaches like TDD to minimize bugs from getting leaked to production. But TDD is like a safety net, nothing more. We TDDers know that a suite of tests is essential if we want to fearlessly change the code. A safety net can help you keep a system simple & reliable if it’s already simple & reliable. But a safety net below a big ball of mud is going to be of marginal assistance in detangling the mess.

Simplicity is the necessity for building up a system which is reliable and simple. But to maintain that system simple & reliable we can use many techniques and one of them as described above is TDD.

How to achieve Simplicity: Compose, Don’t Complect

Composing simple components is the way we write robust software — Rich Hickey

Building a simple system isn’t as easy as “Don’t do X” or “Always use Y”. Rather, it’s about developing a sense of when things are entangled, when two classes or services or processes depend on each other more than they need to and in unspoken ways, and stepping back and building an explicit interface.

Rich Toolkit for Simple Component

In addition to the above thought, Rich in one of his talk gives some pointers to help developer on how to go about making a simple system. He says to build a simple system one has to choose simple components and compose them not interleaving them. Modules and layers don’t imply simplicity (but are enabled by it). To define what is a simple component and what is a complex component he gives some concrete toolkit. What makes these component simple Rich tried to explain in his talk “Simple made easy”.

Conclusion

As a programmer, I believe we should all think instead of just writing gobs and gobs of code. Our jobs are to master what complexity we can, and to avoid what complexity we cannot master.
Simplicity doesn’t fall out of tooling. You have to do the work! You need to gain sensibilities around what is simple and what is complex. Don’t lean on tools such as testing, refactoring, or type systems. They don’t care if your program is simple or not.

References

Articles:-
***No Silver Bullet*** by Dr. Frederick P. Brooks
***Out of the Tar Pit*** by Ben Moseley and Peter Marks

Videos:-
***Simple made easy*** by Rich Hickey

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .