@tank/app-architecture
1.0.0Skill
Description
Application-level architecture patterns for structuring code within a service or monolith. Layered, hexagonal, clean architecture, DDD tactical patterns, CQRS, event sourcing, modular monolith, vertical slices.
Triggered by
app architecturehexagonalports and adaptersclean architectureDDDaggregate
Download
Verified
tank install @tank/app-architectureApplication Architecture
Core Philosophy
- Dependencies point inward. Business logic never depends on frameworks, databases, or HTTP. Infrastructure depends on the domain, never the reverse.
- Boundaries are the architecture. The placement and enforcement of module boundaries matters more than which pattern name you pick.
- Match complexity to the problem. CRUD apps do not need hexagonal architecture. Complex domains do not survive without explicit modeling. Select the lightest pattern that controls your actual complexity.
- Make the implicit explicit. Use cases, domain rules, and module contracts should be readable in code, not buried in service classes or controllers.
- Delay distribution, enforce modularity now. A well-bounded modular monolith can be split into services later. Poorly structured microservices cannot be easily merged back.
Quick-Start: Common Problems
"How should I structure this app?"
- Is the domain complex with rich business rules? -> Clean/Hexagonal + DDD tactical patterns
- Is it mostly CRUD with some validation? -> Layered architecture or vertical slices
- Do reads and writes have very different shapes/loads? -> Consider CQRS
- Will multiple teams work in this codebase? -> Modular monolith with enforced boundaries
- Is it a greenfield with unclear requirements? -> Vertical slices, refactor toward hexagonal as patterns emerge
-> See
references/architecture-selection.md
"Where does this code go?"
- Does it express a business rule independent of any use case? -> Domain layer (entity/value object)
- Does it orchestrate a user-facing workflow? -> Application layer (use case / application service)
- Does it translate between external format and internal model? -> Interface adapter (controller, presenter, mapper)
- Does it interact with a database, API, or file system? -> Infrastructure layer (driven adapter / repository impl)
-> See
references/clean-architecture.md
"Should I use DDD here?"
- Is the domain the primary source of complexity? -> Yes, DDD tactical patterns add value
- Is the complexity mostly technical (integrations, performance)? -> No, DDD adds overhead without payoff
- Can you access domain experts regularly? -> Essential for DDD to work
- Is the team willing to invest in a ubiquitous language? -> Required precondition
-> See
references/ddd-tactical-patterns.md
"My codebase is a big ball of mud"
- Identify the highest-value bounded context -> Draw a boundary around it first
- Define an explicit interface (internal API) for that module -> No direct database access from outside
- Move related code inside the boundary -> One module at a time
- Enforce the boundary with build tooling or access rules -> Prevent regression
-> See
references/modular-monolith-vertical-slices.md
Architecture Style Selection
| Domain Complexity | Read/Write Asymmetry | Team Size | Recommendation |
|---|---|---|---|
| Low (CRUD-dominant) | Low | Any | Layered architecture or vertical slices |
| Medium (some business rules) | Low | Small | Clean architecture (simplified) |
| Medium | High | Any | Clean architecture + CQRS |
| High (complex domain logic) | Low | Any | Hexagonal/Clean + DDD tactical patterns |
| High | High | Any | Hexagonal/Clean + DDD + CQRS |
| Any | Any | Multiple teams, one codebase | Modular monolith with enforced boundaries |
| High + audit/compliance needs | High | Any | Event sourcing + CQRS (evaluate carefully) |
Dependency Direction Quick Reference
| Layer | Depends On | Never Depends On |
|---|---|---|
| Domain (entities, value objects) | Nothing | Application, infrastructure, UI |
| Application (use cases) | Domain | Infrastructure, UI |
| Interface adapters (controllers, presenters) | Application, domain | Infrastructure details |
| Infrastructure (DB, APIs, frameworks) | Application, domain (implements interfaces) | Nothing restricts it inward |
Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| Anemic domain model | Entities are data bags, logic scattered in services | Move behavior into entities/value objects |
| Big ball of mud | No boundaries, everything depends on everything | Identify bounded contexts, extract modules |
| Over-layering | 6 layers for a CRUD endpoint, pass-through delegation | Remove layers that add no logic; vertical slices for simple features |
| Framework coupling | Domain logic imports Spring/Express/Django | Invert dependencies; domain defines interfaces, infrastructure implements |
| Shared database across modules | Modules coupled through tables, no clear ownership | Each module owns its tables, communicate through APIs/events |
| God service | One application service with 50 methods | Split by use case; one class per use case or feature |
| Leaking domain logic | Validation and business rules in controllers | Push rules into domain objects, use application services to orchestrate |
Reference Index
| File | Contents |
|---|---|
references/layered-hexagonal.md | Traditional layered architecture (N-tier, when it works, when it breaks), hexagonal architecture (ports, adapters, driven/driving distinction), dependency inversion mechanics |
references/clean-architecture.md | Clean architecture concentric circles, dependency rule, entities, use cases, interface adapters, frameworks layer, practical project structure |
references/ddd-tactical-patterns.md | Entities, value objects, aggregates, aggregate roots, domain events, repositories, domain services, application services, factories |
references/cqrs-event-sourcing.md | CQRS at application level, read/write model separation, eventual consistency, event sourcing fundamentals, event store, projections, snapshots, when to use vs avoid |
references/modular-monolith-vertical-slices.md | Module boundary enforcement, internal APIs, shared kernel, inter-module communication, vertical slice architecture, feature-organized code, MediatR patterns |
references/architecture-selection.md | Architecture style comparison matrix, migration paths between styles, feature flags as architectural enabler, trunk-based development support, incremental adoption strategies |