- Organize code into layers: Domain (core, independent), Application (use cases), Infrastructure/Presentation (adapters, controllers).
- Group functionality by bounded contexts based on business capabilities.
- Define Domain layer with entities, value objects, domain services, domain events, and repository interfaces (ports).
- Implement repositories and infrastructure details only in Infrastructure layer.
- Use application services to orchestrate domain logic for specific use cases.
- Keep Domain layer pure and framework-agnostic: no external dependencies, imports, or decorators.
- Employ mappers to convert between infrastructure models (e.g., DB entities) and Domain entities/value objects, preventing leakage.
- Controllers and presentation layers invoke application services, handle DTOs, and perform validation/orchestration only.
- Separate concerns strictly: Infrastructure depends on Domain, never vice versa.