Learning Software Architecture

(matklad.github.io)

491 points | by surprisetalk 12 hours ago

30 comments

  • CSMastermind 8 hours ago
    I'll give you the cheat sheet:

    - Good design is a single idea pervaded throughout.

    - More generally, your goal should be to minimize surprise.

    - If your system allows it, people will do it.

    - Everyone will not just. If your solution starts with "if everyone will just..." then you don't have a solution.

    - Isolate the parts of your system that transform data from the ones that use it. Data models outlive code.

    - Coupling is the root of most evil.

    - Versioning is inevitable.

    - Make state explicit.

    - Every piece of information should have a single source of truth.

    - You should spend more time thinking about naming things correctly.

    - If testing is difficult, the design is wrong.

    - You will regret every undocumented decision.

    - Communication is a tax that you should justify before paying it.

    Remember that the job of an engineer at any level is to use rules of thumb to solve problems for which there is incomplete information.

    • miki123211 2 hours ago
      I don't agree with all of these, but I'll add a couple of my own:

      - The ultimate goal of software is to solve the immediate problem at hand. The secondary goal of software is to solve likely future problems with as little work as possible. Any bad design which is better on those goals than a good design is actually a good design.

      - Make your interfaces easy to use correctly and hard to misuse. Think of how people unfamiliar to the project will interact with them, make the obvious way be the correct way.

      - Correct code should be easy to write; suspicious code should stand out.

      - Shift bugs left.

      - Fixing a bug class is better than fixing a bug.

      - Interfaces are harder to change than implementations. An ugly implementation is ok if it has the correct interface.

      - Use comments and documentation to explain why the code is the way it is. If it feels like there's a simpler way to do it, but that simpler way wouldn't actually work due to a constraint some people may be unaware of, document that.

      - Don't repeat yourself; when it comes to data. If you store a single fact in multiple places; those places will inevitably get out of sync, and that causes bugs.

      - There's a cost to straying off the well-trodden path. Don't be afraid to do so when it's truly worth it, but don't underestimate that cost. Worse (boring) technology is often better technology.

      - Think in terms of expected value. Think not "Is this thing worth doing?", but "Is this thing worth doing, compared to the other things we could be doing instead?"

      - Even if you think you're smarter than everybody else, intelligence isn't always enough, some problems can't be discovered until they happen. Other people have worked longer on this problem than you have. Learn from their mistakes.

      - Friction is the silent killer.

    • laszlojamf 8 hours ago
      I'd add

      - data migrations are inevitable and should be planned for (corollary of versioning)

      - planning is good, sometimes you just have to try things out

      - everything costs money. Designing without costs in mind will force hard choices down the line

      • AnimalMuppet 7 hours ago
        I'll add another to that:

        - Code lives longer than you expect. You forget sooner than you expect. Make a readme/architecture overview/theory of operation document. Put more in it than you think is needed. Check it in with the code.

    • RobRivera 7 hours ago
      I wish I could buy you a beer, as this is very validating. I have been building a video game for over a year. But more importantly I have been building a sustainable engine with a distinct data pipeline, resource rendering/management layer fully decoupled, explicit catalogueing of viable state transformation modes, and honestly, most of your list is absolutely applicable. Even tho it is solo, the constraints of my engine guides forgetful me to 'this is the way to add this weird new feature that arose from testing because reasons' without having to have a tome of 'if you want to build a new sound effect that executes at a particular state transformation multiple times, here is how you do it'

      Cheers

      • embedding-shape 3 hours ago
        Ah, the infamous "I believe I'm building a video game, but in reality I'm building a video game engine and I don't realize it yet" every game developer goes through at least once, god speed to you :)
        • RobRivera 2 hours ago
          Its been such a fun endeavor
    • munk-a 2 hours ago
      I work in this space as well - I know that my particular work is much less abstract (we're modeling the healthcare industry) than some others.

      But as a designer of the system you must understand the industry and while you don't need to embrace their terminology and modeling habits fully, you must understand their rationale and how they view the data set. There are some places where we've intentionally simplified complications of the healthcare market to eliminate needless (to us) over definitions and provide a more unified modeling. But these changes took significant comprehension of the problem area to make with confidence.

      > You should spend more time thinking about naming things correctly.

      On this point in particular. Names never die - that's a lie, occasionally they do, but it takes an extreme amount of effort to enforce a renaming. It really is worth spending a big bulk of time letting SMEs stew with naming proposals to make sure you bases are covered. You can force through a few concepts but your business wing (sales, marketing) will constantly put pressure on you towards industry terminology and force your model to adhere to the current view of the industry. If you decide to break with that that break must be decisive and obvious in intent.

      Oh, the single biggest attribute of software to emphasize is maintainability. How much will this cost to build is one question - how much will this cost to run (not just infra but compounding feature requests and code refactoring and maintaining third party software versions etc...) is the far more impactful.

    • embedding-shape 6 hours ago
      Missing the single most important thing, that people seemingly are purposefully trying to avoid nowadays for some reason:

      - It depends

      No solution I've come across, is a solution for everything, everywhere. It's almost always context dependent, and something that is right in one place, can be utterly wrong in another, and there is no universal truths regarding design and architecture.

      The more flexible you can be with "right tool for the right job", the easier time you'll have designing, because you're no longer trying to shoehorn in things that are "right" and "correct".

      > - You should spend more time thinking about naming things correctly.

      This should almost be on the list twice too, the amount of people who couldn't care less about naming, is so damn high, but if people just cared a tiny bit, it'd solve so much future confusion. Whenever I get pulled into helping a "legacy project" or whatever, establishing a "true vocabulary" based on what people actually call things, is the very first thing to do, because it always uncovers that people been talking about different things the entire time.

    • bfivyvysj 5 hours ago
      Great list but I dunno about coupling being evil, it is literally the only place anything important happens.
    • kachnuv_ocasek 4 hours ago
      What exactly do you mean by “make state explicit”?
      • munk-a 2 hours ago
        Minimizing side effects (e.g. functional programming) is a good habit in general. But when we're talking at the scale of a company's entire software solution state is the enemy of everything that is good.

        You never want to work on a platform with 500k lines of code any of which could mutate variable state at will and the more you can isolate or simplify state usage the better your life will be.

      • embedding-shape 2 hours ago
        Depends on the language I'd say, but overall, try to keep state in as few places as possible, and make it more obvious when it's being used. Modern example would be Rust defaulting to immutability for variables, and makes it very clear when you should expect that this variable actually carries state rather than just a value, by prefixing it with `mut `. Other languages might make it the other way around, making constants/read-only variables stick out, and defaulting to "hiding that they have state" basically.
    • mwexler 8 hours ago
      Can you explain the last one? What types of communications are you suggesting an arch would avoid?

      Otherwise, a very wise list!

      • murkt 8 hours ago
        You can make the feature with one colleague, or you can call in five more people to weigh in and do their parts of the work.

        If you involve five more, the result could be better in theory, but it will certainly take MUCH more time because of communication overhead.

        • munk-a 2 hours ago
          Pretalking is highly valuable. Making sure that key stakeholders have an aligned vision and are invested in defending it before opening up a discussion (or dictate, depending on the culture) to a wider audience is necessary. Occasionally expect that the stakeholders and you got it wrong and you'll need to invest time into rebuilding the solution, but, if you're honest with yourselves and diligent, assume that generally the expert subgroup will supply a comprehensive solution.
      • rawgabbit 7 hours ago
        Not the OP. However, in my experience, the "tax" of communication is that everything has winners and losers. You can state that the "1+1=2" or "the sky is blue" and someone will lose politically. You have to prepare yourself to defend your position even if 19 out of 20 agree with you; because the one person who disagrees with you has the most to lose.
      • ragnese 5 hours ago
        When I read it, I assumed it meant like network communication in your program. File and network I/O having/being a "tax" makes sense to me.
      • serial_dev 2 hours ago
        Just one more alternative interpretation… I thought it’s about systems calling into other systems, making everything slower, more complicated and brittle…

        But maybe it’s about discussing an issue with 10 other people from different teams when it’s not necessary.

        But we will never now. I guess OP didn’t want to pay the communication tax on expressing this idea clearly :)

      • theteapot 8 hours ago
        Completely agree. Had me until the very last point. WTF. Communicate.
        • murkt 8 hours ago
          The last one is about involving less people. You don't have to read it as "shut up and keep your thoughts for yourself". I read it more like "Do we really need to have six people working on this feature/present in this call?"
          • munk-a 2 hours ago
            I strongly prefer the phrasing of "When do we actually need to have six people involved on this?" It's often valuable to set a momentum and prune obviously poor decision branches before bringing proposals to a wider audience.
          • ulbu 7 hours ago
            well, it needs to be communicated better.
        • gavmor 7 hours ago
          I wonder if they don't mean "between systems".
          • collabs 7 hours ago
            > Communication is a tax that you should justify before paying it.

            I thought it meant like keep things as local as possible. Like within the same process, within the same machine, avoid going through the network because staying on the processor is always the fastest, going to ram is next fastest, and if you need to communicate across the network it is always slowest

            • alternatex 7 hours ago
              I don't think performance advice should be part of a general architectural principles list, so I don't think that's what they meant. Otherwise might as well add "avoid nested loops", etc, and then it devolves into a general programming advice list.

              Performance is and always was something dependent on the domain rules. You don't start architecting for performance before understanding requirements so why make it a pillar of all architecture.

    • ofrzeta 8 hours ago
      > - Make state explicit.

      Don't save the same state in more than one place.

      • munk-a 2 hours ago
        You can and you must replicate state in a complex system. The key is that state should always have an explicit owner and other carriers of that state should understand that their version of the state has some inherent lag or inconsistency off the true state.

        There's a reason caching (and it's invalidation) is one of the two hardest problems in computer science.

    • avgDev 4 hours ago
      Good list, although things get weird when you are limited by some legacy software/database.
      • munk-a 1 hour ago
        You are always limited by some legacy software/database.

        If you're not limited by some legacy software/database initially then you will have such a large problem scope that you'll create your own legacy software/database internally.

        I'll grant that if your problem is really simple and straightforward you can sometimes just build an ideal greenfield solution that's perfect and wonderful - but those problems are rarely the problems that are profitable to solve.

    • electrosphere 8 hours ago
      Good list!

      One addition?

      * start with a modular monolith

      • munk-a 1 hour ago
        I don't want that to be limited to just architecture though - proper initial factoring of a software product is invaluable at the large and most microscopic level.
      • perkovsky 5 hours ago
        Yes. I’d add: design the module boundaries before splitting deployment.

        A modular monolith still forces you to name ownership, data boundaries and invariants, but without making every mistake a networking/ops problem.

    • ivanjermakov 6 hours ago
      > If testing is difficult, the design is wrong

      Or domain/IO is cumbersome. Think videogames.

      • embedding-shape 5 hours ago
        That's one of the few places where creating abstractions makes a lot of sense, especially in video games. You really, really want as much to be automated tested as humanly possible, because the user/player surface ends up enormous and testing gets "expensive" much quicker than a typical SaaS.
      • nullsanity 5 hours ago
        Nope, that's just the design being wrong. Factorio has no issues with testing.

        It doesn't matter if nobody is interesting it fixing it, video games have been and almost always are written like shitty single use code, (Even when it's not) so it shouldn't surprise anyone that proper test harnesses aren't available in engine.

    • thedetailsguy 8 hours ago
      Thanks for sharing! Really agree with #2 even though ultimately - we can only minimise rather than totally eliminate.
    • tristor 8 hours ago
      As a corollary to

      > Communication is a tax that you should justify before paying it.

      > Every piece of information should have a single source of truth.

      - Do as much as possible on a single system and minimize sharing state.

      - Recognize that every system is distributed, it's just a question of how and where.

      One of the biggest ills I observe with most modern software systems is that we've gone full tilt towards things like microservices which require synchronizing state across multiple interdependent parts. Regardless of how clean the abstractions or how well contracted the APIs, doing all of that copying and state synchronization is going to result in problems: performance problems, cost problems, and synchronicity problems.

    • dmitrijbelikov 5 hours ago
      Good, really good. But not real. You can achieve such ideal only without human which makes no sense.
    • pelasaco 2 hours ago
      then comes the order from your manager: "Put it in production and we can work through this list later".. or even worse, now with Claude, managers are putting stuff "Quick and Dirt" in production and you have to maintain it.. sadly true story..
      • munk-a 1 hour ago
        The job of an architect and good technical management is to teach non-technical management the true costs of their decisions. It's not an easy job by any measure and LLM driven know-nothings in management can make it far more frustrating. But, you need to make sure you're capturing the true[1] costs of decisions to the best of your ability including externalities.

        1. You're allowed to lie for expediency, but make sure you never delude yourself into believing your own lies.

    • john_builds 8 hours ago
      great list! ty
  • mpweiher 10 hours ago
    The recommendations are often very good, for example Ousterhouts A Philosophy of Software Design, but seem to be on software development in general, not actually software architecture in particular.

    For that, I would recommend the classic texts, such as Software Architecture: Perspectives on an Emerging Discipline (Shaw/Garlan) and really anything you can find by Mary Shaw. Including more recent papers that explore why the field of software architecture did not go the way they foresaw, for example Myths and Mythconceptions: What Does It Mean to Be a Programming Language, Anyhow? or Revisiting Abstractions for Software Architecture and Tools to Support Them

    More practically: look at why Unix pipes and filters and REST are successful, and where they fall down and why. Hexagonal architecture is also key.

    And a plug for my own contribution, linking software architecture with metaobject protocols as a new foundation for programming languages and programming: Beyond Procedure Calls as Component Glue: Connectors Deserve Metaclass Status. An answer to Mary Shaw's Procedure Calls Are the Assembly Language of Software Interconnection: Connectors Deserve First-Class Status.

    Answering the question: if procedure calls are the assembly language, what might a high level language look like? And also maybe that software architecture might have a brighter and more practical future ahead of itself.

    • sroerick 3 hours ago
      What is hexagonal architecture?
    • skydhash 8 hours ago
      > if procedure calls are the assembly language, what might a high level language look like?

      I’m not well versed in PLT and SWE tooling, but isn’t that the base concept around lambda calculus, LISP, APL, clojure, TCL,…? You only need a few data structures and types, a small collection of fundamental functions, then you compose them.

      If there’s one thing that I like about Lisp is that more complex type are always opaque (especially the ones from FFI). I would love to see CLOS implementation for a C-like language, where when you define a struct, what you get is a standard collection of functions.

      • mpweiher 7 hours ago
        > You only need a few data structures and types, a small collection of fundamental functions

        For the implementation: yes. Hence "assembly language". The mistake almost universally made is to confuse that with the abstraction mechanism.

        She showed that it's necessary.

        I showed how to do it.

  • miki123211 10 hours ago
    In this vein, I really recommend "Architecture of Open Source Applications."[1] It's a book series where you learn architecture by example, with each chapter written by a maintainer of the project in question. This lets you learn not only what the architecture is, but what are the constraints that shaped it, usually history and changing project visions.

    Not all chapters are equally good or equally interesting, that's the curse of a multi-author book, and all of them are dated, but I think the book is worth reading nonetheless.

    [1] http://aosabook.org/

  • ah1508 7 hours ago
    I think that words like "clean code" or "beautiful code" does help juniors to learn best practices of software architecture.

      - Junior asks to senior: what did you we use an ORM ?
      - senior answers: because it's cleaner.
      - junior: ???
    
    I prefer when people are able to define a clear list of objectives:

      - maintenable;
      - performant, scalable;
      - efficient;
      - resilient;
      - observable;
      - testable (and tested);
      - secured;
      - readable for new devs that come on board.
    
    Each criteria balance the others, and the more we add criteria the more it helps to make good choice when we hesitate. It is also meaningful for people outside of the dev team, we can reach an agreement with the customer so he knows what he pays for.

    "maintenable" can be also defined, since a project is mostly in maintenance mode during its lifetime (which means the project is successful, which is good !). The ability to incorporate new features without breaking architecture or even without breaking a single method signature is a good starting point.

    Being super careful with abstractions. Here someone wrote something like that: "abstraction often hides how what you want is simple". True, ORM I am looking at you. In most case data should be threaten as first class citizen, it also fosters good collaboration with the DBA.

    Thinking beyond "the happy path" without falling in premature optimization is also a challenge. A nice one, once again to it avoids to go head first in implementing a good idea without considering drawbacks.

    I also tend to imagine that the one that will work on my code had a very bad day so it must be pleasant to read what I wrote. Comments here and there, locale variable here and there even if they can be avoided, variable naming, etc...

    Being selective about frameworks. They are good servant but bad leaders. "Be an engineer, not a frameworker" says an article.

    • munk-a 1 hour ago
      Modular frameworks are worth their weight in gold when compared to "highly opinionated frameworks". I don't mind something that's highly opinionated - and highly opinionated is an excellent trait for a library or tool. That lib/tool likely has a large amount of domain expertise in the particular area it operates in.

      When it comes to frameworks - highly opinionated tends to get corrupted into "We have this hammer and suddenly everything looks like a nail" - it doesn't always happen and it doesn't always bite you but when orthodoxies are taken from one domain and applied broadly you run the risk of some of the justifications for that orthodoxy being domain specific and being violated in the wider context.

      So, when it comes to frameworks, I like modularity where I have options to plug in a different ORM or persistence integration layer - where I can swap out the router - or the validator - or any other component that proves a poor fit for our problem. It is especially valuable if there are multiple paradigms expressed in alternatives within the framework's ecosystem since you may find a pre-baked tool that mostly works where you can choose an option with shortcomings that are clear and addressable if ever the need arises.

      To support maintainability it's very important to fight against NIH-ism, that is a constant danger that can soak up resources at an alarming pace - but it's also important to realize that there are some components that you will greatly benefit from tweaking or taking full ownership of with the most difficult problem being trying to figure out which is which.

      I appreciate deeply that your list put maintainability first - that's my opinion as well!

  • ramon156 10 hours ago
    I would like to spend my time more on gaining a mental model of the projects I work on, but I get very demotivated if I start disliking things like the programming language, certain arch. Choices or anything that gets too complex that doesn't seem like its worth my time

    It's heavily dependent on the project, but I feel like working as a "fullstack dev" kind of removes the fun of programming. I'm already spending 40 hrs a week looking at the most dull project I can imagine

    • HumblyTossed 8 hours ago
      > I would like to spend my time more on gaining a mental model of the projects I work on, but I get very demotivated if I start disliking things like the programming language, certain arch. Choices or anything that gets too complex that doesn't seem like its worth my time

      Let it go...

      Not one single project is free of warts. Not a one. And honestly, if the programming language is that big a deal, you're better off jumping ship. We should all be polyglots, but that's up to you.

    • munk-a 1 hour ago
      Analysis paralysis is a danger always - don't aim for perfect, but aim for flexible. Make sure the decisions you're spending the most time on are the most important.

      A well designed data structure is far more impactful on performance and maintainability than framework, language or platform.

      Personally, I work alongside ADHD every day so I need to constantly push to make sure that progress is happening which means picking unimportant decisions and resolving them to focus the remaining open problem space on the decisions that require a lot of careful thought.

    • ambicapter 7 hours ago
      Sounds like you need better emotional regulation.
  • 0xbadcafebee 8 hours ago
    As relates to Systems Engineering: Software architecture is like plumbing architecture. It's certainly very important, but you don't live in plumbing pipes, you live in a house with plumbing. If your plumbing doesn't take the rest of the house into account, it could be a very expensive fix.
  • runningmike 9 hours ago
    Nice read. “ Learning Software Architecture” means understanding that there is no single good answer. It is art and science.

    Read tip: Simplify IT - The art and science towards simpler IT solution https://nocomplexity.com/documents/reports/SimplifyIT.pdf

  • abhik24 11 hours ago
    The Gary Bernhardt talk is truly special. Lots of concepts which will lead you to other interesting places
  • luodaint 7 hours ago
    The architecture assignment that I found most useful did not come from a book. It involved the attempt to articulate my system to an agent session starting with no background information at all.

    If the agent cannot deduce the constraint, then you have to write it out. Conventions for migration. Invariant properties of the authentication protocol. Multi-tenant behavior. This act of articulation – making your implicit reasoning explicit – led to a kind of clarity that several months of construction alone did not bring. Three architectural errors emerged instantly.

    It’s true that learning by doing is the way to go. I would add: learn by explaining it. The agent is an unusually picky audience.

  • zug_zug 8 hours ago
    This guy knows exactly what he's talking about. However, it feels more like a "if you know, you know" rather than relaying the experience/data he's accumulated.

    Let me just say: A lot of people think architecture is how do you build a very complex system with tons of moving components (databases, queues, scaling, reduandancy, failover, dozens of services). I think expert achitecture is being able to answer how do I correctly solve the problem using the fewest of those.

    Genius-level engineering is inventing the zipper, usable anywhere, lightweight, cheap, sturdy, simple to make.

    (I believe he's alluding to this by saying companies follow conways laws and essentially socially construct a lot of work to match up with the number of teams, hence creating a completely unnecessary nightmare of complexity just for the social incentives)

  • senderista 4 hours ago
  • noelwelsh 11 hours ago
    I think this really down plays the value of mental model or strategies for organizing code. Take a compiler: often described as a sequence of transformations on an AST, taken to the extreme in the nanopass framework. That's a really useful mental model, and you can extract that model and apply it in other contexts. For example, many business applications are a sequence of transformations on JSON. So they're basically compilers. That can be good architecture in the right situation.

    You don't have to call a sequence of transformations a compiler. You can say your AST is an algebraic data type, and your transformations are folds (or structural recursions; same thing). Now you have an abstract model that isn't tied to a particular application, and you can more easily find uses for it.

    If you know a bit of maths you might wonder about duals. You will find codata---objects---are the dual of algebraic data. Ok, now we're programming to interfaces. That's also useful in the right context. What's the dual of a fold? An unfold! So now we have another way of looking at transformations, from the point of view of what they produce instead of what they consume. At this point we've basically reinvented reactive programming. And on and on it goes.

    You can find most of this in the literature, just not usually presented in a compact and easy to understand form.

    (Note, the above description is very quick sketch and I'm not expecting anyone to understand all the details from it alone.)

    Shameless self promotion: the book I'm writing is about all these concepts. You can find it here: https://functionalprogrammingstrategies.com/

    • jameshart 10 hours ago
      I’m not sure what part of the article this is attempting to critique.

      But I would say that just because your preferred mental model is an abstract algebraic one where you build an abstract model that can apply to multiple situations doesn’t mean that such an architecture is best for every situation.

      The article talks very clearly about the system and social constraints that it is optimizing for architecturally and ‘turning everything into a fold’ doesn’t immediately strike me as helping to meet the fast-build-feedback needs of the deep contributors and easy-and-safe-to-hack-in-modules needs of the weekend warrriors, which is what are described as the goals of the architecture.

      But it also doesn’t strike me as very clearly not the case that the architecture has some of the features you’re describing.

      It feels rather like you have a pet mental model which you think all architecture should subscribe to, and… I’m sorry but that seems naive.

      • noelwelsh 10 hours ago
        You misinterpreted my comment. Algebraic data types and folds are an example of an architecture, that has application to many situations. They are not the only architecture, and I'm not presenting them as such.

        I am trying to show 1) software architectures are useful, 2) if you abstract them you can find principles and relationships that allow you to transfer them to different domains, and transform them into different models, and 3) there is a lot of depth in software architecture and utility in learning it.

        The article spends most of its time discussing social context in which architecture is developed (I agree it is important, but not everything) and in general downplays the utility of learning about software architecture (e.g. "“software design” is something best learned by doing", and later suggests there is little useful writing on software architecture).

  • NeutralForest 10 hours ago
    Software design/architecture is a strange beast. It feels that if you want to learn it, you should spend time in legacy systems and large codebases of rewrite a project 3 times to explore counterfactuals. A lot of books on the subjects are abstract and give such simple examples, they are useless.
    • sevenzero 9 hours ago
      It's really hard to provide proper guidance on software architecture, because the fundamental deployment strategies differ for each project. For web projects, a lot of people will say Cloud is the best way to deploy, so now you're forced to build your whole project in a "Cloud friendly" architecture.

      When I was learning and being formally educated I regularly only had like 50 bucks to my name, I couldn't even afford the cheapest VPS I could find. So for me learning the architectural ideas of using AWS services where you have to setup credit card information to even register was not feasible. After all I already had a computer, why not learn how to deploy from there? Especially after reading about horror stories of people racking up huge cloud bills due to some slip up. So AWS was out of the window. Next I got myself a book about Microservices which was popular at the time, but quickly learned that they are about organizational structure rather than software architecture, so I never had a reason to try that architecture.

      I still have no idea how to chose the right architecture or make the "correct" decisions on it. I do whatever works and for some reason it still pays my bills. Currently I just use Laravel monoliths for everything and I am pretty sure this is good enough for most web services out there.

      I know the original post wasnt about webapps, it's just where I find myself having the most issues.

    • atulatul 9 hours ago
      >Software design/architecture is a strange beast

      Yes. At one point I thought a set of good programs can be composed into a good architecture. Then at another stage- with agile, etc.- I was thinking about evolutionary architectures.

      But experience and dealing with different kind of problems and systems work best. Also, I have seen Conway's law hold when many other patterns, principles fail.

      Books like Garlan Shaw are good but help if you have some experience. Some other books/ courses like Neal Ford's help, but for me those helped only to know the terms/ ideas. Practice and rewrites, tech-upgrades helped more. Also, books like Michael Nygard's Release It.

    • andyferris 9 hours ago
      My example here is: it’s impossible to know what spaghetti code is until you experience it, and are on the hook for its bugs and outages.

      We hear a lot about it prior and upon experiencing it I could name it. (Like love, I suppose?)

    • skydhash 5 hours ago
      > A lot of books on the subjects are abstract and give such simple examples, they are useless

      They are abstract because architecture is for dealing with pain, and you can’t explain pain. You need to experience it and reflect on what was done wrong to be in trouble. The examples are like a gentle pinch which does not prepare you for pulling a muscle in your back or having a nail in your foot.

      My strategy is to read the books, try to implement the things at least once to get a sense of the costs, and then get back to it once you’re experiencing pain in your project. It may be too late, but you will then learn the lesson.

  • finnnk 9 hours ago
    I'm surprised that it seems no-one has brought up Residuality (see https://www.architecture-weekly.com/p/residuality-theory-a-r...) which is a very interesting take on architecture (as opposed to design) which aligns with my own experiences.

    As well as the book (https://leanpub.com/residuality) the author has one on the philosophy of architecture (https://leanpub.com/architectsparadox).

    • grusgrus 3 hours ago
      Wanted to say thanks for posting this. I found the NDC talk interesting and well presented. Will try to read more about it and, as an exercise, try applying it to my own solutions to see what insights I could gain.
    • 4b11b4 6 hours ago
      Residuality is very interesting. Have you used it in practice?
  • npl 10 hours ago
    I think there is huge space for architecture case studies that help a non coder learn how to critique llm architecture decisions.

    I’m a NP - lots of learning came in clinical rotations where you see real life situations and how they are addressed. I want something like this for software architecture.

    The closest I’ve seen is the open source case study books referenced previously but these are older.

    I’d like to be able to see explanations at various layers of abstraction about why certain decisions are made or not.

  • getnormality 7 hours ago
    A lot of people seem to lean too much on Conway's Law. It takes social organization as primary instead of itself shaped by the nature of a problem. Maybe the reason Sales and Engineering are different departments is because they are different things.
  • jdw64 10 hours ago
    Most codebases eventually take on similar shapes, depending on their size and on the IoC model imposed by the framework.

    And when you try to prevent that IoC from leaking into the domain too much, the design often starts to look like hexagonal architecture.

    Programming often feels like inventing a new form, but in the end we tend to converge on the shapes that previous programmers already discovered.

    • esjeon 10 hours ago
      Perhaps the real job of programmers is (or has been) adapting to new requirements. The art lies in the process, not in the result.
      • jdw64 10 hours ago
        > The art lies in the process, not in the result

        nevertheless, I often deceive myself into thinking that I am inventing a new design. In reality, I am usually just being shaped by the IoC model imposed by the framework and by the pressure of business requirements.

        Only the scale changes. Similar problems tend to leave similar structures behind.

        Sometimes it feels as if earlier generations of programmers have already solved so many of the important problems that all that remains for me is rediscovery.

        But I do not want mere rediscovery. I want to create a new kind of problem. Still, in front of the solidity of established engineering, my small mind sometimes feels as if there is no place left for me.

    • alex1sa 7 hours ago
      [dead]
  • amelius 9 hours ago
    With AI we all have to make the switch from programmer to software architect, I suppose.
    • xyzal 9 hours ago
      With the amount of shit code generated it ain't gonna happen anytime soon.
  • sailfast 7 hours ago
    Immediately favorited as this article and the comments underneath are great reference points and reminders. (Even as someone that's been doing this for awhile)
  • kevinwang 9 hours ago
    Learn by doing? Certainly helpful. But I feel like the real secret is to work with others who are good at software architecture. You can learn very efficiently that way.
  • vova_hn2 5 hours ago
    > the phenomenon of “scientific code”

    I have some experience being a software engineer in a data science team or in a team adjacent to a DS team, a lot of problems that they think are "data science problems" are actually software engineering problems being solved in an extremely convoluted and weird way.

    I think that if DS community wasn't so resistant to basic SE good practices, or involved engineers in making architectural decisions, total time and effort needed to solve some problems would be greatly reduced.

    When I'm in a bad mood, I even entertain a silly conspiracy theory in my head: they do everything in the most ugly and weird way specifically to keep people like me out :)

  • systems 8 hours ago
    there is also The Architecture of Open Source Applications books

    https://aosabook.org/en/

  • woodydesign 11 hours ago
    [flagged]
    • jerf 8 hours ago
      I think of it this way. Software architecture can not be taught. (This is not particularly uncommon, and so not a claim to being particularly special.) But you can sensitize people to the problems they will encounter and solutions they should consider. You can't "teach" someone into being a software architect of 10 "software architecture goodness units", but you can accelerate the rate at which they accumulate SAGUs by doing this.

      In fact, per my parethetical, honestly I would say most things work like this. You can't just pluck people up and drop them five or ten years down the road of experience for nearly anything. What you can do is give them a car and show them the road rather than letting them hack through a jungle with a machete and no map.

      One of my major criticisms of how we teach is that for the most part everyone in the system operates in the belief that we can just stand in front of people and say things for a few hundred hours and they will be magically equipped with completed and refined skills after that process. Too much focus on trying to drop people into some mythical state of "educated" rather than accelerating them through their own journey. A journey that can be highly guided and structured for sure, but where you understand that for all you can clear the road you can't actually take steps for the student.

      "It is also subtraction: removing unnecessary abstraction, ceremony, cleverness, and control."

      This reminds me of one of the most distinct menaces to software architecture I encounter on a regular basis, the person who follows Hexagonal Design or Clean Architecture or MVC or some other Answer To All Architecture, rigorously following it to the letter and insisting that any system that doesn't follow the Answer To All Architecture is prima facie a bad system that needs immediate redesign to bring it into conformance with the ATAA.

      The "answer" to something as complicated as software architecture doesn't fit in a book. In fact it doesn't even fit in a human head; for all the experience I have in network servers I wouldn't expect to be able to sit down and architect a high-performance game engine that could compete in the marketplace. I have ideas about how to do it, sure, but I know that I don't know all the details that people who operate in that space do, and plenty of those details will matter. No one has the breadth of experience to truly tell us all how to architect software, under all circumstances and conditions. Anyone de facto operating as an architect needs to bear that in mind, and while consulting the prior experience is part of that "be in a car on a road and not hacking through a jungle", the supposed set of blessed answers must always be mediated through the task in front of you and not vice versa.

      • mplanchard 7 hours ago
        It’s tangential to your point, which I agree with completely, but this is also exactly why I get so frustrated with the idea that higher education is about acquiring job skills. Ideally, regardless of major, a university teaches you how to think, critically and deeply, and how to learn. If you have those things, job skills are easy to pick up, but instead we treat college like an RPG skill tree, where you’ve got to put points into your intended career path in order to unlock the skills you’ll need to do the job.

        Edit: although I do think university focus is important for subjects that are less about job skills and more about knowledge synthesis, such as most sciences, critical analysis, and so on, if you intend to not just do a job but contribute to the overall knowledge base of the field.

    • faangguyindia 7 hours ago
      I did this both

      1. used Ruby on Rails, got familiar with it

      2. Got rid of it, wrote the part i really need in Go.

      And running with it.

      Achieving scale on commodity VPS at Hetzner.

    • jareklupinski 10 hours ago
      "code on, code off"
      • woodydesign 9 hours ago
        Haha... wax on, wax off. Love this analogy that learning coding as learning Kungfu
    • ulbu 7 hours ago
      so Tao is coinductive
    • dvfjsdhgfv 9 hours ago
      > Laozi gives the complementary warning: “In pursuing learning, every day something is added. In pursuing the Tao, every day something is dropped.” Mastery is not only accumulation. It is also subtraction: removing unnecessary abstraction, ceremony, cleverness, and control.

      Well, your (or your LLM's) interpretation is a bit less nuanced than the original. The verse from DDJ you mention is more about letting go and living a simple life, a bit the opposite of programming where we actually need an adequate level of complexity to handle the complexity of the world.

      As a side note, even if you are not a native English speaker, trying to formulate thoughts without the support of LLMs is very welcome here.

      • joaohaas 8 hours ago
        Definitely a 'your LLM' case here.
    • supriyo-biswas 10 hours ago
      [flagged]
      • woodydesign 10 hours ago
        Correct — LLM helped with the wording. The thought is mine.

        As a non-native English speaker, I’m pretty happy that the final version is more readable and probably sharper than what I would have written alone.

        • tomhow 2 hours ago
          We understand you feeling like it's more important to post polished writing than imperfect writing, as a non-native English speaker. But neither the HN audience nor the guidelines (https://news.ycombinator.com/newsguidelines.html) see it that way.

          AI-translation/editing/polishing takes away all the authenticity and makes the writing seem like it came from a machine, not a person. It's much better if you write in your own voice, even if there are imperfections. The HN audience appreciates the effort.

      • kaycey2022 9 hours ago
        We can't even say something in public these days. All your comment needs is the trigger words or constructions

        - That's why X works. - Not X but Y.

        And some moron will be in the replies, saying "LLM comment". I hate this world. But probably yeah. llm comment.

        • supriyo-biswas 9 hours ago
          Except that their entire profile is like this.
          • macintux 9 hours ago
            So. What.

            People, particularly non-native English speakers, are going to use LLMs to help with their writing. Complaining about it adds nothing to the discussion.

  • maxothex 5 hours ago
    [flagged]
  • lacymorrow 8 hours ago
    [flagged]
  • JoheyDev888 6 hours ago
    [dead]
  • SadErn 11 hours ago
    [dead]
  • rahadbhuiya 10 hours ago
    [dead]