System Design Cases
Onion Architecture
Onion Architecture (Jeffrey Palermo, 2008): concentric rings with domain model at center, surrounded by domain services, application services, infrastructure outside. Dependencies only inward. Pre-cursor to Clean Architecture, sister pattern to Hexagonal.
Onion architecture: inward coupling and explicit infrastructure ports
Palermo’s Onion Architecture controls coupling: code may depend on layers closer to the center, not farther out. Domain Model combines state and behavior; repository interfaces belong in the application core while implementations and database live outside. Это подходит прежде всего long-lived systems with complex behavior, а не универсальная обязанность для каждого маленького CRUD-сайта.
Что утверждает паттерн — и чего он не гарантирует
- Palermo’s fundamental rule is coupling toward the center; outer infrastructure depends on core contracts.
- The Domain Model at the center combines state and behavior; an anemic data model plus all rules in services misses this intent.
- Repository interfaces are in the application core; concrete persistence belongs at the edge.
- Runtime call direction can cross outward into an injected implementation while source dependency still points inward.
Границы и компоненты
| Компонент | Ответственность |
|---|---|
| Web Delivery Adapter | Переводит transport request в application command. |
| Application Service Ring | Оркестрирует use case, transaction и external ports. |
| Behavior-Rich Domain Model | Содержит state и business behavior/invariants в центре. |
| Core Repository Interface | Core-owned contract сохранения/получения domain model. |
| Core Payment Interface | Core-owned semantic contract внешнего payment operation. |
| Postgres Infrastructure Adapter | Реализует repository interface и mapping/transactions. |
| Payment Infrastructure Adapter | Реализует payment port, idempotency и status reconciliation. |
| Composition Root | Связывает concrete implementations с interfaces вне domain core. |
Сценарии
Execute behavior in the domain model
Delivery maps request data, application service loads state through the repository interface and asks the domain object to enforce its invariant.
Проверяемый исход: Business behavior remains in the domain center rather than becoming a procedural service-layer script.
Persist without core-to-database coupling
Application code names a repository interface defined toward the center. The outside Postgres adapter translates it into SQL/transaction behavior.
Проверяемый исход: Domain and application assemblies do not import database framework types.
Call a remote payment through a port
Application service creates a stable operation identity and invokes the payment interface. Concrete provider adapter maps provider status and timeout to semantic outcomes.
Проверяемый исход: The core never calls a concrete SDK and never treats timeout as definite failure.
Replace an infrastructure adapter
Composition root injects a candidate only after repository/payment contract tests and migration/reconciliation plans pass.
Проверяемый исход: Dependency inversion enables substitution points but does not assert semantic equivalence.
Failure, concurrency и evolution checklist
- Statically reject core imports of UI, ORM and provider SDK types.
- Contract-test adapter conflicts, unavailable dependency, timeout and cancellation.
- Use stable operation identity and reconciliation for remote side effects.
- Treat composition-root startup success as wiring evidence, not end-to-end correctness.
Метрики, units и допущения
- Layer count is intentionally variable; adding rings is not a maturity score.
- Adapter error rate, p95/p99 latency and recovery time need measured units and workload context.
- Migration completeness and rollback window are explicit data/time gates; dependency inversion supplies neither.
Числа здесь — размерностные формулы или явно помеченные учебные inputs. Паттерн архитектуры сам по себе не задаёт SLA, throughput, latency или fault tolerance.
Связанные темы
[CONCEPT]hexagonal-ports-adapters
Первичные источники
- https://jeffreypalermo.com/2008/07/the-onion-architecture-part-1/
- https://jeffreypalermo.com/tag/onion-architecture/
Scope note
Onion Architecture controls code coupling. Injection does not itself provide retries, durable state, authorization, migration compatibility, provider idempotency or availability.