Docs
Pricing
Explore
Search...
⌘
K
Log in
Sign up
Toggle menu
Home
shaikapsar
arch-design-rules
public
Published on 5/8/2025
Architecture and Design Rules
Rules
Star
0
Remix
Add block
Preview
YAML
Repository Placement Rule
Define repository interfaces (e.g., OrderRepository) in the domain layer as output ports.
Repository implementations reside in the infrastructure layer and use persistence technology (e.g., JPA, MongoDB).
Repositories must deal only with aggregate roots, not child entities or value objects.
Application services use repositories to load and persist aggregates.
Avoid business logic in repositories; focus on data access.
Ensure repository interfaces are technology-agnostic.
Prevent direct repository access from domain entities to preserve encapsulation.
Input Port Rule
Input ports represent use cases and are defined as interfaces in the application layer.
Input ports are invoked by controllers, APIs, or UI layers.
Application services implement input ports and coordinate domain logic and infrastructure.
Output Port Rule
Output ports represent dependencies on external systems (e.g., repositories, message brokers).
Place domain-relevant output ports (e.g., repositories) in the domain layer.
Place application-level output ports (e.g., email, payment) in the application layer.
Implement output ports in the infrastructure layer with technology-specific adapters.
Keep output port interfaces clean, focusing on business capabilities rather than technology concerns.
Hexagonal Architecture Layers
Domain Layer: Contains core domain models, aggregates, entities, value objects, domain events, and domain-level output ports.
Application Layer: Coordinates use cases, defines input ports, and uses domain services and output ports.
Infrastructure Layer: Implements technical concerns like database access, messaging, external APIs.
Presentation Layer (optional): Interfaces with the user, typically via HTTP or WebSocket.
Apply Dependency Inversion: inner layers define interfaces, outer layers implement them.
Maintain strict boundaries and avoid circular dependencies.
Domain-Driven Design (DDD) Layering
Follow the DDD principles: model around the business domain.
Use Aggregates to enforce invariants and model transactional consistency boundaries.
Use Value Objects to model concepts without identity.
Use Entities to model stateful business concepts with identity.
Encapsulate domain rules and logic inside aggregates.
Use Domain Services only when logic doesn’t naturally belong to an entity or value object.
Place shared domain logic and factories in the domain layer.
Align boundaries using Bounded Contexts — model consistency boundaries for different subdomains.
CQRS Rule
Separate read and write operations using different models and components.
Commands mutate state and are handled by command-side services.
Queries retrieve data, often optimized for read performance (e.g., projections).
Avoid using domain aggregates in the query layer.
Apply CQRS only where it simplifies complexity or enables scalability.
SAGA Coordination Rule
Use SAGA patterns to coordinate multi-step, long-running processes across bounded contexts or services.
Orchestrated SAGA: central orchestrator controls flow, often implemented in application layer.
Choreographed SAGA: distributed coordination through domain events, no central controller.
Each step should be idempotent and compensatable.
Model each SAGA as a state machine or flow.
Persist SAGA state to support recovery and retry.
Event Sourcing Rule
Persist domain events instead of current state snapshots.
Rehydrate aggregates by replaying their event stream.
Events represent historical facts (e.g.,
OrderPlaced
,
PaymentCaptured
).
Commands result in new events; events are then applied to the aggregate.
Use snapshots for performance if event streams are long.
Apply versioning and schema evolution to support long-lived events.
Outbox Pattern Rule
Persist events in an
outbox
table as part of the same transaction that changes domain state.
Use an outbox relay to publish events to external systems (e.g., Kafka, RabbitMQ).
Decouple business logic from messaging concerns using this pattern.
Ensure idempotent publishing using message IDs or deduplication strategies.
Use this pattern to achieve transactional consistency across database and message queues.
General Architecture Guidelines
Ensure domain logic is the heart of the system and is isolated from infrastructure.
Adhere to clean architecture: direction of dependencies points inward.
Use dependency injection to bind interface contracts to implementations.
Avoid anemic domain models — embed behavior within aggregates.
Use rich domain models to reflect business understanding and terminology.
Structure your codebase by feature or subdomain, not technical layer.
Apply DDD strategic design to split domains into meaningful bounded contexts.
Integrate between contexts via APIs, events, or shared kernel — be explicit.
Evolve architecture incrementally — not all systems need all patterns upfront.