1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
---
title: Slowftware Development
date: 2024-10-06
draft: false
---
# Slow is Fast
The fastest way to create high-quality software is to develop this software slowly and thoughtfully.
It might seem counterintuitive, but by focusing on understanding the problem,
designing the **right** solution, and refining it through iteration and simplification,
ends up being faster in the long run.[^8]
Rushing to get an MVP out the door often results in poorly scoped projects and architectural design,
technical debt, and "Big balls of Mud" -- architectures that are costly to maintain, and slow to fix.
# Perfection Through Removal
> "Perfection is attained, not when there is nothing more to add, but when there is nothing more to remove." <br>
> --- _Antoine de Saint-Exupéry’s observation_
The same applies also to software development. Simplicity trumps complexity.
Clean, maintainable software is born from stripping down, not piling on. Yet, simplicity doesn't come quickly.
It requires careful thinking, planning, and understanding the problem before jumping into coding.
# Worse is Better
In 1989, Professor [Richard P. Gabriel][4] wrote an [essay][5] to describe the dynamics of software acceptance.
It is the argument that software quality does not necessarily increase with functionality: that there is
a point where less functionality ("worse") is a preferable option ("better") in terms of practicality and usability.
Software that is limited, but simple to use, may be more appealing to the user and market than the reverse.
In his [essay][5], he sums up the worse-is-better philosophy as:
> - **Simplicity**: the design must be simple, both in implementation and interface. It is more important for the
> implementation to be simple than the interface. Simplicity is the most important consideration in a design.
> - **Correctness**: the design must be correct in all observable aspects.
> It is slightly better to be simple than correct.
> - **Consistency**: the design must not be overly inconsistent. Consistency can be sacrificed for simplicity
> in some cases, but it is better to drop those parts of the design that deal with less common circumstances
> than to introduce either implementational complexity or inconsistency.
> - **Completeness**: the design must cover as many important situations as is practical. All reasonably expected
> cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must
> be sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness
> if simplicity is retained; especially worthless is consistency of interface.
This philosophy advocates a stronger emphasis on quality and true agile principles through
"simplicity over correctness"[^1].
It’s easier to maintain simple software, even if it’s not fully feature-complete. A simpler design is often more
robust because it’s easier to test, easier to debug, and easier to extend later on.
By aiming for simplicity, you not only make the system easier to work with but also pave the way for future
improvements.
# Working Backwards
Amazon’s "[Working Backwards][21]" process exemplifies the power of taking time upfront to define the
customer experience. Before any code is written, teams work backward from the final product, crafting
press releases and FAQs to clarify the vision. This approach forces developers and stakeholders to deeply
understand the problem before jumping into solutions, preventing the costly mistake of building the wrong thing.
By focusing on the end goal from the start, it ensures that despite that the process may seem counterintuitive
and slower, it actually speeds up the development and delivers better products.[^2][^6]
# Agile Pitfalls
Agile, though powerful, is often misunderstood and misinterpreted, Many organizations are taking it too far
and using it to avoid careful planning and preparation[^3], Many teams focus on velocity and delivering
a constant stream of features without truly understanding the product’s requirements.
This "move fast, break things"[^4] approach can lead to shallow products that don’t truly solve the customer’s problems.
Instead of rushing to build the next feature, teams should balance speed with proper planning, and proper architectural
decisions, focusing on building sustainable solutions rather than quick fixes.
# Avoid the Big Ball of Mud
In a [paper][10] published in 1997, Authors [Brian Foote][11], and [Joseph Yoder][12]
examine the most frequently deployed architecture, dubbed "The BIG BALL OF MUD":
> A BIG BALL OF MUD is a casually,
> even haphazardly, structured system. Its organization, if one can call it that, is dictated more by expediency
> than design. Yet, its enduring popularity cannot merely be indicative of a general disregard for architecture.
"Big Ball of Mud" architectures arise when short-term gains —like meeting deadlines— are prioritized over
long-term health —like architectural design integrity—. These systems are thrown together hastily, without regard
to maintainability, leading to increased complexity and either an inevitable need for rewrites or quite high
maintenance and running costs.
Many reasons could lead to the creation of a "Big Ball of Mud", these include:
- Time (i.e. meeting deadlines vs time to consider the long-term architectural design and implementation).
- Experience/Skill (i.e. team experience level, experience with the domain, experience with tools, etc.).
- Turnover (even with proper handover, some knowledge is forever lost).
- Complexity (i.e. the domain is complex and bound by certain regulations, like the automotive industry).
- Cost (i.e. early stage startup that needs to try the quick and dirty solution to validate the idea).
While architecture often takes a back seat to more mundane concerns such as cost, time-to-market, and programmer skill.
**Architecture is a long-term concern**, and shouldn't be seen as a luxury, or treated with neglect. To quote the
authors:
> If you think good architecture is expensive, try bad architecture.<br>
> --- Brian Foote
Good architecture takes time and meticulous thought, but it pays off when your system is easy to maintain and scale.
# Code Disposability Over Reusability
Another shift in thinking comes with focusing on code disposability. Rather than trying to write code that’s
reusable across the board, aim for code that’s easy to delete or replace.
By reducing dependencies and layering the code, you build flexibility into the system, making it easier to evolve.
"Boring[^7]" (aka simple code) is often more effective than clean but overly abstracted code,
which is harder to debug or replace when needed.
> Debugging is twice as hard as writing the code in the first place. Therefore,
> if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.<br>
> --- Brian W. Kernighan
There can be tension between "Code Disposability" and "Code Reusability", namely around the ["DRY" principle][30],
In such cases, a "healthy" level of repetition that would make the code more replaceable or removable is preferred to
making the code more reusable (by being more "DRY").[^5]
# Slowftware Development
(or slow software development), is the collection of these old ideas and concepts, to develop valuable,
maintainable software with patience and a deliberate focus on simplicity and correctness.
It's an attempt to embrace working backward from the realized end-product vision, iteration,
disposable code, and solid architecture design to create systems that don’t just work for today
but are easy to constantly and sustainably evolve in the future.
Slow software development isn’t about being slow. It is about being thoughtful, sustainable, and ultimately,
faster in the long run.
---
Special thanks to [Abdallah Dorra][34] and [Tom Nick][35] for proofreading, reviewing, and making suggestions on
this post.
Further Readings:
- [Write code that is easy to delete, not easy to extend.][26]
- [Write code that’s easy to delete, and easy to debug too.][27]
- [Repeat yourself, do more than one thing, and rewrite everything.][28]
- [Going fast slowly.][3]
- [Cognitive load.][42]
[^8]: "In our study of 343 businesses (conducted with the Economist Intelligence Unit),
the companies that embraced initiatives and chose to go, go, go to try to gain an edge ended up with
lower sales and operating profits than those that paused at key moments to make sure they were on the right track.
What’s more, the firms that “slowed down to speed up” improved their top and bottom lines,
averaging 40% higher sales and 52% higher operating profits over a three-year period." --- [source][40]
[^1]: In this [interview][33], Kevlin Henney elaborates on this claim,
"Simplicity is considered the most important characteristic. One consequence of simplicity is improved correctness:
not just that it is easier to create correct code, but that it is easier to see that code is correct. It is also
easier to correct something that is incorrect when it is simple than when it is complicated. And it is easier to
discard and replace something that is simple and incorrect, because it's simple."
[^2]: The Kindle e-reader, AWS cloud computing services, and the Echo voice assistant with Alexa
all came from "working backwards" at Amazon.
[^6]: Fun fact: [Tom Nick][35] suggested "working backwards" from the initial longer version, to make it direct and
concise, instead of a long story told.
[^3]: "The fundamental problem with agile, as many companies use it, is that its relentless pace biases developers.
They want to get out a minimum viable product in only a few weeks, so they skimp on scoping out just what the
product should accomplish." --- [source][18]
[^4]: Although [Gabriel][4] himself later regretted this statement, many software companies latched onto
this particular interpretation of the worse-is-better philosophy. Facebook's Mark Zuckerberg promoted the
"Move fast and break things" term. --- [source][8]
[^7]: "Boring is good. Boring is stable. Boring means being able to focus on your work." -- [source][41]
[^5]: This claim was inspected by [Sandi Metz][36] in her [blog post][32] and [RailsConf talk][37].
[3]: https://vinyl-cache.org/docs/7.2/phk/thatslow.html
[4]: https://en.wikipedia.org/wiki/Richard_P._Gabriel
[5]: https://www.dreamsongs.com/RiseOfWorseIsBetter.html
[8]: https://cs.stanford.edu/people/eroberts/courses/cs181/projects/2010-11/WorseIsBetter/index.php/Worse-is-better.html
[10]: https://joeyoder.com/PDFs/mud.pdf
[11]: http://www.laputan.org/
[12]: https://joeyoder.com/
[18]: https://hbr.org/2021/04/have-we-taken-agile-too-far
[21]: https://www.amazon.com/Working-Backwards-Insights-Stories-Secrets/dp/1250267595
[26]: https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to
[27]: https://programmingisterrible.com/post/173883533613/code-to-debug
[28]: https://programmingisterrible.com/post/176657481103/repeat-yourself-do-more-than-one-thing-and
[30]: https://en.wikipedia.org/wiki/Don't_repeat_yourself
[32]: https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
[33]: https://www.agileconnection.com/interview/worse-better-revisited-interview-kevlin-henney
[34]: https://www.linkedin.com/in/abdallah-dorra-2bbba229/
[35]: https://tn1ck.com/
[36]: https://sandimetz.com/about
[37]: https://www.youtube.com/watch?v=8bZh5LMaSmE
[40]: https://hbr.org/2010/05/need-speed-slow-down
[41]: https://go.dev/blog/compat
[42]: https://github.com/zakirullin/cognitive-load
|