[HN Gopher] Software Design Principles I Learned the Hard Way
       ___________________________________________________________________
        
       Software Design Principles I Learned the Hard Way
        
       Author : thunderbong
       Score  : 30 points
       Date   : 2024-04-25 09:36 UTC (3 days ago)
        
 (HTM) web link (read.engineerscodex.com)
 (TXT) w3m dump (read.engineerscodex.com)
        
       | Waterluvian wrote:
       | > Far too many times I've seen code that looks mostly the same
       | try to get abstracted out into a "re-usable" class.
       | 
       | I've had a hard time explaining this but I know it when I see it.
       | Two things that are the same shape but aren't really semantically
       | related. So if you try to share code, your abstraction breaks the
       | moment they start to inevitably express how they're not related.
        
         | Maxatar wrote:
         | Sure, if the abstraction is very broad like a class, but I find
         | I have a lot of success factoring out code that mostly looks
         | the same into a plain function.
        
       | foobarkey wrote:
       | +1000 to PRY, if something needs to possibly evolve separately
       | dont force it into some shared abstraction, I think DRY probably
       | causes the most bad code but we still keep doing it.
       | 
       | Agree with mocks also, currently not even using them, just go
       | with integration tests and set db back to known state between
       | every test run, oh and wiremock for rest
        
       | monero-xmr wrote:
       | The hill I'll die on is to avoid classes, everywhere. You don't
       | need classes. Just use functions and structs (or plain objects,
       | etc.). OOP was a terrible mistake and mixing state with logic was
       | a major catastrophe that poisoned a few generations of engineers.
       | Burn the Gang of Four design patterns and scatter the ashes into
       | the ocean.
        
         | foobarkey wrote:
         | I will join you on that hill, just make a pureish
         | function/method that does the thing its supposed to do and job
         | done. Although in 10% of cases OOP and inheritance is useful
        
         | mvdtnz wrote:
         | From 15 years industry experience my biggest takeaway is to
         | ignore advice from anyone who claims their point of view
         | applies "everywhere".
        
           | monero-xmr wrote:
           | Well I have over 20 years experience so maybe you need 5 more
           | years or so
        
         | klysm wrote:
         | I generally agree with you. The only time I find classes make
         | sense is when you need a stateful imperative handle. Those
         | cases are rare.
        
       | mvdtnz wrote:
       | Absolutely agree with 1 ("Maintain one source of truth"), not
       | just in a service but in an architecture. I am dealing with a
       | microservice architecture where decisions have been made to store
       | the same state across different services. Needless to say this is
       | massively challenging to keep in sync and requires a ton of work
       | keeping the production systems consistent. Not to mention the
       | difficulty of setting up proper test environments where any given
       | data store might be reset or refreshed at any given moment,
       | causing all kinds of havoc and causing people to lose trust in
       | the test environments.
       | 
       | For number 2, (please repeat yourself), the truth is in the
       | middle. Don't repeat yourself when the proper abstractions
       | present themselves, and always be on the lookout for a good
       | abstraction. But don't force an abstraction where it's not
       | appropriate. Where to draw the line is the hard part and in my
       | opinion comes from experience and intuition. If in doubt, repeat
       | yourself.
       | 
       | Number 3 (overused mocks) I find myself swimming against the tide
       | of popular opinion. I think mocks are very valuable for unit
       | testing. This doesn't mean you don't write your integration tests
       | without the mocks, but I still think there's a ton of value in
       | being able to quickly write a large number of fast unit tests
       | that say "when this component does this, I expect the system
       | under test to do that". As for leaking implementation details, I
       | don't think it's such a big deal at the unit testing level. The
       | details need to be tested somewhere. I appreciate this is an
       | increasingly unpopular viewpoint but it has served me well.
       | 
       | For number 4 (minimize mutable state) this is software
       | engineering 101, but always bears repeating.
        
       | xwowsersx wrote:
       | What I've noticed over the years is that software engineers tend
       | to sometimes mistakenly believe that when they are, for example,
       | modeling some domain that they are involved in some sort of
       | Aristotelian categorization exercise wherein they are trying to
       | capture the true essence of some pure Platonic form. In reality,
       | whenever anything comes under the umbrella of software, we are
       | doing it not because we are interested in some ontological sense
       | of the thing under consideration, but because it has some
       | usefulness for a particular line of business. This I think is the
       | key thing. There are unifications and abstractions that make
       | sense in a pure theoretical sense, but that serve no purpose when
       | it comes to software that is meant to serve some practical end.
        
       ___________________________________________________________________
       (page generated 2024-04-28 23:00 UTC)