Many years ago, I wrote a blog post explaining what was wrong with computers, and essentially saying the problem was complexity. Several years after that, I published Code Simplicity, which was essentially a thesis describing how and why simplicity was the most important quality of software.
Many years after that, I was sitting in a room of some of the world’s most experienced software engineers, coming up with guidelines and principles around which we wanted to structure software development, and after questioning the room, I came to a terrible realization: nobody had ever defined what “simplicity” was for software.
I thought, perhaps naively, that this was simply a known fact—that when I said “simplicity,” everybody just knew what I meant. To some degree, honestly, this was true. When you say the word “simplicity,” people at least get some idea. But I noticed that people would apply it in many different ways, some of them very much not what I intended. I would see people point at a function or file and say, “Look, it has fewer lines of code now, thus it is simpler!” Or say, “Look, this system uses such-and-such design pattern, thus it is now simpler!” Or worse, “This system is now completely generic and follows all of the things that ‘everybody knows’ you’re supposed to do with software, so that’s simple, right?”
So, I went on a search to try to find some sort of valid definition for simplicity. Eventually, I had to come up with it. I actually came up with this several years ago now, and I’ve been meaning to write a blog post about it, but simply haven’t done so. So what is the answer to this great mystery? For software, what is simplicity?
For software, “simple” means easy to read, understand, and correctly modify.
There are several important things about this definition.
First off, simplicity is fundamentally a human factor. It is not caused by machines and it is not done for machines. Only human beings read and understand software. In terms of “correctly modify,” yes, that can be done by a computer, and there are aspects of simplicity where you might be making things easier to be modified by automated refactoring tools or something like that. But the important part there is that we want people to be able to correctly modify software.
This tells you at once that you will never write a computer program that will magically do all simplifications of software. Tools absolutely help people in their quest to simplify and make code understandable. But they cannot do all the work. When somebody wants to take on a quest to simplify software at their company, be very skeptical if their only solution is a tooling solution. If they say, “We want to encourage this better practice by improving the tooling,” great! That’s a human factor. The practice involves people. But never lose sight of the fact that simplifying software always involves human beings acting causatively to develop that simplicity (usually by deleting or modifying something that’s difficult to understand into something easier to understand).
It also tells us that there will never be an automated analysis system that tells us whether or not software is complex. This is a constant question among people who are working on software simplicity–how do I measure how simple something is? Simplicity is a quality experienced only by human beings. It has no inherent truth to it other than the viewpoint of the beholder. There is no inherent quality to code called “simplicity.” You cannot put a number down on paper that says how simple your code is. What you can do is find out from people how simple or complex they find a piece of code to be. (As a side note, you often can’t ask them directly how complex it is, but you can ask them for their emotional reaction to it, which is often the best indicator of how complex it is. If they find some code or system frustrating, frightening, angering, hopeless, etc. that’s often a good sign of complexity.) So any measurement of software simplicity must include a measurement via finding things out from people. Once you’ve done that measurement via people, you might find that certain patterns or systems are almost universally bad or complex, and you can write tooling that bans or fixes those patterns. But the understanding of complexity and its validity comes from understanding what people are doing with the code, what the think about it, how they feel about it, etc.
One of the things that this tells us is that simplicity tends to come when a person spends some time paying attention to simplicity for code. That sounds obvious, but if you observe the behavior of many software teams, you will find out that they do not operate on this fact. Specifically, what this means is that some person being responsible for a piece of code (not responsible in the sense of “to blame for it” but responsible in the sense of “has ownership of it and actively works on it”) is almost necessary to developing simplicity. And this plays out in the physical universe. You can see that reading, understanding, and modifying unmaintained, unowned code almost always becomes more and more difficult over time. I only say “almost always” because I haven’t looked at every single piece of code in the world, and because in order for this to be fully true, you would have to look at it over infinite time (that is, it tends to become more and more complex the longer it’s unmaintained, so sometimes it has to be unmaintained for a very long time before you really encounter this). But it’s been true in every situation I’ve ever seen–I don’t know of any counter-examples where a piece of code got simpler the longer it was unmaintained. When you let software be unowned, you are allowing it to become more difficult to read, understand, and maintain over time.
The other primary cause of complexity, besides lack of ownership, is time compression. In fact, this is the most common cause of complexity–possibly the only true cause of complexity. By “time compression” I basically mean making people feel like they don’t have enough time. Funnily enough, this is most often done to programmers by themselves. They say it’s being done to them by their management (“They gave me these deadlines and now I have to cut corners,”) and sometimes that is true. But more often, developers simply feel a pressure themselves to “be done” with this work. They feel like they need to finish something or somebody will be mad, or they will be in trouble, or they won’t be fast enough, or somebody will think they are a bad programmer, or, or, or…. But often none of that is true, and the actual truth is that they’re perfectly free to take a little longer to do something the right way.
If you don’t think this is true, ask a developer why they made a hack the next time you see a hack. They will either tell you that they didn’t understand what they were doing (another primary cause of complexity) or they will tell you something like, “Well, that other library is very hard to use and doesn’t work right so I had to do it this way.” But think that through. The developer is often saying, “I did not want to spend the time to fix that other library.” Wow, you say, that’s pretty harsh! Fixing that other library could have been a lot of work! True, but did they actually have the time to do it? Maybe they did. One could also say, “I did not feel responsible for that library,” which is where you see once again responsibility coming in for causes of complexity. Maybe it was “outside of their control,” like it was at another company or something. Okay, that’s still a declaration of the level of responsibility they’re willing to take. I’m not saying the decision there was bad, just that you have to recognize that you’re making a conscious decision of how responsible to be (you could have reached out to the other company, reported it to them, worked with them to fix it, etc.) and that you’re intentionally deciding to make complexity instead of spend the time to develop simplicity.
Anyhow, I hope that gives you a better understanding of what simplicity is and what actually causes it. Remember, when you’re talking about simplicity with somebody, make sure they know first that what you’re really talking about is making the code easier to read, understand, and correctly maintain!
Software development is primarily a people problem rather than a technical one (not sure who said this first), so it makes perfect sense that simplicity is not a technical thing. But, that brings in all the messiness of human issues.
Code that is easy for one person “to read, understand, and correctly modify” may not be easy for a different person (and vice versa). This makes encouraging or allowing a single person to “own” any part of the code base problematic, because that person’s idea of easy might be quite idiosyncratic. One of the best reasons to encourage practices like shared ownership, promiscuous pairing and even mob programming is to promote producing code that many people agree is simple instead of what only the “owner” finds simple.
BTW, one “technical” criteria I use for code simplicity is that it is inversely proportional to the amount of comments required.
Hey Steven! Totally agreed that it’s different for each person. I also agree that you can get some agreement on what is simple, and that pair programming and code review both help with this! It’s actually somewhat like writing, where it helps to understand the viewpoint of the reader.
Just like every problem in the physical universe, there is no “perfect” solution to this, but there are _good_ solutions. In actual practice, it is definitely possible to make things contextually simple for the intended readers.
There are lots of problems that have perfect solutions, just none that involve humans.
The main point of my post was to counter “some person being responsible for a piece of code (not responsible in the sense of “to blame for it” but responsible in the sense of “has ownership of it and actively works on it”) is almost necessary to developing simplicity”. In 40+ years of experience, I have found that individual ownership of parts of the code base ALMOST always leads to idiosyncratic complexity. The old school solution was code reviews, but that happens too late and too infrequently. Shared code ownership via pair and mob programming have proven much more effective at achieving maintainability and simplicity than individual ownership.
Even the proposed definition of simplicity is inadequate. Instead of “easy”, try, “as easy as possible.” This accounts for the fact that an operating system kernel module can never be as simple as a CRUD screen having the same number of lines because the kernel module works within a greater number of constraints.
Even this description of simplicity fails to be a definition, since you cannot, even in principle, use it to tell if a piece of software is simple. I think that if we cannot, in principle, build a machine to determine whether a piece of software is simple, it must be because we don’t actually understand what simple means. Perhaps we could solve the smaller problem of “simpler.” We ought at least be able to tell if one piece of software is simpler than another piece of software that produces the same outputs.
A description does not have be measurable in order to qualify as a definition. It would be nice to have a measurable definition, but unless you have a good candidate, it is not fair to fault a definition for not being measurable.
Hey Kurt. It’s true that different things are simple in different ways. That’s okay. There are no absolutes anywhere in the physical universe. This is just another case (just like all cases, for everything) where you have to think in shades of gray rather than in black and white.
Excellent breakdown of the concepts — thank you!
If I were to attach a word to “easy to read, understand, and correctly modify”, I would use the word “Maintainable”.
Would you say there is a difference between “Simplicity” and “Maintainability”?
Hey Nelson! I think I tried to capture maintainability in a more practical way by saying “correctly modify,” because that captures what people are trying to do with maintenance–make changes that match the changes they intend to make.
Hi Max, That makes sense. Maintainability, at its core, encompasses less than Simplicity. I can work with that. Thanks again.
Hello max. Very good blog you have submitted and how you have explained the code to make simple and easy. So, thank you for sharing this blog. It helps me a lot.
I read this article for my thesis paper. And really this article helped me a lot. Thanks to the author for writing such a nice article.
“Where everyone is responsible, no one is really responsible.” ― Albert Bandura, Selective Activation and Disengagement of Moral Control I’ve seen teams responsible for different parts of a system but sometimes only at the code review stage. Other teams would modify the code then get approval from the owner(s). If you have to do this the larger organization should at least facilitate inter-team relationship building, trust building and instill buy in to a core set of “simplicity” principles. This is just good onboarding practice. Don’t leave it up to individuals to summon the initiative to reach out to others.
I love this article by the way 🙂