
Write dumb code - luord
https://matthewrocklin.com/blog//work/2018/01/27/write-dumb-code
======
userbinator
It is often the case that the simplest solutions require the greatest skill in
achieving. Thus, I agree immensely with avoiding unnecessary complexity
whenever possible, but not "We should endeavor to write code that a novice
programmer can easily understand without explanation or that a maintainer can
understand without significant time investment." \--- which tends to lead to
extremely verbose, inefficient, and dumbed-down code.

In other words, if you only ever use the very simplest features of the
language, you are effectively reducing _micro_ complexity but increasing
_macro_ complexity. One of the best examples of this is the classic arguments
over the use of the ternary/conditional (?:) operator --- those against say
it's hard to read and should always be replaced with if/else, while those for
say it simplifies the code by removing redundancy and should always be used in
place of an if/else with a single assignment statement with the same LHS in
both clauses.

Similarly, if you believe programmers are almost completely incapable of
understanding operator precedence, or that it "makes code hard to read" and
restrict expressions to only one operator (and mandate that variables be
created for all intermediate results), then you will get code with all the
verbosity of Asm but none of the benefits.

In other words, good code may not be immediately obvious; but your reaction
when you do understand it should be one of pleasant enlightenment, and not "I
can think of a simpler way to do this."

A somewhat related article: [http://typicalprogrammer.com/what-does-code-
readability-mean](http://typicalprogrammer.com/what-does-code-readability-
mean)

~~~
quickthrower2
Yes definitely. If you code using a VB6 style subset of your language you'll
probably end up with spaghetti. That's easy to understand at an individual
procedure level but pretty hard to refactor and maintain.

~~~
flukus
> If you code using a VB6 style subset of your language you'll probably end up
> with spaghetti

Unless I'm remembering incorrectly I'd say the opposite, vb6 had a pretty sane
feature set comparable to "modern" languages like go and rust. Coding with
that feature set will give you simple and understandable code, if a little
verbose at times.

The spaghetti code it's famous for was mostly a result of the event driven,
drag and drop nature of the IDE and community. If you want real spaghetti code
then try vb.net which suffers from the same problem but allows devs to pile on
a bunch of OO features that obscure what code is doing.

~~~
majewsky
> vb6 had a pretty sane feature set comparable to "modern" languages like go

What's not sane about Go's feature set? (Except for its debatable omissions.)

~~~
juki
I think you misread that. They said "comparable to" (equally sane), not
"compared to".

------
nine_k
Apparently the author mistakes dumb for simple.

Usually dumb code is layers upon layers of needless complexity, grown because
the coder had neither time nor inclination to understand the problem, and kept
tweaking.

Such dumb code becomes a huge support and troubleshooting cost, letting alone
quickly modifying it.

Don't write dumb code. Write simple code. The recipe is known: think about the
data first, untangle and minimize dependencies (including any global state),
write simple, orthogonal functions over these data. Use the language's
standard library and built-in data structures. Crave for these negative line
count PRs.

It takes much shorter time than working with dumb code.

~~~
marzipan
If it's complex and hard to maintain, then it's not dumb code. It's genius
code. Dumb code is actually very hard to write successfully in production and
there isn't a recipe for it. The novice flails and makes the code too
complicated trying to add one hack on top of another without doing any causal
analysis, the journeyman programmer starts throwing in a lot of defensive
abstraction they learned about yesterday that doesn't tame the problem at
hand, and the expert writes a correct solution that is exactly what is needed
and no more. As a bonus, when you enter a new problem domain you're a novice
again. All that stuff you knew about working with databases is irrelevant if
you're working with real-time audio. But you get to skip through the cycle
faster this time.

Ergo, dumb code. It's hard to make dumb code that actually stays dumb instead
of turning into genius-level complexity or bad abstraction.

~~~
AstralStorm
That is some interesting definition of genius you put in here. Usually the
criticism of so called genius code is about manual optimization and sometimes
domain specific optimization and not about crust achieved over years of
lacklustre maintenance.

There ate actual real reasons you shouldn't or cannot write dumb code. One
piece of such "cruft" is handling numerical corner cases which is
_unavoidable_ unless _proven mathematically_ to be impossible (And commented
why). Using IEEE floating point? Guess you get to handle ULP precision, NaN
and Inf. Using integers? Welcome to wraparound. Memory management? What
happens if an allocation fails? Threads? Race freedom is quite interesting to
achieve.

Using Java? Then figure out what happens when you choke GC with hundreds of
objects. Etc.

You can only go so far in passing the buck to library authors, they can make
mistakes too.

------
ScottBurson
_My point today is that, if we wish to count lines of code, we should not
regard them as “lines produced” but as “lines spent”: the current conventional
wisdom is so foolish as to book that count on the wrong side of the ledger._ —
E. W. Dijkstra

One of my favorite quotes :-)

------
ams6110
Parallels Strunk & White's _Elements of Style._ Who knew there was so much
similarity between writing code and writing prose?

Omit needless words.

Write in a way that comes easily and naturally to you, using words and phrases
that come readily to hand.

It is always a good idea to reread your writing later and ruthlessly delete
the excess.

Avoid the elaborate, the pretentious, the coy, and the cute. Do not be tempted
by a twenty-dollar word when there is a ten-center handy, ready and able.

~~~
Royalaid
Which has inspired
[https://leanpub.com/elementsofclojure](https://leanpub.com/elementsofclojure)

------
somethingsimple
> Software is the currency that we pay to solve problems, which is our actual
> goal. We should endeavor to build as little software as possible to solve
> our problems.

Amazingly well put. I’m gonna try and not forget this so I quote it when
discussing with people who love to come up with bloated, overengineered
solutions.

------
seanmcdirmid
Writing dumb code is a lot more expensive up-front than writing smart code. It
is like writing something in simple-to-understand prose; that costs more on
write than hard-to-understand prose, but pays off when read.

So I feel like the author of this essay is talking about some costs (the
reader's) without considering the cost of the writer. If the code is never
read because other solutions are considered more viable, then all that cost in
making it simple for not. As always:

1\. make it work.

2\. make it nice (if it works and is going to survive to code review).

3\. make it fast (if it has performance problems).

Unless you are completely on waterfall, you aren't going to be able to do 1.
and 2. concurrently.

~~~
CloudYeller
I'm not sure if it's more expensive either. The first correct algorithm I can
think of, expressed in the programming equivalent of pre-K level English,
usually is less buggy and 10X easier to maintain than the advanced-language-
feature-filled code that certain engineers love writing. And it takes a
fraction of the time to write because it doesn't require much refinement. Is
it slower than finely tuned C++? Yes. Does that matter? michael-scott-NO-GOD-
NO.gif

It boggles my mind when people who are just building an everyday website
decide that querying models from the DB means we need a multi-level class
hierarchy that requires a 5 page paper to explain. Or that anything remotely
related to math means we need to start overloading operators. Congratulations!
Your brain recognizes patterns! Wow, someone should make you the President of
all Engineers Everywhere.

The code you're writing now will likely not survive another 2 years,
especially if every time there's a bug or even a question like "how does
feature X work under condition ABC?", everyone shrugs their shoulders and has
to read 1000 lines of horribly nested abstractions.

~~~
seanmcdirmid
> The first correct algorithm I can think of, expressed in the programming
> equivalent of pre-K level English

If I can think of it, then I hope it already exists and I can just reuse it.
The tricky stuff that needs a lot of thought is the same stuff that you can't
just reuse off the shelf.

> It boggles my mind when people who are just building an everyday website

If it is something so routine that it doesn't need to really be designed, then
I guess you can do it right the first time from memory (shame you just can't
reuse some functionality if it is so routine though).

> The code you're writing now will likely not survive another 2 years

I work in research where your code is lucky to survive 2 months. I don't
disagree with you, but you can't crank out perfectly simple code on the first
go if the design space is clear. Those abstractions usually don't exist
because the programmer was trying to be clever, they often exist because the
programmer was trying to solve the problem. Its only with hindsight that we
can often see a better more simple way (and hopefully have time to go back and
do the simpler way).

~~~
erichurkman
> If I can think of it, then I hope it already exists and I can just reuse it.

There is also a cognitive load of 'using it' for simple algos and packages,
like left-pad. Some end up the de facto standard of a community (Python's
`requests` package), but other communities fracture (Node's SuperAgent, Axios,
got, Request, reqwest, ...).

I like to think of code I write today as automatically being 'obsolete' 12
months from now. I might not replace it +12 mo, but if I _were_ to replace it,
what comments, patterns, and hints might I leave my future-self to make that
easier? Simpler code is easier to test and replace. Less magic code is easier
to swap out with other languages. Verbose code is easier for my new team of +N
engineers to digest, even if it takes twice as long to read.

------
dawhizkid
It took me a little longer to understand higher order functions in JavaScript
than it took me to understand for loops but once I “got it” then using
something like array.filter((x)=> x%2===1) seemed cleaner and arguably
“simpler” than the alternative but not “dumber.”

~~~
mvindahl
Also, unlike the for loop alternative, it clearly expresses the intent. "I am
filtering this array, using this condition". The functional programming style
really shines here, and it shines even more whan you start chaining the
operations.

I guess the rule of thumb is to write code to most clearly express the intent
of it. Often harder said than done but a good goal to strive for.

~~~
collyw
To be fair the new arrow operator syntax is a bit cryptic. I am sure Ruby
offers plenty of things like that, because when I look at Ruby codebases I
often don't understand what they intend to achieve.

------
root_axis
> _The best way you can contribute to an open source project is to remove
> lines of code from it._

Deleting code doesn't necessarily mean you're making it simpler. Compressing a
5 line function into a snazzy 1-liner is almost certainly making the code
worse, not better.

> _Every line that you write costs people time._

This kind of mantra is how you end up with nested ternary expressions and
tightly wound functional compositions in imperative languages.

~~~
Dreami
I don't think he meant compressing 5 lines of "normal code" into a one-liner.
He meant, actually removing it. Maybe the logic it provides is not needed
anymore, or you could do it somewhere else in a far more readable way (I'm
thinking about abstraction levels)

~~~
root_axis
Sure, and I think we can all agree that this type of refactoring is useful,
but I have worked with many developers that really take this anti-LoC idea to
heart and end up producing difficult to read code because they are so focused
on finding the most terse way to express logic.

~~~
majewsky
A favorite quip of mine is that I dislike Ruby because the entire community
optimizes for one-liners.

~~~
collyw
Back in my days of writing Perl one liners were also kind of encouraged,
because usually it would likely be more performant. At least thats what some
instructors told us.

------
partycoder
Very similar to the "the principle of least power":

\-
[https://en.wikipedia.org/wiki/Rule_of_least_power](https://en.wikipedia.org/wiki/Rule_of_least_power)

\-
[https://www.w3.org/2001/tag/doc/leastPower.html](https://www.w3.org/2001/tag/doc/leastPower.html)

\- [https://blog.codinghorror.com/the-principle-of-least-
power/](https://blog.codinghorror.com/the-principle-of-least-power/)

I also would like to add this blog post by Li Haoyi (from Scala.js fame)

\-
[http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLe...](http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLeastPower.html#philosophy-
principle-of-least-power)

I think the tradeoff is maintainability and flexibility. I think code cannot
be allowed to be complex. Complex code will eventually be broken during
maintenance.

------
keithnz
while theres an esssense of truth in this blog ( write simple code ) the
details given miss the mark. Software shouldn't be considered a cost, that
could lead to the wrong choices, it's just part of a bigger system and costs
generally should be measured at the system level.

Also you have to be careful with using "interns" as a measure of minimum code
level. Often the interns opt for what they feel is simple to understand but
can be prone to errors. There are many micro patterns that avoid many problems
that come from experience. But the sentiment about not using too clever code
is generally good.

~~~
wickawic
> Software shouldn't be considered a cost

I fully disagree. Code is a liability taken on as a calculated risk to perform
some task.

~~~
dragonwriter
> Code is a liability

Code is an asset, like any other piece of capital. Like physical capital,
using it and maintaining it may have costs. Like physical capital, the costs
associated with it are not worth paying if you don't have a productive
application for the capital asset that justifies those costs (and, also, the
amortized cost of acquiring the asset in the first place.)

~~~
scarface74
It depends. Any code that I see written in support of cross cutting concerns
that are not specific to specialized needs of the business are a cost I look
for others to bare. I'm not going to write my own logging framework, ORM,
configuration, scheduler, etc.

Recently I removed three custom written classes - one involving a friendly
wrapper around .Net Http client, one to handle writing and reading CSV files
and one to handle retry logic. I found better implementations on Nuget and
replaced my custom versions.

Why? Because I knew my future self would appreciate not having to maintain
them. Of course I had unit tests around the existing functionality first to
help keep me from breaking stuff.

Any company has a narrow niche for which it is writing software. Avoid writing
anything outside of that niche and use third party software. You are not
giving your company any competitive advantage by writing yet another wrapper
around database access.

~~~
megaman22
RestSharp, CsvHelper and Polly?

~~~
scarface74
Wow. You're 3 for 3.

------
lopatin
I find these kinds of articles ultimately unhelpful. I do agree with the
overall message, but with the lack of practical examples, all I came away with
is a description of the problem we're all too familiar with already (software
design is hard, simplicity is desirable) but no answers to _how_ to achieve
that in the real world.

"Don't use recursion to solve a problem easily solved by a for-loop, except
when recursion is the right tool for the job."

You're not wrong. Just not terribly useful advice when fighting against real
complexity in systems.

------
justboxing
I've heard and read about this time and again over the years, but am yet to
find a blog post -- including this one -- or video that take an existing set
of code snippets that is un-necessarily complex, and then refactored / re-
written that code to be dumb code that performs similarly but is easier for
any rookie to understand and maintain.

Can anyone point me to real examples for C# or Java?

~~~
ssivark
I haven't programmed in C# or Jave, but I was recently looking into expository
literature on why functional programming helps write more modular code [1]. I
found the following Haskell-based example to be really enlightening:
[http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-
Way...](http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-
Way/#functional-style)

I think it's okay to skim over the Haskell specific parts; what I really liked
how the end result (version 10 of the program) is nicely composed out of
orthogonal pieces, compared to version 1, which is a monolithic blob, while
"simple". So, if you want to solve a related but different problem, you can
reuse everything you've written instead of duplicating code. So any
bugfixes/improvements to one part can trivially be propagated to all other use
cases.

[1]: [https://blog.acolyer.org/2016/09/14/why-functional-
programmi...](https://blog.acolyer.org/2016/09/14/why-functional-programming-
matters/)

------
dswalter
This post is by the author of the dask parallel computing framework, which is
written in Python and getting some traction in astronomy circles.

------
bootcat
I have to completely agree with the article, and that has been my learning
working for biggies in the US. But not all people agree on that. They consider
themselves smarter, after writing complex code with no documentation. Also,
certain people make value with complex stuff instead of making it easy as a
breeze for others to understand and contribute.

------
carussell
Here are links to two of my favorite essays that make a similar point:

Java for Everything[1]

Too DRY[2]

And then there's a third, which is not quite the same topic, but still in the
same vein. It's arguably even more relevant today than three years ago when it
was written, especially given how much attention is being captured by
ecosystems that attract folks who end up generating a morass of terrible
tooling:

Helping my students overcome command-line bullshittery[3]

1\. [https://www.teamten.com/lawrence/writings/java-for-
everythin...](https://www.teamten.com/lawrence/writings/java-for-
everything.html)

2\. [http://jamie-wong.com/2013/07/12/grep-test/](http://jamie-
wong.com/2013/07/12/grep-test/)

3\. [http://pgbovine.net/command-line-
bullshittery.htm](http://pgbovine.net/command-line-bullshittery.htm)

------
pvsukale3
IMHO this is the philosophy behind ruby and rails. Any kind of software has a
people cost. We should be able to spend less time writing software and it
should be a time efficient process as we pay for it using human time.

~~~
collyw
Ironically I find Ruby code one of the hardest languages to read when I see a
random snippet.

------
IncRnd
The author wrote a nice piece, but it should be called, "Write Dumb Code,"
but, "Write correct & concise code." Dumb code doesn't mean the same thing as
short code.

------
skun
Kiran addressed a very similar (if not the same) topic at the PyCon India 2013
keynote:
[https://www.youtube.com/watch?v=_stsJlNgGfA](https://www.youtube.com/watch?v=_stsJlNgGfA)
(40 mins). I was there at the keynote and it really helped set my basics very
strongly. Highly recommended.

------
jeffdavis
I agree, but the author doesn't tell us how to do that in practice.

~~~
anonfunction
It's not by the author but Rich Hickey (creator of clojure) has a great talk
titled "Simple Made Easy"[1] which I always recommend.

Furthermore I have been using Golang and would say it is very simple language
that anyone could pick up and become productive with quickly. One of Go's
proverbs is "Clear is better than clever."[2] At the expense of a little
verbosity there is much less ambiguity in the intent of code.

1\. [https://www.infoq.com/presentations/Simple-Made-
Easy](https://www.infoq.com/presentations/Simple-Made-Easy) 2\. [https://go-
proverbs.github.io/](https://go-proverbs.github.io/)

------
perlpimp
Consistency is the name of the game. Principle of least surprise. Keep flow
happening. etc etc.

------
shobhitchittora
Gold mine of Empathy!

------
dbcurtis
> Software is the currency that we pay to solve problems,

A great mind shift there.

------
xstartup
Our company's full-time job is to shrink our customer's codebase size
aggressively. Your team will not do that because it's a job security to them.
Let us make your company where it's easy to fire anyone without risking major
drawdowns.

~~~
xamuel
>Your team will not do that because it's a job security to them

Every team I've ever been on [albeit that's only two], it's the opposite, if
the devs had their way they'd spend all day every day simplifying and
refactoring. The only reason we don't, is because actual business needs demand
attention.

~~~
dingo_bat
If I had a free reign over my time at the office, I'd spend at least a month
just cleaning up the mess that has accumulated.

