Balancing Software Architecture Choices in Real Projects
The article explains that software architecture is fundamentally about trade‑offs, categorises major architecture families such as DDD, Clean/Hexagonal/Onion, Microservices vs SOA, CQRS/Event Sourcing, MVC, PACELC, BASE, FLP, Repository and 12‑Factor principles, and shows how each addresses specific constraints to help engineers pick the most suitable design for their context.
Architecture as Trade‑off – Every architectural idea answers the same question: under which constraints should we sacrifice what to gain what. The article introduces a "four‑family" classification to make these sacrifices and benefits explicit.
Domain Architecture Family (DDD) – Eric Evans' 2003 Domain‑Driven Design defines Bounded Contexts that delimit business domains. The trade‑off is higher modelling complexity for precise domain expression, and bounded contexts also serve as the theoretical basis for microservice decomposition.
Layered Architecture Family (Clean / Hexagonal / Onion) – Although named differently, all three place business logic at the core and isolate external concerns via indirect layers. Clean Architecture enforces dependency rules, Hexagonal uses ports and adapters, and Onion visualises concentric layers. The core trade‑off is added indirection for maintainability and testability.
Split Architecture Family (Microservices / SOA) – James Lewis and Martin Fowler promoted Microservices (split first, then connect) while SOA (early 2000s) connects first then splits via an ESB. The trade‑off is independent deployment and evolution versus increased operational complexity. Example: HBase chooses consistency (CP) during partitions, Cassandra chooses availability (AP).
Pattern Architecture Family (CQRS / Event Sourcing) – Greg Young's 2010 CQRS separates command and query models, optimising write consistency and read performance. Event Sourcing records state changes as immutable events, enabling auditability. Combined, they achieve full read/write decoupling but require eventual consistency instead of single‑node transactions.
Presentation Layer Family (MVC / MVP / MVVM) – Originating from Trygve Reenskaug's 1979 MVC, these patterns separate UI concerns from state, mirroring the layering principles of the deeper architecture families.
PACELC – Full‑scene Distributed Decision Framework – Daniel Abadi's 2010 extension adds the "E" (Latency vs Consistency) decision for normal operation to CAP's partition‑time trade‑off. The article maps HBase (CP, latency‑heavy) and Cassandra (AP, low‑latency) to the two PACELC branches.
BASE – Distributed Compromise for CAP's Availability – Dan Pritchett's 2008 BASE model (Basically Available, Soft state, Eventual consistency) describes how systems compensate after choosing availability in CAP.
FLP Impossibility and Engineering Work‑arounds – The 1985 Fischer‑Lynch‑Paterson result shows deterministic consensus is impossible in fully asynchronous systems with failures. Paxos and Raft introduce randomness or timeouts to bypass this theoretical limit.
Repository Pattern – DIP in Data Access – The Repository abstracts data access, embodying the Dependency Inversion Principle. Active Record (Rails style) binds data to domain objects, while Data Mapper separates them; the choice depends on system complexity.
Domain Model – Core of DDD – A rich domain model places behavior inside domain objects, contrasting with anemic models that push logic to services, thereby preserving OO encapsulation.
12‑Factor App – Constraints for Cloud‑Native Freedom – Heroku's 2011 methodology lists twelve constraints (single codebase, explicit dependencies, config via env vars, build‑release‑run separation, stateless processes, etc.) that, when accepted, grant scalability and predictability in the cloud.
Reactive Manifesto – Message‑Driven as Root – The 2014 manifesto defines four traits (Responsive, Resilient, Elastic, Message‑Driven), with message‑driven architecture enabling fault isolation, load‑leveling, and timely responses.
Inverse Conway Maneuver – Organization First – Building on Conway's Law, the inverse strategy suggests reshaping team communication structures to steer architecture, deciding whether to change organization or architecture first.
Conclusion – At the class level the answer is SOLID (dependencies toward abstractions); at the component level it is SDP/SAP (dependencies from volatile to stable); at the architecture level the trade‑off frameworks of layered families, DDD bounded contexts, and PACELC guide the choice. There is no universally optimal architecture, only the one that best fits the current constraints.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ZhiKe AI
We dissect AI-era technologies, tools, and trends with a hardcore perspective. Focused on large models, agents, MCP, function calling, and hands‑on AI development. No fluff, no hype—only actionable insights, source code, and practical ideas. Get a daily dose of intelligence to simplify tech and make efficiency tangible.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
