{"id":6,"date":"2024-08-24T08:41:18","date_gmt":"2024-08-24T08:41:18","guid":{"rendered":"https:\/\/contentlabstudy.com\/soft\/?p=6"},"modified":"2026-09-24T21:16:50","modified_gmt":"2026-09-24T20:16:50","slug":"architectural-patterns","status":"publish","type":"post","link":"https:\/\/contentlabstudy.com\/soft\/architectural-patterns\/","title":{"rendered":"Architectural Patterns"},"content":{"rendered":"<p>An <strong>architectural pattern<\/strong> is a reusable way to slice a system so that change, failure, and scale land in predictable places. Use one when you can name the force you are optimizing for (independent deploys, a clear domain model, bursty I\/O). It is not a GoF class diagram and not a UI pattern \u2014 MVC, MVVM, and MVP live in <a href=\"\/soft\/mvc-mvvp-and-mvp\/\">MVC, MVVM, and MVP<\/a>.<\/p>\n<h2>Pattern vs style vs tactic<\/h2>\n<ul>\n<li><strong>Style<\/strong> is the vocabulary (client\u2013server, REST, pipes and filters). See <a href=\"\/soft\/architectural-styles\/\">Architectural Styles<\/a>.<\/li>\n<li><strong>Pattern<\/strong> is a named structure with trade-offs (layered, hexagonal, microservices).<\/li>\n<li><strong>Tactic<\/strong> is a local move (circuit breaker, cache). See <a href=\"\/soft\/reliability-design-patterns\/\">Reliability Design Patterns<\/a>.<\/li>\n<\/ul>\n<h2>Layered (n-tier)<\/h2>\n<p>Stack responsibilities so each layer only talks to neighbors: UI \u2192 application\/use-case \u2192 domain \u2192 persistence\/infrastructure. \u201cn-tier\u201d is the same idea when tiers are <em>process or machine<\/em> boundaries (browser, API host, database).<\/p>\n<ul>\n<li><strong>Use when<\/strong> the team is small, the domain is one, and you want a boring default.<\/li>\n<li><strong>Fails when<\/strong> every feature drills through all layers (\u201carchitecture sinkhole\u201d) or the \u201cbusiness layer\u201d becomes a dump of SQL and HTTP.<\/li>\n<\/ul>\n<h2>Hexagonal \/ ports and adapters<\/h2>\n<p>The domain sits in the middle. <strong>Ports<\/strong> are interfaces the domain owns (for example \u201cload Order\u201d). <strong>Adapters<\/strong> implement those ports (Postgres, REST, a test fake). Application services orchestrate use cases; they do not leak SQL types into the model.<\/p>\n<p>Same family: <strong>onion<\/strong> and <strong>clean architecture<\/strong> \u2014 dependency arrows point inward. The win is testability and swapping infrastructure. The cost is more types up front; do not add a port for a one-off script.<\/p>\n<h2>Microservices<\/h2>\n<p>Independently deployable services, each with its own data and a clear bounded context. You buy independent scale and team autonomy. You pay with distributed failure, eventual consistency, and operational load.<\/p>\n<p><strong>Do not start here<\/strong> because the org chart might look like Amazon. Extract a service when a module already has a different rate of change, data owner, or failure domain. Pair with <a href=\"\/soft\/domain-driven-design-principles\/\">bounded contexts<\/a>.<\/p>\n<h2>Event-driven<\/h2>\n<p>Components publish facts (\u201cOrderPlaced\u201d) instead of calling each other. A broker or bus routes events. Good for fan-out and temporal decoupling. Bad when you pretend events are a synchronous API (you now have an invisible call graph and poison messages). See <a href=\"\/soft\/message-broker-functions\/\">Message Broker functions<\/a>.<\/p>\n<h2>CQRS (when it is actually CQRS)<\/h2>\n<p>Split <em>write<\/em> model from <em>read<\/em> model when they disagree on shape or load. It is not \u201chave a command handler class.\u201d Most CRUD apps want one model. Add CQRS when the read side is a projection you can rebuild, not a second source of truth you edit by hand. CQRS is not event sourcing: that read model can be a projection of the same database.<\/p>\n<h2>Example<\/h2>\n<p>The use case names the port. The SQL adapter lives outside the domain project.<\/p>\n<pre><code>interface IOrders\n{\n    void Add(Order order);\n}\n\nsealed class PlaceOrder\n{\n    public void Handle(IOrders orders) =&gt; orders.Add(new Order());\n}\n\nsealed class SqlOrders : IOrders\n{\n    public void Add(Order order)\n    {\n        \/\/ Postgres stays in this adapter, outside the domain project.\n    }\n}<\/code><\/pre>\n<h2>What breaks it<\/h2>\n<p>The domain method takes a <code>DbContext<\/code>, so every test and every new database drags Entity Framework in with it. Pass <code>IOrders<\/code> instead.<\/p>\n<pre><code>sealed class PlaceOrderThroughSql\n{\n    public void Handle(DbContext db) =&gt; db.Add(new Order());\n}<\/code><\/pre>\n<h2>Pitfalls<\/h2>\n<ul>\n<li>Copying a pattern\u2019s boxes without the force it solves.<\/li>\n<li>Calling every folder \u201cClean Architecture\u201d while the domain still depends on Entity Framework types.<\/li>\n<li>Microservices without ownership of data \u2014 that is a distributed monolith.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>An architectural pattern is a reusable way to slice a system so that change, failure, and scale land in predictable [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[4],"tags":[],"class_list":["post-6","post","type-post","status-publish","format-standard","hentry","category-software-design"],"_links":{"self":[{"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/posts\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/comments?post=6"}],"version-history":[{"count":12,"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/posts\/6\/revisions"}],"predecessor-version":[{"id":3259,"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/posts\/6\/revisions\/3259"}],"wp:attachment":[{"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/media?parent=6"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/categories?post=6"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/contentlabstudy.com\/soft\/wp-json\/wp\/v2\/tags?post=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}