Comment by suzzer99
8 hours ago
> Generally, though, most of us need to think about using more abstraction rather than less.
Maybe this was true when Programming Perl was written, but I see the opposite much more often now. I'm a big fan of WET - Write Everything Twice (stolen from comments here), then the third time think about maybe creating a new abstraction.
>WET - Write Everything Twice
I've always heard this as the "Rule of three": https://en.wikipedia.org/wiki/Rule_of_three_(computer_progra...
Antymony with DRY
Totally agree with this, the beauty of software is the right abstractions have untold impact, spanning many orders of magnitude. I'm talking about the major innovations, things like operating systems, RDBMS, cloud orchestration. But the majority of code in the world is not like that, it's just simple business logic that represents ideas and processes run by humans for human purposes which resist abstraction.
That doesn't people from trying though, platform creation is rife within big tech companies as a technical form of empire building and career-driven development. My rule of thumb in tech reviews is you can't have a platform til you have three proven use cases and shown that coupling them together is not a net negative due to the autonomy constraint a shared system imposes.
That is where I put systems programmers, they need to extract an abstract algebra out of the domain. If they are able to accomplish this, the complexity of the problem largely evaporates.
Use the wrong abstraction and you are constantly fighting the same exact bug(s) in the system. Good design makes entire classes of bugs impossible to represent.
I don't believe the trope that you need to make a bunch of bad designs before you can do good. Those lessons are definitely valuable, but not a requirement.
A great example is the evolution from a layered storage stack to a unified one like ZFS. Or compilers from multipass beasts to interactive query based compilers and dynamic jits.
The design and properties of the system was always the problem I loved solving, sometimes the low level coding puzzles are fun. Much of programming is a slog though, the flow state has been harder and harder to achieve. The super deep bug finding, sometimes, if you satisfactorily found it and fixed it. This is the part where you learn an incredible amount. Fixing shallow cross module bugs is hell.
Don't you have to be really seasoned to in good faith, attempt to couple two systems and say where that would be productive? You can't prove this negative. I would imagine a place like that would have to have a very strong culture of building towards the stated goals. Keeping politics and personalities out of it as much as possible.
"Duplication is far cheaper than the wrong abstraction"
Sandi Metz https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction
And adding an abstraction later is much easier than removing an unneeded one, which can be very hard or even impossible depending on the complexity of the app.
More than twice is a rather low bar, I don’t think that it conflicts with the quote from Programming Perl.
I don't think it's a hard rule, more of an ethos. If you know there are going to be a bunch of something, write the abstraction out of the gate. If you have three code entities with a lot of similar properties, but the app is new and you feel like there's a good chance they might diverge in the future, then leave them separate.
Writing twice makes sense if time permits, or the opportunity presents itself. First time may be somewhat exploratory (maybe a thow-away prototype), then second time you better understand the problem and can do a better job.
A third time, with a new abstraction, is where you need to be careful. Fred Brooks ("Mythical Man Month") refers to it as the "second-system effect" where the confidence of having done something once (for real, not just prototype) may lead to an over-engineered and unnecessarily complex "version 2" as you are tempted to "make it better" by adding layers of abstractions and bells and whistles.
I agree with what you're saying about writing something twice or even three times to really understand it but I think you might have misunderstood the WET idea: as I understand it, it's meant in opposition to DRY, in the sense of "allow a second copy of the same code", and then when you need a third copy, start to consider introducing an abstraction, rather than religiously avoiding repeated code.
Personally, even for a prototype, I'd be using functions immediately as soon as I saw (or anticipated) I needed to do same thing twice - mainly so that if I want to change it later there is one place to change, not many. It's the same for production code of course, but when prototyping the code structure may be quite fluid and you want to keep making changes easy, not have to remember to update multiple copies of the same code.
I'm really talking about manually writing code, but the same would apply for AI written code. Having a single place to update when something needs changing is always going to be less error prone.
The major concession I make to modularity when developing a prototype is often to put everything into a single source file to make it fast to iteratively refactor etc rather than split it up into modules.
I've been advocating for writing everything twice since college.
I agree. It's crazy how many layers of abstraction have been created since 1991 (when Programming Perl was published.)
That will still result in more abstraction than the average programmer.