“…where the work is stripped down to its most fundamental features and core self expression”.
The world needs more minimalism.
Style has always been very important for me. When I talk about style, I mainly mean in terms of expression and art. In the last years, I’ve started to realize that, my definition of style, and what I’m really looking for, is minimalism.
Minimalism plays a very important role in art and design. It is a universal quality that can be found in any kind of art or design form. We can for example see brands from very different niches, like Apple (hardware and software), 37signals (web design), Bruno Mattsson (furniture) and Miles Davis (music), all have made a successful business out of it and have managed to create very passionate and in some cases almost religiously addicted user communities. Minimalism gets you.
It is important to understand that minimalism (and simplicity in general) is not equal to plainness. Actually, it is the contrary. My years as a jazz musician told me (the hard way) that simplicity and minimalism is actually one of the hardest thing one can achieve as an artist. One of the hardest things in the art of musical improvisation is to decide when not to play. To not fear the silence, but to use it as important building blocks in the picture, to paint a story around the silence.
Few have captured it better than Antoine de Saint-ExupÃ©ry:
“Perfection (in design) is achieved not when there is nothing more to add, but rather when there is nothing more to take away.”
Minimalistic design can perhaps be best described as QWAN, short for quality without a name, it is hard to put the finger on it, it has something to do with elegancy, it just feels good, feels right.
I have always thought of minimalistic design as a synonym for good design. But I like the term better since I think that it captures the essence of good design better, and communicates better what it should be and feel like.
The last days I have been thinking about questions like; what is really minimalistic design in the context of computer programming, what are the qualities that characterizes it, what does it feel like and how can it be achived?
Minimalistic Design in Computer Programming
I think that Ward Cunningham captures the essence of minimalistic design in his informal discussion with Kent Beck:
“So when I asked [KentBeck], “What’s the simplest thing that could possibly work,” I wasn’t even sure. I wasn’t asking, “What do you know would work?” I was asking, “What’s possible? What is the simplest thing we could say in code, so that we’ll be talking about something that’s on the screen, instead of something that’s ill-formed in our mind.” I was saying, “Once we get something on the screen, we can look at it. If it needs to be more, we can make it more.”
“The simplest thing that could possibly work”, sounds simple enough, but…what does it mean and…hmm…is it really simple?
Let’s try to break down the statement, and look at what the two parts; “The Simplest Thing” and “Possibly Work” could mean, and if they can to guide us towards minimalism.
But before we jump into that discussion, let’s define what “design” means in computer programming, both in terms of process and artifact.
What is Design?
When I talk about design in computer programming, I’m talking about the Code. I am a firm believer that The Code Is the Design.
This does not mean that UML diagrams, CRC cards or whiteboard drawings are bad, useless or unecessary. They are all part of planning and planning is essential. But while the act of planning is highly useful, the plans themself are of limited value. The planning (or design) sessions are best treated as a learning experience where the end product is not a document or a diagram, but increased knowledge and understanding.
“Do the planning but, throw out the plans.”
- Mary Poppendieck, Lean Development & the Predictability Paradox
“No plan survives contact with the enemy.”
- Field Marshall Helmuth Graf von Moltke
The documents or diagrams will be outdated in a short period of time anyway and are best thrown away as soon as possible, since they will only cause frustration when struggling to keep them in sync with the changes of reality. My advice here are, keep design sessions short, try to keep a high-level focus, see the whole and do not get buried in details, use simple tools and don’t put too much effort into the end artifact (diagram/document) – since that will make it harder to through away.
So, let’s now get back to the dissection of the “Wardism” we just chopped up. Starting with part 2.
Part 2: “Possibly Work”
First, I think that it must contain the minimal amount of functionality that solves the (customer’s) problem, nothing more and nothing less.
Another way to look at it is; customer satisfaction, which has also been described as:
“the right product, at the right time, for the right price”.
Second, if we see “Work” as the product, then the natural question is; how do we define the scope of the work, when can we consider ourselves “done”?
Ken Schwaber talks about Scrum’s definition of “done” as an;
“…increment of functionality that is complete… [that] must contain all analysis, design, coding, testing, documentation and anything else appropriate for the application”.
This would mean that “possibly work” could be defined as: an increment of functionality that is complete (in every sense) and that gives the customer satisfaction. I am sort of half satisfied with this definition, but I think it will work for now.
Now let’s take a look at part 1.
Part 1: “The Simplest Thing”
What does “The Simplest Thing” mean? How can it be achived?
As we discussed in the beginning of this article; “simple is not plain”. It is more a matter of purification and in the context of code I have found the qualities below to be some of the most important ones:
Conceptual Integrity is a quality in art and design, that is described by Fred Brooks, in the context of software, as a a system that is coherent and has been build with a unified vision:
“I will contend that conceptual integrity is the most important consideration in system design. It is better to have a system omit certain anomalous features and improvements, but to reflect one set of design ideas, then to have one that contains many good but independent and uncoordinated ideas. â€¦ Simplicity and straightforwardness proceed from conceptual integrity. Every part must reflect the same philosophies and the same balancing of desiderata. Every part must even use the same techniques in syntax and analogous notions in semantics. Ease of use, then, dictates unity of design, conceptual integrity.”
- Fred Brooks, The Mythical Man-Month, p 42, 44
I believe that conceptual integrity is one of the key qualities that characterizes minimalistic design, where, as we could learn from the definition above, “the work is stripped down to its most fundamental features and core self expression”. It is not an easy thing to achive in in any art form, but especially not in software development with its highly complex nature paired with tight deadlines and customer’s ever-changing requirements.
Things that could help here are; a common vision for the project (have to be shared between developers, management and stake holders), having a small, tight, self-managed and adaptive team, steady flow of feedback from customer (short iterations etc.), refactoring and continuous refinement of the code etc.
The code should have high cohesion, which means that a class should have one single and well-defined purpose. This principle was first introduced by Tom DeMarco who defined cohesion as the functional relatedness of the elements of a module. Bob Martin changed the meaning of this quality slightly when he define the Single-Responsibility Principle (SRP) which says that:
“A class should only have one reason change.”
What this means is that you should only implement one single concern (piece of functionality) in each class (or set of classes) and that all methods and attributes in this class should, one way or the other, contribute to to this specific piece of functionality – no more and no less.
The code should be clear, easily understood and have a quality that is best described as self-documenting.
The code should be modular in the sense that every concern in the system should, if possible, be made orthogonal to the other concerns. This will help you to minimize code tangling and code scattering, and will not only make the code more simple to write, but also to understand, maintain and reuse.
Here we can be helped by using common OO practices such as, the Single Responsibility Principle (see above), the Dependency Inversion Principle (DIP), the Open-Closed Principle (OCP) and the Liskov Substitution Principle (LSP) along with Aspect-Oriented Programming (AOP) and design patterns such as Strategy and Template Method.
One single authoritative representation of every piece in the system
Dave Thomas and Andy Hunt talks captures this in their DRY (Don’t Repeat Yourself) principle. We all know that code duplication is bad and should be eliminated, but the DRY principle takes it even further when it says that:
“…every piece of system knowledge should have one authoritative, unambiguous representation. Every piece of knowledge in the development of something should have a single representation.”
This ties back to both cohesion and orthogonality, since if you have a highly cohesive single representation of every concern in the system, then it is very likely that you can make these concerns orthogonal to each other and get good modularity. It is all connected.
Captures the right abstractions
The code needs to capture the right abstractions. This means that it has to be based upon a model that naturally reasons with both domain experts and developers. Maintaining a Ubiquitous Language can really help here, along with continuous refactoring and refinement of the model.
Finally, I think that the fact that, when Ward’s statement was formalized into a rule; Do The Simplest Thing That Could Possibly Work, it was prefixed with the verb “Do”, is of importance. It might sound subtle, but I think it is not. Because simplicity and minimalistic design is truly a process and not an end product.
We constantly need to challenge the way we work and the code we write, constantly strive for simplification and purification, more pragmatic and effective ways to work, continuously adapt and improve, and keep our humility for one of the most complex crafts there is.
“This complex craft will demand our continual development of the discipline, our learning to compose in larger units, our best use of new tools, our best adaptation of proven engineering management methods, liberal application of common sense, and a God-given humility to recognize our fallibility and limitations.”
- Fred Brooks, The Mythical Man-Month after 20 Years, p 289