- 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.
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'
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.
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.
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?"
> 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
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.
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.
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.
> 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.
This made me think of the wisdom of learning between Confucius and Laozi in ancient Chinese philosophy.
Confucius treats learning as cultivation: you do not really know something just because you were instructed in it. You know it by practicing, reflecting, making mistakes, and gradually developing judgment.
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.
Software architecture seems to need both. You learn it in a Confucian sense, by doing real work and living with the consequences. You improve it in a Taoist sense, by noticing when the system has accumulated structure that no longer serves the people, incentives, and constraints that actually shape it.
That is why the article’s point about incentives resonates. Architecture is not just what you design on paper. It is what survives contact with the organization that produces and maintains it.
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.
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.
> 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.
People, particularly non-native English speakers, are going to use LLMs to help with their writing. Complaining about it adds nothing to the discussion.
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.
> 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.
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.
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.
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.
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.
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)
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
> 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.
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.)
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.
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).
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.
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.
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.
> 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.
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.
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.
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 :)
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)
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.
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.
- 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.
- 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
- 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.
Cheers
- 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.
Otherwise, a very wise list!
If you involve five more, the result could be better in theory, but it will certainly take MUCH more time because of communication overhead.
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
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.
Don't save the same state in more than one place.
Or domain/IO is cumbersome. Think videogames.
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.
One addition?
* start with a modular monolith
A modular monolith still forces you to name ownership, data boundaries and invariants, but without making every mistake a networking/ops problem.
> 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.
Confucius treats learning as cultivation: you do not really know something just because you were instructed in it. You know it by practicing, reflecting, making mistakes, and gradually developing judgment.
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.
Software architecture seems to need both. You learn it in a Confucian sense, by doing real work and living with the consequences. You improve it in a Taoist sense, by noticing when the system has accumulated structure that no longer serves the people, incentives, and constraints that actually shape it.
That is why the article’s point about incentives resonates. Architecture is not just what you design on paper. It is what survives contact with the organization that produces and maintains it.
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.
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.
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.
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.
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.
- 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.
People, particularly non-native English speakers, are going to use LLMs to help with their writing. Complaining about it adds nothing to the discussion.
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.
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.
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.
https://github.com/wangjohn/mit-courses/blob/master/6.033/Pr...
"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.
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/
Read tip: Simplify IT - The art and science towards simpler IT solution https://nocomplexity.com/documents/reports/SimplifyIT.pdf
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.
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)
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
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.
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/
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.
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).
As well as the book (https://leanpub.com/residuality) the author has one on the philosophy of architecture (https://leanpub.com/architectsparadox).
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.
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.
We hear a lot about it prior and upon experiencing it I could name it. (Like love, I suppose?)
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.
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.
[1]: https://en.wikipedia.org/wiki/SOLID [2]: https://www.youtube.com/watch?v=wo84LFzx5nI
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 :)
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.
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.
https://aosabook.org/en/