Prerequisites | Recommended | Alternative |
---|---|---|
IDE | Visual Studio 20221 | JetBrains Rider |
Environment | Docker |
Fake, Inc. (a fictional company) is launching a new expense management service to handle a wide range of employee-initiated expenses. Authorized employees can submit expense claims, which are then reviewed and processed by relevant departments within the company.
This domain is inherently complex and spans multiple business concerns, including:
- Submitting and managing expense claims
- Auditing and approving expenses
- Tracking the processing lifecycle
- Managing employee profiles and entitlements
- Storing and analyzing historical financial data for compliance and insights
In addition to the domain complexity, the company is growing rapidly and prioritizes agility in delivering new features and scaling the system. The application is expected to:
- Operate at cloud scale
- Meet high service level objectives (SLOs)
- Support diverse and evolving data storage and querying needs across different functional areas
Given these requirements, a microservices architecture is a natural fit. It allows the system to be decomposed into independently deployable, domain-aligned services that can scale and evolve at different rates. This architecture also supports:
- Clear separation of concerns aligned with business capabilities
- Flexible technology choices per service (e.g., optimized storage engines or processing models)
- Improved resilience and fault isolation
- Faster iteration cycles for teams working on different parts of the system
As a result, Fake, Inc. has chosen a microservices approach to build a scalable, maintainable, and adaptable Expense Management platform.
.NET Aspire mode (recommended):
- Open solution
Starter.slnx
- Launch
Starter.AppHost:https
- Wait for all resource nodes to be in the
Running
status then the Swagger UI ofCommand.Api:https
andQuery.Api:https
will be automatically launched.
In the .NET Aspire Dashboard, you can access to the following built-in observability tools: Resources, Console Logs, Structured Logs, Traces, and Metrics.
Docker compose mode (alternative):
- Run
docker compose -d
in Terminal from the root folder of the repository - Open solution
Stater.slnx
- Launch
Command.Api:https
and / orQuery.Api:https
to access the Swagger UI
flowchart LR
Step1["Analyze domain"]
Step2["Define bounded contexts"]
Step3["Define entities, aggregates, and services"]
Step4["Identify microservices"]
Step1 --> Step2 --> Step3 --> Step4
Exercise | Input | Output |
---|---|---|
Domain Analysis (Strategic DDD) | Scenario | Subdomains > bounded contexts with integration > high-level architecture. |
Domain Modeling (Tactical DDD) | Bounded contexts with integration | Breakdown patterns: aggregate roots, entities, value objects, domain behaviors, domain events. |
Deep Dive: Expense Management | Breakdown patterns | Data model with dependencies for Expense Management service. |
API Design (REST) | Data models | A stateless, loosely coupled interface between a client and service. |
Clean Architecture | Use cases, business rules, and other key concepts. | Separates the business logic from the technical decisions.. |
Design Patterns | Common problems | Common approaches to solving similar problems. |
Testing | Test Driven Design | Definition and confirmation upon the software's behavior. |
flowchart LR
subgraph .aspire
Starter.AppHost
Starter.ServiceDefaults
end
subgraph .docker
DockerCompose["docker-compose"]
end
subgraph src
subgraph Core
Domain
Application
end
subgraph External
Infrastructure
end
Command.Api
Query.Api
end
subgraph tests
ArchitectureTests
FunctionalTests.Command.Api
FunctionalTests.Query.Api
IntegrationTests
UnitTests
end
Application ---> Domain
Infrastructure ---> Domain
Command.Api ---> Application
Command.Api ---> Infrastructure
Command.Api ---> Starter.ServiceDefaults
Query.Api ---> Application
Query.Api ---> Infrastructure
Query.Api ---> Starter.ServiceDefaults
ArchitectureTests ---> Command.Api
ArchitectureTests ---> Query.Api
FunctionalTests.Command.Api ---> Command.Api
FunctionalTests.Query.Api ---> Query.Api
IntegrationTests ---> Infrastructure
UnitTests ---> Application
Footnotes
-
The option Solution File Persistence Model must be enabled to support
.slnx
. ↩