Vlad's Roam Garden

Powered by ๐ŸŒฑRoam Garden

when you develop software you invent a language

Each time you create a piece of software - you create a language. It can be composed of just a few verbs in a simple script or it can encompass a whole new and complex domain of knowledge.

Each class and each function add a concept to your language. Every time you create one - either from primitive statements or from other concepts you've already defined - you make your language more expressive. You rise it's [[level of abstraction]].

And you explicitly define things that were too hazy or unclear before allowing you to solve more complex problems.

The language that fits well together is an indicator of good design

And you can improve it by refactoring your code.

DSLs, when used effectively, raise the abstraction level above code idioms and design patterns. They allow the developer to reveal the intent of the code at the appropriate [[level of abstraction]].

G5: duplication This is one of the most important rules in this book, and you should take it very seriously. Virtually every author who writes about software design mentions this rule.
Dave Thomas and Andy Hunt called it the DRY principle (Donโ€™t Repeat Yourself).
Kent Beck made it one of the core principles of Extreme Programming and called it: โ€œOnce, and only once.โ€
Ron Jeffries ranks this rule second, just below getting all the tests to pass.
Every time you see duplication in the code, it represents a missed opportunity for abstraction. That duplication could probably become a subroutine or perhaps another class outright. By folding the duplication into such an abstraction, you {{=:1|increase the vocabulary of the language of your design. Other programmers can use the abstract facilities you create}}. Coding becomes faster and less error prone because you have raised the abstraction level.
The most obvious form of duplication is when you have clumps of identical code that look like some programmers went wild with the mouse, pasting the same code over and over again. These should be replaced with simple methods.
A more subtle form is {{=:2|the switch/case or if/else chain that appears again and again in various modules, always testing for the same set of conditions}}. These should be replaced with polymorphism.
Still more subtle are {{=:3|the modules that have similar algorithms, but that donโ€™t share similar lines of code}}. This is still duplication and should be addressed by using the Template Method , Strategy pattern. Indeed, most of the design patterns that have appeared in the last fifteen years are simply well-known ways to eliminate duplication. So too the Codd Normal Forms are a strategy for eliminating duplication in database schemae. OO itself is a strategy for organizing modules and eliminating duplication. Not surprisingly, so is structured programming. I think the point has been made. Find and eliminate duplication wherever you can.

Humans are really good at mixing them in one place when they write code.
This hurts the long term maintainability of the code. Its reader will lack in-the-moment knowledge possessed by writer and will have to constantly switch mental gears.
Making it harder for them to understand the system and making the defect introduction more likely.
Ideally, you want for each function/etc to descend only 1 level of abstraction.
Hence the secret is that every well-designed software module wants to become a DSL for the problem it's solving ๐Ÿ™‚.
Unfortunately, from the writer's perspective, it's hard to notice when you start violating this principle.
I believe a relevant improvement in tooling can help developers to be more productive. And improve the communication between different parts of the team by providing them with better vocabulary to discuss the system.
Notes
Initial long version
The Software Industry has by no means settled on what does the "good code" mean in all details. But there are some broad principles that have emerged. One of the key ones being an appropriate separation of different [[level of abstraction]].
Humans are really good at mixing different [[level of abstraction]] in one place at the moment when they write the code.
But that hurts the long term maintainability of the code. As the person who is going to read the code will lack the contextual understanding of the broader system and will have to constantly switch mental gears.
Making it harder for them to understand the system and making the defect introduction more likely.
So what you ideally want is for each function/etc to descend only 1 level of abstraction.
If you are to follow this principle to it's logical conclusion what you'll end up with is each module becoming a kind of DSL for the problem it is solving.
Hence the secret is that every well designed software module want to become a DSL ๐Ÿ™‚.
Unfortunately, from the writer's perspective it's rather hard to notice when you start violating this principle.
I believe an improvement in tooling on this level can help developers to be more productive. And improve the communication between technical and non technical parts of the team by providing them with the new vocabulary to discuss the problem.
you don't allways go there though as making it explicit /etc implied additional cost
Unfortunately it's rather hard, from writer perspective, to detect when you're violating this principle
good software design wants to become a DSL?
layers of abstraction leading to better undestanding between product people and SDE
readability of the code
explicit internal dsl
look through my ideas?
Something about transaction costs/efficiency of labor allocation?
On costs of remote work