Possible structures:
src/
├── domains/
│ ├── subscriptions/
│ │ ├── subscription.controller.ts
│ │ ├── subscription.service.ts
│ │ ├── subscription.repository.ts
│ │ ├── subscription.model.ts
│ │ ├── subscription.schema.ts # validation schemas
│ │ └── subscription.types.ts # interfaces/types
│ ├── channels/
│ ├── bots/
│ ├── posts/
│ └── postlines/
├── shared/
│ ├── middleware/
│ ├── utils/
│ └── types/
└── server.ts
src/
├── controllers/
│ ├── subscription.controller.ts
│ ├── channel.controller.ts
│ └── ...
├── services/
├── repositories/
├── models/
├── schemas/
├── types/
└── server.ts
Overview:
- Focus: Emphasizes understanding the business domain to design software that closely aligns with the business logic.
- Core Concepts: Ubiquitous Language, Bounded Contexts, Aggregate Roots, Entity Framework, Value Objects, and Repositories.
Structure:
- Ubiquitous Language (Domain Language):
- A shared language used across all stakeholders (developers, product managers, domain experts) to describe the system's functionality and business rules.
- Bounded Contexts:
- Divides a large complex domain into smaller, manageable pieces where each piece has its own context and rules.
- Helps in managing complexity by allowing different teams or parts of an organization to independently develop their part without conflicts.
- Aggregates and Aggregate Roots:
- Aggregates are collections of objects that are treated as a single unit.
- An Aggregate Root is the entry point for any operation within an aggregate, ensuring consistency.
- Entities:
- Objects with identity (e.g.,
User
,Order
), which means two instances with different IDs are considered distinct even if their properties match.
- Objects with identity (e.g.,
- Value Objects:
- Objects that represent immutable data (e.g.,
Address
,Money
). They are compared by value rather than reference and are typically used as parts of entities or other value objects.
- Objects that represent immutable data (e.g.,
- Repositories:
- Interfaces for accessing domain objects without exposing the underlying storage mechanisms.
- Abstracts how data is persisted, allowing changes to be made in one place.
Key Benefits:
- Strong Focus on Business Rules: Aligns code more closely with business logic, making it easier to understand and evolve.
- Scalability and Maintainability: Easier to manage large systems by breaking them down into bounded contexts.
- Collaboration: Promotes better communication between teams through a shared language.
Overview:
- Focus: Organizes the application into distinct layers, each responsible for specific functions.
- Core Layers: Presentation Layer (UI), Business Logic Layer (Domain Services, Application Services), and Data Access Layer (Persistence).
Structure:
- Presentation Layer:
- Handles user interaction, routing, controllers, and HTTP endpoints.
- Acts as an interface between the outside world and the application.
- Business Logic Layer:
- Contains the core business rules and logic of the application.
- Includes domain models, services, and use cases.
- Data Access Layer:
- Manages data storage and retrieval, interfacing with databases or external systems.
- Abstracts database operations to provide a clean interface for the business layer.
Key Benefits:
- Separation of Concerns: Clear distinction between different responsibilities, making the code easier to maintain and extend.
- Testability: Layers can be tested independently, which simplifies unit testing.
- Scalability: Easier to scale as each layer can be developed or upgraded without affecting others.
DDD vs. Layered Architecture:
Aspect | DDD | Layered Architecture |
---|---|---|
Focus | Business logic | Separation of concerns |
Project Structure | Domains, Aggregates, Entities | Presentation, Application, Infrastructure |
Flexibility | High (supports complex domain models) | Moderate |
Complexity | Higher | Lower |
Use Cases | Large-scale enterprise applications with complex business logic | General-purpose web applications |
Testing | Domain-driven testing | Layered testing |
When to Use DDD:
- Applications with highly complex and dynamic domain models.
- Projects that require a deep understanding of business rules and need to evolve over time.
- Teams aiming for high maintainability and scalability in large-scale systems.
When to Use Layered Architecture:
- Simpler applications where clear separation of concerns is sufficient.
- Projects requiring rapid development or iteration with minimal overhead.
- Applications where the domain model is relatively straightforward.
Choosing between DDD and a layered architecture depends on the complexity of your application, the importance of aligning code with business logic, and your team's familiarity with these architectural styles. While DDD offers more flexibility and alignment with business requirements, it may introduce additional overhead for simpler projects. On the other hand, a layered architecture provides a clear separation of concerns and is generally easier to implement but might not capture all nuances of complex domain interactions.
Both approaches aim to enhance code organization and maintainability, so consider your project's specific needs and constraints when selecting an architectural pattern.