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!