1. "You need to have taste (so: experience) to do DRY right". Same chunk of code more than once, so natural/expected behavior is to export to a helper... Aaaand the now introduced coupling is (too) often ignored, as in "no thought given whatsoever".
2. "Sometimes it's better to just leave it as is". 95% to 98% of "same chunk of code" in a number of places. The temptation to DRY is strong, yet the "numerically mere 2 to 5 pp" make the extracted helper an exercise in all manners of gymnastics. The only correct answer is: do not start.
(Own experience; your mileage may vary - if it does, feel free to comment back!)
Great piece, very straightforward examples, although I did have to squint for quite a while to grok the Closure portion.
I am currently building a piece of very modular software and it has been the hardest-to-design project of my entire career. I would never be allotted this amount of time-effort at any job I have held to make something this robust and clearly defined. Many aspects of this project have taken 3-5 rounds trying-and-trashing to get an abstraction that is uncomplicated.
This is precisely why vibe coding is so successful for building tiny isolated scripts, and so disastrous for anything else. It's just really dang hard to build something large and simple.
Important to note as well, is that "simple" isn't "lesser" or "dumber", it can be "more" and "wider", yet still "simpler".
Expectedly, Rich Hickey explains it best, watch the "Simple Made Easy" talk if you haven't before, one of the few talks I probably watch bi-yearly: https://www.youtube.com/watch?v=SxdOUGdseq4
Few things, concepts and ideas have changed as much of my programming mind as Hickey's talk and ultimately Clojure have done over the years.
Wish we had new amazing Hickey talks to link to, maybe it seems he's about the hang up the hammock perhaps?
My reaction to the Unix pipeline was that, the reason it exploded in complexity is because the pieces were too simple. They were insufficiently expressive.
But the word is used in a different way here, and I'll have to watch the talk to understand what exactly is meant. (Something like orthogonality?)
Agreed. There are multiple senses for "simple" and on of those senses is "small". It is actually a very useful sense too, as Solomonov/Levin/Kolmogorov/Chaitin-style inductive reasoning has shown.
And it is important not to just make snappy quips by equivocating.
UNIX Pipes do not mandate having to use tons of different programs
with stupid commandline options. I simulate them in ruby itself;
method chaining works in a very similar way, but I built a pseudo
pipe around it. The idea was more to have an object oriented shell,
e. g. combine good ideas from UNIX pipes and the MS powershell.
They are simple if you design them well and have them be flexible
too. The reason UNIX pipes were awkward is because they delegated
onto many different programs such as awk or sed with their own
strange rules. Nowhere does it say you HAVE to use such awkward
tools. Use better tools and the idea of piping becomes simple,
similar to (a more flexible variant of) method chaining. Just
without being tied down to a specific object per se (I do use
the pipe-handler master object to handle the pipe instructions;
each pipe instruct I call cmdlet, e. g. shorter for commandlet,
as this is how I like to think about this in terms. This also
combines e. g. virtualdub + avisynth ideas. I loved them when I
used windows. The idea behind avisynth is great - not necessarily
all of the syntax, but the idea that all multimedia audio can be
operated on at all times in flexible ways.)
This argument is just based on "I wish the things I need to do were baked into the language." It's nice when that happens, but once programs get sufficiently large and complex, it stops mattering--you're dealing with domain-specific concepts that have zero built-in helpers and you're just building everything yourself regardless.
The examples in the essay are perhaps not specific enough - they do gesture in the direction of the author’s point, but they also admit other valid interpretations like your own. I think the Rich Hickey talk “Simple Made Easy”, which this post is based on, makes the point more clearly and precisely.
(For what it’s worth, the point of both this essay and the aforementioned talk is that programs do not have to get complex, even when they get large, even when it gets hard because there are no more easy / close-at-hand / familiar helpers in the language to tackle the domain specifics. In support of this point I will note that Rich Hickey is the creator of Clojure, a language in which “building domain-specific helpers yourself” is very nearly idiomatic.)
I don't think it's possible to have a universal "colloquial" definition of "simple" that is also precise. It's all relative.
This is why I think the formalists studying complexity back in the 50s had the right approach. You can only give "simple" precise meaning within some kind of formal system with a shared set of initial axioms or assumptions. From that point you can define it quantitatively over some set of objects (relations, programs).
Funnily enough, this approach also touches on Hickey's etymological derivation. The root words also fundamentally have to do with the quantity of relationships.
1. "You need to have taste (so: experience) to do DRY right". Same chunk of code more than once, so natural/expected behavior is to export to a helper... Aaaand the now introduced coupling is (too) often ignored, as in "no thought given whatsoever".
2. "Sometimes it's better to just leave it as is". 95% to 98% of "same chunk of code" in a number of places. The temptation to DRY is strong, yet the "numerically mere 2 to 5 pp" make the extracted helper an exercise in all manners of gymnastics. The only correct answer is: do not start.
(Own experience; your mileage may vary - if it does, feel free to comment back!)
I am currently building a piece of very modular software and it has been the hardest-to-design project of my entire career. I would never be allotted this amount of time-effort at any job I have held to make something this robust and clearly defined. Many aspects of this project have taken 3-5 rounds trying-and-trashing to get an abstraction that is uncomplicated.
This is precisely why vibe coding is so successful for building tiny isolated scripts, and so disastrous for anything else. It's just really dang hard to build something large and simple.
Expectedly, Rich Hickey explains it best, watch the "Simple Made Easy" talk if you haven't before, one of the few talks I probably watch bi-yearly: https://www.youtube.com/watch?v=SxdOUGdseq4
Few things, concepts and ideas have changed as much of my programming mind as Hickey's talk and ultimately Clojure have done over the years.
Wish we had new amazing Hickey talks to link to, maybe it seems he's about the hang up the hammock perhaps?
This specific usage appears to come from this linked talk, Simple Made Easy:
https://www.youtube.com/watch?v=SxdOUGdseq4
My reaction to the Unix pipeline was that, the reason it exploded in complexity is because the pieces were too simple. They were insufficiently expressive.
But the word is used in a different way here, and I'll have to watch the talk to understand what exactly is meant. (Something like orthogonality?)
And it is important not to just make snappy quips by equivocating.
But they are.
UNIX Pipes do not mandate having to use tons of different programs with stupid commandline options. I simulate them in ruby itself; method chaining works in a very similar way, but I built a pseudo pipe around it. The idea was more to have an object oriented shell, e. g. combine good ideas from UNIX pipes and the MS powershell.
They are simple if you design them well and have them be flexible too. The reason UNIX pipes were awkward is because they delegated onto many different programs such as awk or sed with their own strange rules. Nowhere does it say you HAVE to use such awkward tools. Use better tools and the idea of piping becomes simple, similar to (a more flexible variant of) method chaining. Just without being tied down to a specific object per se (I do use the pipe-handler master object to handle the pipe instructions; each pipe instruct I call cmdlet, e. g. shorter for commandlet, as this is how I like to think about this in terms. This also combines e. g. virtualdub + avisynth ideas. I loved them when I used windows. The idea behind avisynth is great - not necessarily all of the syntax, but the idea that all multimedia audio can be operated on at all times in flexible ways.)
(For what it’s worth, the point of both this essay and the aforementioned talk is that programs do not have to get complex, even when they get large, even when it gets hard because there are no more easy / close-at-hand / familiar helpers in the language to tackle the domain specifics. In support of this point I will note that Rich Hickey is the creator of Clojure, a language in which “building domain-specific helpers yourself” is very nearly idiomatic.)
This is why I think the formalists studying complexity back in the 50s had the right approach. You can only give "simple" precise meaning within some kind of formal system with a shared set of initial axioms or assumptions. From that point you can define it quantitatively over some set of objects (relations, programs).
Funnily enough, this approach also touches on Hickey's etymological derivation. The root words also fundamentally have to do with the quantity of relationships.