[HN Gopher] Software Architecture Patterns: 5 minute read
       ___________________________________________________________________
        
       Software Architecture Patterns: 5 minute read
        
       Author : jlee11
       Score  : 273 points
       Date   : 2021-10-28 11:27 UTC (11 hours ago)
        
 (HTM) web link (orkhanscience.medium.com)
 (TXT) w3m dump (orkhanscience.medium.com)
        
       | nealabq wrote:
       | You don't start by choosing an architecture. You start by
       | understanding the problem and the pieces in the solution space.
       | You then figure out how those pieces can work together to solve
       | the problem. After that you can see the system as nested
       | subsystems and interactions, which you can draw as diagrams and
       | call it an architecture.
       | 
       | So I see "architecture" more as a teaching and communication
       | technique, applied after the fact. Altho since we're always
       | moving between the details and the big picture, having organized
       | abstractions (ie an architecture) in mind will help keep the
       | design clean.
       | 
       | The architecture evolves and sharpens as a system comes together.
       | And this evolving architecture provides the team with a common
       | terminology and overall direction.
       | 
       | But you rarely start by choosing a specific architecture. Unless
       | you already know a lot about your solution.
        
         | y4mi wrote:
         | > _But you rarely start by choosing a specific architecture.
         | Unless you already know a lot about your solution._
         | 
         | That's how it probably should be, but in my experience it
         | rarely is. Generally, businesses decide that they need to
         | re-/implement x, then the enterprise architect shows up and
         | decides on the pattern and then the developers are required to
         | somehow make it work, even if it objectively doesn't.
        
           | amatecha wrote:
           | I guess theoretically if the enterprise architect knew about
           | the project and its requirements, the pattern should probably
           | have matched the intended outcome...
        
           | weego wrote:
           | These patterns are so vague and high-level that you could
           | just throw a dart in one of them and it'd work OK for
           | whatever some company is doing. Almost no one is solving
           | issues that can only be described in one pattern.
           | 
           | If anything people are too caught up in the idea that there
           | decisions are make or break for a business.
        
         | contingencies wrote:
         | _Don 't pick the right tool for the job, pick the right
         | framework which secures you extra work for being a tool._ -
         | @iamdevloper ... via https://github.com/globalcitizen/taoup
        
         | nuerow wrote:
         | > _You don 't start by choosing an architecture._
         | 
         | It really depends. Some patterns might be specific to problem
         | domains, but a layered architecture applies pretty much across
         | all types of software projects.
         | 
         | Between defaulting to a layered architecture and just
         | mindlessly piling up ad hoc decisions without any coherent
         | criteria, a layered architecture always wins.
        
           | munk-a wrote:
           | Honestly - a layered approach ends up paying dividends even
           | if used solely for code organization. Options like
           | microservices and event frameworks work quite well when using
           | layered approaches internally.
           | 
           | Basically, I've seen SQL in controllers and I don't ever want
           | that again.
        
       | amelius wrote:
       | Why is React not in this list?
        
       | nefitty wrote:
       | Here are some of my favorite posts regarding architecture/systems
       | design:
       | 
       | Ask HN: Are there any openly available software architecture
       | documents? https://news.ycombinator.com/item?id=22011743
       | 
       | Systems Design for Advanced Beginners
       | https://news.ycombinator.com/item?id=23904000
       | 
       | Ask HN: What are good resources to learn system design?
       | https://news.ycombinator.com/item?id=24762734
        
       | artogahr wrote:
       | Never thought I'd see an article from an Azerbaijanian dev in the
       | front page, but here we are. And babat article idi. Props!
        
       | egeozcan wrote:
       | There are also many variations in between, something like SCS
       | [0], for example.
       | 
       | Nowadays, people started doing such interesting (although
       | sometimes over-engineered) things with architecture, I couldn't
       | even tell what would be the closest from this list.
       | 
       | [0]: https://scs-architecture.org/
        
       | DeathArrow wrote:
       | They are better explained here:
       | https://www.oreilly.com/content/software-architecture-patter...
        
         | williamdclt wrote:
         | Definitely not a 5min read though
        
           | CppCoder wrote:
           | Actually it was. It was ok as an overview.
        
             | Arisaka1 wrote:
             | This would take 5 minutes to read if you already know what
             | you're looking for and you use it as a reference or
             | refresher.
        
             | ascar wrote:
             | I think he meant the mentioned O'Reilly link isn't a 5
             | minute read.
        
               | haraball wrote:
               | According to Instapaper, the O'Reilly article is a 43
               | minute read.
        
           | hutzlibu wrote:
           | But on the other hand, you cannot really expect a full
           | explanation of software patterns in 5 minutes.
        
         | HPsquared wrote:
         | TFA is basically a Cliff's Notes version of that link.
        
         | bewuethr wrote:
         | There's also the full-blown book version at
         | https://www.oreilly.com/library/view/fundamentals-of-softwar...
        
           | devwastaken wrote:
           | $40 dollaryroos for that boy howdy. No wonder nobody knows
           | how to make software, by the time you can afford a stack of
           | these you already have the job.
        
             | 5e92cb50239222b wrote:
             | It's been that way forever. I live in a third world
             | country, for me $40 is a week's expense (total, including
             | food, bills, and so on). If it wasn't for some, ahem, _less
             | reputable_ means of obtaining learning material, I would be
             | carrying boxes in some warehouse right now.
        
             | cyberbanjo wrote:
             | The Architecture of Open Source Applications[1] book are
             | available for free online, and that Fundamentals of
             | Software Architecture is on LibGen.
             | 
             | 1: https://aosabook.org/en/index.html
        
               | hliyan wrote:
               | This is incredible! Breadth, depth and no crap
               | formatting. I can't believe that this isn't more well
               | known.
        
           | raju wrote:
           | [Disclaimer: I know both Mark and Neal well. I don't think it
           | matters here but I just wanted that out of the way]
           | 
           | Their follow-up book to Software Architecture Fundamentals is
           | also available on O'Reilly -
           | https://learning.oreilly.com/library/view/software-
           | architect...
        
       | scns wrote:
       | DDD would be a good addition to that list. Domain Driven Design
       | made functional would be my recommendation for those wanting to
       | look into it.
        
         | adamors wrote:
         | DDD is completely orthogonal to software architecture.
        
           | lyjackal wrote:
           | I agree DDD doesn't belong in this list, but this seems a
           | little harsh. Form follows function. DDD is more about
           | understanding the function, and then architecture patterns
           | are the form
        
             | marginalia_nu wrote:
             | DDD works well enough for translating a business domain to
             | computer code, and if your main obstacle is byzantine
             | business requirements it's great, but I wouldn't want to
             | develop something like an MPEG encoder or an operating
             | system based on that principle. They have quite different
             | types of difficulties that don't benefit from DDD.
        
       | kenniskrag wrote:
       | What I nerver understood:
       | 
       | * How to disconnect the domain model from persistence.
       | 
       | Some solutions add the OR Annotations to the domain model. Some
       | other map the domain model to persistence with a Mapper-layer.
       | 
       | But all of them have some constraints. For e.g. on a web api I
       | receive a dto, map it to a domain model, map it to a persistence
       | model and vice versa. Not much gained imho. In this example I
       | would add the OR-annotations to the domain model and configure
       | many-to-many by "text" so that they are not contained in the
       | domain model.
       | 
       | What are your thoughts?
        
         | laurent92 wrote:
         | - DTO: The "domain model" for us.
         | 
         | - DB objects: A poor flat view of those DTOs, for example
         | complex subobjects can be jsonized, or mapped as a foreign key.
         | 
         | Basically it is the role of the DAO to transform the DTOs into
         | DBOs and store them immediately, or read the tables and
         | transform them into structured DTOs. Why? Because the DB
         | representation is always ugly.
         | 
         | So our application works mostly only with the DTOs. The trick
         | is to make the DTOs rich: Adding methods onto them to ease
         | manipulation, and add validation so that a DTO can only exist
         | in a valid state (as much as possible, modulo when they come
         | from the front-end). So it's not "setDocument(abc)" then
         | "setState(HAS_DOCUMENT)" then "setLastUpdated(now())". It's
         | ".addDocument(doc)" and it changes the state accordingly, so
         | the state is always coherent.
         | 
         | So, our DTOs only have Json annotations on them.
         | 
         | And merging DTOs and DB objects? Never succeeded even on a
         | simple app. I wish we could write into tables without copying
         | data into the DB objects.
        
         | DenisM wrote:
         | > Not much gained imho.
         | 
         | The more complex your system gets the more you will appreciate
         | this division. However at the outset it just makes things more
         | complex than the situation warrants and it's not clear if the
         | system will ever grow large and complex enough to pay for this
         | expense.
         | 
         | I recommend creating your domain model as a simple wrapper
         | around the persistence model. This way if the whole system
         | never gets complex you will retain 95% of simplicity and if it
         | does get complex you're one refactoring away from making your
         | "shallow" domain model into a full-blown domain model.
         | 
         | Likewise the outbound part of your view/DTO model can be a
         | simple wrapper around the domain model. Inbound models will
         | probably have to be their own classes with extra mapping. The
         | latter might be a bit of a pain (in ASP.NET MVC, for example),
         | however I suspect the pain is instructive - making your inbound
         | DTO a copy of the entire object could be simply the wrong path
         | altogether.
        
           | kenniskrag wrote:
           | So you create a class in the Domain which is responsible to
           | save the domain object? And inside of this class you map the
           | domain object to the persistency model? Is that not a
           | forbidden by the layer principle because now the domain model
           | layer has a dependency to the persistency layer.
        
             | marcosdumay wrote:
             | > Is that not a forbidden
             | 
             | You will have a bad time with real software engineering if
             | you take those rules as mandatory. Software engineering
             | rules are like algebraic math postulates, they create
             | common ground that let you explore and communicate some
             | things. Not like legal rules that disallow you from doing
             | something.
             | 
             | Anyway, "layers" imply on single-way dependency. If you
             | have completely independent code, two-way or multi-way
             | dependency, it's something else.
        
             | DenisM wrote:
             | > So you create a class in the Domain which is responsible
             | to save the domain object?
             | 
             | Yes.
             | 
             | > Is that not a forbidden by the layer principle because
             | now the domain model layer has a dependency to the
             | persistency layer.
             | 
             | In my book it's fine. I find that in practice one-way
             | dependencies are ok, so domain->persistence dependency is
             | fine so long as there is no persistence->domain dependency.
             | Simply avoiding loops will take you a very long way.
        
               | kenniskrag wrote:
               | > In my book
               | 
               | Which book?
               | 
               | I see know that one can think of the domain model as most
               | changed layer and if there is a bigger change it is
               | because the domain model changes (e.g. business
               | requirements). So a dependency from the domain model to
               | other parts below are mostly fine.
        
               | 5e92cb50239222b wrote:
               | > Which book?
               | 
               | I believe it's used as an idiom.
               | 
               | https://dictionary.cambridge.org/us/dictionary/english/in
               | -my...
        
               | myohmy wrote:
               | You are technically correct, the best kind of correct.
        
               | DenisM wrote:
               | indeed
        
         | brainwipe wrote:
         | Depends what "disconnected" means. Before Object Relational
         | Mappers came along, you wrote a load of SQL in Stored Procs or
         | in some other framework. This was super tight coupling because
         | updating the database version could ruin everything. Not
         | everything was in compiled code, so it was hard to track.
         | 
         | If you use an ORM (such as Entity Framework I'm about to
         | mention but there are lots) for the write/mutation part then
         | the ORM provides you with that disconnect. You might want to
         | use a different mapper for read, that allows you to write
         | efficient SQL that meets particular needs.
         | 
         | For example, a few years back in .NET Framework I swapped a
         | system that designed/built on Sql Server to run on Postgres.
         | Took me a few days. I didn't change any domain logic during
         | that time. I'd say that the ORM provided a disconnect between
         | the actual persistence and my domain.
         | 
         | I do like a disconnect between my API and the database so that
         | I am able to update the database without causing issues with
         | consumers of my API. That usually requires some kind of mapping
         | but only once. My preferred model right now is a CQRS (don't
         | need ES) using Paramore's Brighter command pattern.
         | 
         | That's for an RDBMS, I think with schemaless/DocDB you can go
         | even further but then the code that loads out the data needs to
         | deal with missing values. That's a different sort of
         | constraint.
         | 
         | I hope that helps, I think I'm rambling now.
        
           | kenniskrag wrote:
           | I usually create "Service" classes in the domain layer, which
           | use Repositories. These repositories are a wrapper for the
           | DbContext to allow unit testing. Where do you put your domain
           | logic? Do you have a domain model or is your persistence
           | model your domain model?
        
             | telchar wrote:
             | Can you expand on how those repositories are written and
             | how you use them for unit testing?
        
         | bob1029 wrote:
         | Decoupling the physical storage of the model from its logical
         | representation is a very important capability if you want any
         | sort of agility down the road. The way we do this is fairly
         | simple:
         | 
         | - Maintain a common domain model stored in a shared dll. This
         | is a POCO type without any methods or mappers of its own. All
         | it does is contain all the facts you might need. To encapsulate
         | everything into a serializable structure, we place all top-
         | level domain types as collections into an aggregate type simply
         | called "Domain".
         | 
         | - Maintain mappers to/from the domain model in the locations
         | most appropriate for these to live. These mappers could talk to
         | SQL, memory, some noSQL garbo, the user's web UI, etc.
         | 
         | The advantages with this layer of separation almost universally
         | outweigh the downsides unless you can convince your development
         | team to build a more standardized single-process/monorepo
         | product. In a simpler product, I would be more inclined to just
         | directly interact with SQLite via anonymous types.
         | 
         | We have used ORMs like EF in the past, but these get in the way
         | really badly and prevent you from building your logical model
         | in precisely the way you want to.
        
         | Cthulhu_ wrote:
         | I'm building an application in this fashion at the moment in
         | Go, and honestly, I think it's kinda painful. At some point I
         | already merged the persistence with the domain model, so it's
         | just the domain model with SQL related struct tags. I am
         | tempted to merge it with the HTTP model as well, add JSON tags
         | to it.
         | 
         | But everyone is telling me it's a bad idea, so I'm really not
         | sure. A more convenient way to copy properties over would be
         | nice.
        
           | kgeist wrote:
           | All you need is a little conversion function which takes a
           | domain struct and converts it to a DB struct with tags (for
           | example)? Unless it's a very complex entity multiple levels
           | deep, I usually don't find it all that painful. What is it
           | about DTO conversions that makes it painful for you? Being
           | boilerplate, it's probably not very aesthetically looking,
           | but it usually doesn't take more than a minute to write the
           | conversion function.
        
           | kenniskrag wrote:
           | > I am tempted to merge it with the HTTP model as well, add
           | JSON tags to it.
           | 
           | If you add a property which shouldn't be public you have to
           | separate them. For example in the domain model you have a
           | user with email but do not want to expose the email.
           | 
           | Second argument: I usually create a simple struct for each
           | method. For example I do not want, that they provide the id
           | for post requests. I want to send the id on get requests so
           | that they can send an update request with the id. I prefer
           | only "non-null" arguments and as a bonus you get a clean
           | (auto-generated) api documentation.
        
             | 5e92cb50239222b wrote:
             | > in the domain model you have a user with email but do not
             | want to expose the email.
             | 
             | You can usually configure that out with @JsonIgnore or
             | something like that. Although this works only for this
             | particular (very simple) example and won't help with e.g.
             | flattening multiple nested objects.
        
               | williamdclt wrote:
               | At this point you already have 2 "models", in the sense
               | of 2 "concepts" or 2 "types": the one with the field and
               | the one without. The second one is implicitly defined
               | with these annotations, which has a good chance to be
               | annoying sooner or later when you need it to be explicit.
        
             | kgeist wrote:
             | >If you add a property which shouldn't be public you have
             | to separate them. For example in the domain model you have
             | a user with email but do not want to expose the email.
             | 
             | Another possible problem: having to support two versions of
             | the API at the same time.
        
         | stonemetal12 wrote:
         | MS Office back in the day was well known for being horrible to
         | interoperate with. Their file format was literally a memory
         | dump. So disconnecting enough that the data on disk is at least
         | serialized in to something that can be understood by others is
         | good.
         | 
         | Being disconnected enough so that V2, can load V1's persistence
         | without too much pain is good. Again looking at you office.
         | 
         | Persistence and domain models are fraternal twins, not
         | identical twins. In general recognize that domain model, and
         | persistence model are different things that have slightly
         | different needs. For example the domain model of a person might
         | only care about age, the persistence model is only going to
         | care about DOB. So yeah 95% of the time they are the same and
         | nothing is gained from separating them but having them be too
         | close is often the source of problems.
        
       | mitchbob wrote:
       | https://archive.ph/Nd1AM
        
       | Toine wrote:
       | "Microservices" are not an architecture
       | 
       | https://dwmkerr.com/the-death-of-microservice-madness-in-201...
        
       | tylfin wrote:
       | I don't think the term "Microkernel Architecture" should be used
       | in this context. I think "Modular Architecture," (or Plug-in like
       | is mentioned) gets closer to this extension-based pattern.
       | 
       | The reason being that there's no relevance to the kernel, and
       | modular kernels, also take this approach with replaceable plug-
       | ins or extensions.
        
         | zerkten wrote:
         | I think people gravitate to it because "kernel" feels like a
         | cool word and some people have heard of OS microkernels being
         | modular. As you say, "modular architecture" is a much clearer
         | way to express the intent and conveys the purpose without being
         | pretentious.
        
         | kapep wrote:
         | I don't think "Microkernel Architecture" is the same as
         | "Modular Architecture". I've only heard the term "Microkernel
         | Architecture" used for systems that have clear public
         | extensions points that enables users to choose which plugins to
         | run or even add third-party plugins.
         | 
         | "Modular Architecture" is more broad in my opinion and rather a
         | description of internal structure. A "modular monolith" for
         | example is modular but doesn't necessarily have a "core" nor is
         | it required to be extensible with plugins by users.
        
       | platz wrote:
       | who is doing Space-based architecture?
        
         | ccday wrote:
         | Hadoop/HDFS
        
         | kgeist wrote:
         | There's a MMO which uses the approach described in the article.
         | Almost everything happens and is stored in memory, in various
         | independent processing units. Data is dumped to disk only
         | occasionally, in case there's complete system failure (so it's
         | more like a backup). I guess they can afford it because losing
         | some progress in a casual game is not very critical.
        
       | FR10 wrote:
       | Good introductory post. For those relatively new to Soft
       | Architecture I always recommend Software Architecture in
       | Practice, great to read and filled with good tactics focused on
       | Quality Attributes.
        
       | ChrisMarshallNY wrote:
       | I tend to design architectures that combine facets of all of
       | these.
        
         | zerkten wrote:
         | That's what I was thinking as I looked at the list. It a nice
         | little overview, perhaps for starting a discussion, but it
         | doesn't capture how you'd use them in practice. When presented
         | separately they appear like they should be applied in a
         | standalone fashion.
        
         | rwoerz wrote:
         | Right, although it seems to be a common misconception that such
         | architectures are mutually exclusive alternatives. And terms
         | are relative: Isn't a single microservice a small monolith on
         | its own? Isn't a bunch of monoliths in an enterprise IT
         | landscape that communicate via network so much different from a
         | microservice architecture.
        
         | spaetzleesser wrote:
         | Probably everybody does. Purists usually don't get very far
         | when they face the real world.
        
           | ChrisMarshallNY wrote:
           | _> Purists usually don't get very far when they face the real
           | world._
           | 
           | This is true. I said as much to someone else, in another
           | thread: https://news.ycombinator.com/item?id=29021254
        
       | AzzieElbab wrote:
       | and in the real world you normally get 4 of these patterns glued
       | together by some informal knowledge. I havent encountered micro-
       | kernels so far
        
       ___________________________________________________________________
       (page generated 2021-10-28 23:00 UTC)