[HN Gopher] Design Pressure: The Invisible Hand That Shapes Your...
       ___________________________________________________________________
        
       Design Pressure: The Invisible Hand That Shapes Your Code
        
       Author : NeutralForest
       Score  : 119 points
       Date   : 2025-05-25 13:51 UTC (9 hours ago)
        
 (HTM) web link (hynek.me)
 (TXT) w3m dump (hynek.me)
        
       | 1317 wrote:
       | [video]
        
       | da39a3ee wrote:
       | I'm not sure I'd take design advice from someone who thought
       | attr.ib and attr.s were a good idea. On the other hand he points
       | out that DDD is a vacuous cult, which is true.
        
         | skydhash wrote:
         | DDD is nice especially in the first phase. All the concepts are
         | actually rehashed from earlier principles. There's nothing
         | fully new there.
        
         | wilkystyle wrote:
         | > _I 'm not sure I'd take design advice from someone who
         | thought attr.ib and attr.s were a good idea_
         | 
         | Can you elaborate?
        
           | hynek wrote:
           | that's a reference to my attrs library which is what data
           | classes are based on. It originally used
           | @attr.s         class C:             x = attr.ib()
           | 
           | as its main api (with `attr.attrs` and `attr.attrib` as
           | serious business aliases so you didn't have to use it).
           | 
           | That API was always polarizing, some loved it, some hated it.
           | 
           | I will point out though, that it predates type hints and it
           | was an effective way to declare classes with little "syntax
           | noise" which made it easy to write but also easy to read,
           | because you used the import name as part of the APIs.
           | 
           | Here is more context:
           | https://www.attrs.org/en/stable/names.html
           | 
           | I REGRET NOTHING
        
         | switchbak wrote:
         | I'd call out patternitis and over-OOPification way before I'd
         | criticize DDD. Yes, the latter can go too far, but the two
         | former cases are abused on a much more frequent basis. Happily
         | the pattern crazyness has died down a lot though.
        
       | g958198 wrote:
       | i've cultivated the perception of what op calls design pressure
       | my whole career as the primary driver behind code and her shape.
       | i think it's the most important aspect of a successful
       | architecture, and it's purely intuition based, which is also why
       | there's no silver bullet. i've seen people take most well
       | intended best practices and drive them into the ground because
       | they lack the design pressure sense.
       | 
       | i believe that design pressure sense is a form of taste, and like
       | taste it needs to be cultivated, and that is can't be easily
       | verbalized or measured. you just know that your architecture is
       | going to have advantageous properties, but to sit down and
       | explain why will take inordinate amount of effort. the goal is to
       | be able to look at the architecture and be able to see its
       | failure states as it evolves through other people working with
       | it, external pressures, requirement changes, etc. over the course
       | of 2, 3, ... 10, etc. years into the future. i stay in touch with
       | former colleagues from projects where i was architect, just so
       | that i can learn how the architecture evolved, what were the pain
       | points, etc.
       | 
       | i've met other architects who have that sense, and it's a joy to
       | work with them, because it is vibing. conversly "best practices
       | or bust" sticklers are insufferable. i make sure that i don't
       | have to contend with such people.
        
         | layer8 wrote:
         | This reminds me of the concept of "forces" [0][1][2] in design-
         | pattern descriptions. To decide for or against the use of a
         | given design pattern, or to choose between alternative design
         | patterns, one has to assess and weigh the respective forces in
         | the particular context where it is to be used. They are called
         | forces because they collectively pull the design in a certain
         | direction. Just a different physics analogy versus "pressure".
         | 
         | [0]
         | https://www.cs.unc.edu/~stotts/COMP723-s13/patterns/forces.h...
         | 
         | [1] https://www.pmi.org/disciplined-agile/structure-of-
         | pattern-p...
         | 
         | [2] Chapter 19 in "Pattern languages of program design 2", ISBN
         | 0201895277
        
         | skydhash wrote:
         | Code is for communicating with humans primarily, even though it
         | needs to be run on a machine. All the patterns, principles, and
         | best practices is to ease understanding and reasoning by other
         | people, including your future self. Flexibility is essential,
         | but common patterns and shared metaphors work wonders.
        
           | rowanG077 wrote:
           | That's terribly short sighted. You can have a very clear
           | architecture and code which cannot support the use cases
           | required without almost starting from scratch.
        
             | semicolon_storm wrote:
             | You can also have the most flexible system ever designed,
             | but if the rest of your team doesn't understand it then
             | good luck implementing that required use cases
        
               | rowanG077 wrote:
               | Sure, both extremes are shortsighted. I wasn't arguing
               | for that, to be clear. I'm just saying clarity and ivory
               | tower architecturing has little value if your system
               | can't actually support the intended use case.
               | 
               | Which is what the person I was replying to said with
               | "Code is for communicating with humans primarily, even
               | though it needs to be run on a machine.". If the primary
               | purpose is communication with other humans we wouldn't
               | choose such awkward languages. The primary purpose of
               | code is to run and provide some kind of features
               | supporting use cases. It's really nice however if humans
               | can understand it well.
        
           | immibis wrote:
           | That aphorism is completely incorrect. Code is primarily for
           | communicating with a machine. If the purpose was to
           | communicate with humans, we'd use human languages. Lawyers do
           | that.
           | 
           | The code does also need to be understandable by other humans,
           | but that is not its _primary_ purpose.
        
             | skydhash wrote:
             | So why do we have Java, Kotlin, Scala, Groovy, and Clojure,
             | all targeting the JVM? And many such families?
             | 
             | The only thing that matter to the machine is opcodes and
             | bits, But that's alien to human, so we map it to assembly.
             | Any abstractions higher than that is mostly for reasoning
             | about the code and share that with other people. And in the
             | process we find some very good abstractions which we then
             | embed into programming languages like procedure,
             | namespacing, OOP, patterns matching, structs,
             | traits/protocols,...
             | 
             | All these abstractions are good because they are useful
             | when modeling a problem. The some are so good then it's
             | worth writing a whole VM to get them (lisp homoiconicity,
             | smalltalk's consistent world representation,...)
        
               | rowanG077 wrote:
               | Because a secondary goal of code is communication with
               | other humans. That means readability is still a highly
               | valuable trait. Just not as valuable as the primary
               | purpose.
        
             | Mikhail_Edoshin wrote:
             | I'd say code is a machine. Even code in a high-level
             | language. Code machine is somewhat special because its
             | details look like words. This misleads us into believing we
             | can reason with these words. We cannot. We can use them to
             | make the machine itself, but the only way to explain how it
             | works is to write a normal technical description and the
             | normal way to understand it should begin with reading that
             | description. (There's no standard for a normal technical
             | description though.)
        
             | necovek wrote:
             | While you are obviously right about it not being the
             | _primary_ purpose, here it seems the discussion is about
             | designing for long term maintainability vs just running
             | code.
        
               | rowanG077 wrote:
               | The person he replied said code is primarily for
               | communicating with other people. I'm not sure how else to
               | interpret that than what is literally written down.
        
         | osigurdson wrote:
         | Zen and Art of Motorcyle maintenance is a good reference.
         | 
         | Also, it is good to remember what game is actually being
         | played. When someone comes up with a popularizes a given "best
         | practice", why are they doing so? In many cases, Uncle Bob
         | types are doing this just as a form of self promotion. Most
         | best practices are fundamentally indefensible with proponents
         | resorting to ad-hominem attacks if their little church is
         | threatened.
        
       | loevborg wrote:
       | Great talk, there's a lot I can relate to in here.
       | 
       | I find this topic difficult to navigate because of the many
       | trade-offs. One aspect that wasn't mentioned is temporal. A lot
       | of the time, it makes sense to start with a "database-oriented
       | design" (in the pejorative sense), where your types are just
       | whatever shape your data has in Postgres.
       | 
       | However, as time goes on and your understanding of the domain
       | grows, you start to realize the limitations of that approach. At
       | that point, it probably makes sense to introduce a separate
       | domain model and use explicit mapping. But finding that point in
       | time where you want to switch is not trivial.
       | 
       | Should you start with a domain model from the get-go? Maybe, but
       | it's risky because you may end up with domain objects that don't
       | actually do a better job of representing the domain than whatever
       | you have in your SQL tables. It also feels awkward (and is hard
       | to justify in a team) to map back and forth between domain model,
       | sql SELECT row and JSON response body if they're pretty much the
       | same, at least initially.
       | 
       | So it might very well be that, rather than starting with a domain
       | model, the best approach is to refactor your way into it once you
       | have a better feel for the domain. Err on the side of little or
       | no abstraction, but don't hesitate to introduce abstraction when
       | you feel the pain from too much "concretion". Again, it takes
       | judgment so it's hard to teach (which the talk does an admirable
       | job in pointing out).
        
         | bubblyworld wrote:
         | Pretty naive question, but what differentiates a "domain model"
         | from these more primitive data representations? I see the term
         | thrown around a lot but I've never been able to grok what
         | people actually mean.
         | 
         | By domain model do you mean something like what a scientist
         | would call a theory? A description of your domain in terms of
         | some fundamental concepts, how they relate to each other, their
         | behaviour, etc? Something like a specification?
         | 
         | Which could of course have many possible concrete
         | implementations (and many possible ways to represent it with
         | data). Where I get confused with this is I'm not sure what it
         | means to map data to and from your domain model (it's an actual
         | code entity?), so I'm probably thinking about this wrong.
        
           | metayrnc wrote:
           | For me domain model means capturing as much information about
           | the domain you are modeling in the types and data structures
           | you use. Most of the time that ends up meaning use Unions to
           | make illegal states unrepresentable. For example, I have not
           | seen a database native approach to saving union types to
           | databases. In that case using another domain layer becomes
           | mandatory.
           | 
           | For context:
           | https://fsharpforfunandprofit.com/posts/designing-with-
           | types...
        
           | skydhash wrote:
           | A quick example can be found with date. You can store it in
           | ISO 8601 string and often it makes more sense as this is a
           | shared spec between systems. But when it comes to actually
           | display it, there's a lot of additional concerns that creep
           | in such as localization and timezones. Then you need to have
           | a data structure that split the components, and some
           | components may be used as keys or parameters for some logic
           | that outputs the final representation, also as a string.
           | 
           | So both the storage and presentation layer are strings, but
           | they differs. So to reconcile both, you need an intermediate
           | layer, which will contains structures that are the domain
           | models, and logic that manipulate them. To jump from one
           | layer to another you map the data, in this example, string to
           | structs then to string.
           | 
           | With MVC and CRUD apps, the layers often have similar models
           | (or the same, especially with dynamic languages) so you don't
           | bother with mapping. But when the use cases becomes more
           | complex, they alter the domain layer and the models within.
           | So then you need to add mapping code. Your storage layers may
           | have many tables (if using sql), but then it's a single
           | struct at the domain layer, which then becomes many models at
           | the presentation layer with duplicate information.
           | 
           | NOTE
           | 
           | That's why a lot of people don't like most ORM libraries.
           | They're great when the models are similar, but when they
           | start to diverge, you always need to resort to raw SQL query,
           | then it becomes a pain to refactor. The good ORM libraries
           | relies on metaprogramming, then they're just weird SQL.
        
             | groone wrote:
             | ORM libraries have Value conversion functionality for such
             | trivial examples https://learn.microsoft.com/en-
             | us/ef/core/modeling/value-con...
        
           | galaxyLogic wrote:
           | To me domain model is an Object-Oriented API through which I
           | can interact with the data in the system. Another way to
           | interact would be direct SQL-calls of course, but then users
           | would need to know about how the data is represented in the
           | database-schema. Whereas with an OOP API, API-methods return
           | instances of several multiple model-classes.
           | 
           | The way the different classes are associated with each other
           | by method calls makes evidednt a kind of "theory" of our
           | system, what kind of objects there are in the system what
           | operations they can perform returning other types of objects
           | as results and so on. So it looks much like a "theory" might
           | in Ecological Biology, m ultiple species interacting with
           | each other.
        
       | Noumenon72 wrote:
       | There was a comment on here saying this was an implied diss of
       | SQLModel, but now that I came back to reply to it it's gone.
       | Weird. Since it's implied I couldn't find it in the slides.
        
       | vinipolicena wrote:
       | Parts of the talk remind me of https://www.amundsens-maxim.com/
        
       | knallfrosch wrote:
       | I had the reverse problem a month ago. Greenfield project without
       | existing data, domain model or API. I had no reason to model the
       | API or persistence layer any different than the domain model, so
       | I implemented the same class 3 times, with 2 mappings on top. For
       | what? Well at some point, you will have API consumers and
       | existing data and you need to be able to change the then-existing
       | system.
        
       | leecommamichael wrote:
       | Interesting, perhaps modern conveniences encourage coupling.
       | 
       | No wonder there are so many single-monitor, no-LSP savants out
       | there.
        
       | HappMacDonald wrote:
       | There are certainly times I would love to see a presentation like
       | this reformatted as an article.
       | 
       | I tried pulling out the Youtube transcript, but it was very
       | uncomfortable to read with asides and jokes and "ums" that are
       | all native artifacts of speaking in front of a crowd but that
       | only represent noise in when converted to long written form.
        
         | hynek wrote:
         | Shouldn't some AI be able to clean that up for you? This seems
         | something LLMs should be well-suited for.
         | 
         | ---
         | 
         | FWIW, I'm the speaker and let me be honest with you: I'm super
         | unmotivated to write nowadays.
         | 
         | In the past, my usual MO was writing a bunch of blog posts and
         | submit the ones that resonated to CfPs (e.g.
         | <https://hynek.me/articles/python-subclassing-redux/> -
         | <https://hynek.me/talks/subclassing/>).
         | 
         | However, nowadays thanks to the recent-ish changes in Twitter
         | and Google, my only chance to have my stuff read by a
         | nontrivial amount of people is hitting HN frontage which is a
         | lottery. It's so bad I even got into YouTubing to get a roll at
         | the algorithm wheel.
         | 
         | It takes (me) a lot of work to crystallize and compress my
         | thoughts like this. Giving it as a talk at a big conference, at
         | least opens the door to interesting IRL interactions which are
         | important (to me), because I'm an introvert.
         | 
         | I can't stress enough how we're currently eating the seed corn
         | by killing the public web.
        
       ___________________________________________________________________
       (page generated 2025-05-25 23:00 UTC)