The Four Elements of Simple Design
I realize that I’ve never really written this down before, and I say it so frequently in my work as a trainer and mentor, that I think it bears repeating.
I have reduced everything I’ve ever learned about effective object-oriented design to the four elements of simple design that I first learned from Kent Beck’s work. Maybe you can, too.
I define simple design this way. A design is simple to the extent that it:
- Passes its tests
- Minimizes duplication
- Maximizes clarity
- Has fewer elements
Note that I put these properties in priority order. I’m willing to copy-and-paste to get a test passing, but once the test passes, I can usually remove the duplication quickly. I’m willing to extract code into a method and call it foo() in order to get rid of duplicate code, although that name foo() rarely survives more than 15 minutes. Finally, I will gladly introduce interfaces, classes, methods and variables to clarify the intent of a piece of code, although generally speaking once I make things more clear, I can find things to cut.
Some people put “minimize duplication” and “maximize clarity” in a tie for second place. I don’t. My experience has led me to conclude that removing duplication helps more than fixing bad names does. Moreover, removing duplication tends to allow a suitable structure to emerge, whereas bad names highlight an inappropriate distribution of responsibilities. I use this observation as a key element of my demonstration, “Architecture Without Trying”.
Now I should point out that, as a test-driven development (and now also a behavior-driven development) practitioner, I write tests as I draw breath, so I don’t really need to emphasize that part.
Passes its tests- Minimizes duplication
- Maximizes clarity
- Has fewer elements
I should also point out that I’ve yet to see a codebase with low duplication and high clarity that, nonetheless, had considerably more design elements than it needed, so I don’t really need to emphasize that part, either.
Passes its tests- Minimizes duplication
- Maximizes clarity
Has fewer elements
As some of you have commented, while we can generally agree on what constitutes duplication, “clarity” remains up for intense debate. I have developed over the years a few heuristics related to code clarity that have helped me a great deal, and they relate mostly to names. While I could probably write a long pamphlet or short book on the topic, let me start with one example: a process for improving names.
Names tend to go through four stages: nonsense, accurate, precise, meaningful. Laziness or ignorance push us towards the left end of this spectrum, while with diligence we can move to the right. I contend that names further to the right of this spectrum provide more clarity. This, too, matches Kent Beck’s original conception of this idea, as he referred to “intention-revealing names”.
When I find fifteen lines of duplicate code, I start by extracting them to a new method, and since I probably don’t yet know what those lines of code do yet, I name the new method foo(). After around 15 minutes of working in the same area, I begin to understand what this method does, so I give it an accurate name, such as computeCost(). As I try to write tests for this new method, and find it more tedious than I expected, I realise that it does more than just compute the cost of an item, so I rename it more precisely: findItemThenComputeCost(). The mere appearance of a conjunction, like “and”, “or”, “but” or “then” tells me that the method has more than one responsibility, and as a result, I soon find myself writing tests that duplicate irrelevant details. When I remove this duplication, I have to split this method into two: one that finds the item and the other that computes the cost. When I look at computeCost more closely, I see that it really adds taxes and shipping charges to the net price of an item, which leads me to split that behavior into multiple methods, each that applies a charge to an order item. This leads me to introduce the more meaningful OrderItem class and the OrderItemCharge interface with method applyTo(item) and implementations PrinceEdwardIslandSalesTax, CanadianGoodsAndServicesTax and DomesticShipping. These more meaningful names communicate the story of the design much better than the previous computeCost() name did. You can find similar examples in your code bases of the movement towards meaningful names. Most of the time, I struggle to reach the accurate and precise stage, then I find the jump to meaningful names quite easy. I have found that most clarity issues reduce to misleading names.
That leaves me with two key elements of simple design: remove duplication and fix bad names. When I remove duplication, I tend to see an appropriate structure emerge, and when I fix bad names, I tend to see responsibilities slide into appropriate parts of the design.
I claim these to be axioms of modular design, with a “parallel postulate” of whether you use objects or not. If you use objects, you get object-oriented design, and if you don’t, you get structured design. (I don’t know how functional design fits into this yet, because I haven’t done enough of it.)
I claim that developing strong skills of detecting duplication, removing duplication, identifying naming problems, and fixing naming problems equates to learning everything ever written about object-oriented design.
Put more simply, if you master removing duplication and fixing bad names, then I claim you master object-oriented design.
Now I wouldn’t bother burning your old OOD/OOP books, but I will tell you that if you have an interested buyer, then feel free to sell them.

Pingback: Tweets that mention The Four Elements of Simple Design – jbrains -- Topsy.com
Pingback: How does your code smell?
Pingback: Test Strategy in SharePoint: Part 3 – Event Receiver as procedural, untestable feature at the tar pit
Pingback: The Code Dump » Blog Archive » Design is Simpler Now: Embrace the Extract - A place a coder rants at…
Pingback: CodeRetreat – TDD and Pair Programming « zbyhoo's blog
Pingback: Première « code retreat » à Paris Samedi 2 Juillet «
Pingback: Code Retreat – szafranek.net
Pingback: Why not to work overtime
Pingback: Code Retreat Quebec | Eric Hogue's Blog
Pingback: The Four Rules of Simple Design « I Am Not Myself
Pingback: Global day of Coderetreat: the Belgian edition « talboomerik
Pingback: Première Jam de Code 2012: toujours enthousiastes en TDD ! | Arolla
Pingback: Blog arolla » Première Jam de Code 2012: toujours enthousiastes en TDD !
Pingback: Blog arolla » La qualité de code à tous les niveaux – Round-Table Software Craftsmanship Janvier 2012
Pingback: My first coderetreat abroad « talboomerik
Pingback: To Name A Rose | Neil Traft
Pingback: ProxiAD vous parle d’IT » Agilité Productivité Test populaire » Code retreat : de l’autre coté de la barrière !
Pingback: What does good software design look like? « devCraft
Pingback: TDD en pratique au Software Craftsmanship de Paris | Blog Arolla
Pingback: Global Day of Coderetreat | the pluralsight blog
Pingback: 4 כללים למדידת פשטות של תוכנה | Newsgeek
Pingback: Coderetreat Turku, Finland | Adrian Bolboaca
Pingback: Dealing with legacy in ruby « talboomerik
Pingback: In-house coderetreat workshop « talboomerik
Pingback: Metriken und wofür sie gut sein können | Markus Gärtner
Pingback: My Teddy Bear went to XP Days Germany 2012 | Adrian Bolboaca
Pingback: The value of beautiful code
Pingback: The history of “Taking Baby Steps” | Adrian Bolboaca
Pingback: FAST is safe
Pingback: My first Coderetreat abroad | Co-Learning.be
Pingback: Extreme Enthusiasm » Blog Archive » Refactor to remove duplication
Pingback: alexbolboaca.ro » A Programmer Story