10 KiB
name, description, compatibility, metadata
| name | description | compatibility | metadata | ||||||
|---|---|---|---|---|---|---|---|---|---|
| dotnet-microservice-workflow | Workflow phát triển .NET Microservices theo 4 lớp (Domain → Infrastructure → Application → API). Use for creating new features, new services, hoặc khi cần structured approach theo DDD + CQRS + Clean Architecture. | .NET 10+, EF Core 9+, MediatR 12+ |
|
.NET Microservice Development Workflow
Quy trình 4 giai đoạn để phát triển features hoặc services theo chuẩn DDD + CQRS + Clean Architecture.
When to Use This Skill / Khi Nào Sử Dụng
Use this workflow when:
- Creating a new domain feature / Tạo feature mới trong domain
- Building a new microservice from scratch / Xây service mới từ đầu
- Refactoring existing code to DDD / Refactor code sang DDD
- Need structured approach / Cần approach có cấu trúc
DO NOT use when:
- Simple CRUD operations / Các thao tác CRUD đơn giản
- Prototyping / Làm prototype nhanh
- Small utilities / Các utility nhỏ
Overview / Tổng Quan
┌──────────────────────────────────────────────────────────────────┐
│ WORKFLOW 4 GIAI ĐOẠN │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ PHASE 1 │────►│ PHASE 2 │ │
│ │ DOMAIN │ │ INFRASTRUCTURE │ │
│ │ │ │ │ │
│ │ - Aggregates│ │ - EF Config │ │
│ │ - Entities │ │ - Repositories │ │
│ │ - V.Objects │ │ - Migrations │ │
│ │ - D.Events │ │ - Idempotency │ │
│ └─────────────┘ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ PHASE 4 │◄────│ PHASE 3 │ │
│ │ API │ │ APPLICATION │ │
│ │ │ │ │ │
│ │ - Controls │ │ - Commands │ │
│ │ - Health │ │ - Queries │ │
│ │ - Resilien. │ │ - Handlers │ │
│ │ - OpenAPI │ │ - Behaviors │ │
│ └─────────────┘ └─────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
Phase 1: Domain Layer / Lớp Nghiệp Vụ
Goal: Thiết kế Domain Model sạch, không phụ thuộc framework
Key Skill: Domain-Driven Design
Checklist
-
Xác định Aggregate Root
- Mọi thay đổi dữ liệu phải đi qua Aggregate Root
- Đảm bảo tính nhất quán (Consistency)
-
Thiết kế Entities
- Properties với
private set - Thao tác qua methods có ý nghĩa nghiệp vụ
- Backing fields cho collections
- Properties với
-
Tạo Value Objects
- Immutable (bất biến)
- Equality by all properties
-
Định nghĩa Domain Events
- Implement
IDomainEvent - Raise trong aggregate methods
- Implement
-
Unit Tests
- Test business rules trong domain
Rules
// ❌ SAI: Public setter, expose mutable collection
public class Order
{
public OrderStatus Status { get; set; }
public List<OrderItem> Items { get; set; }
}
// ✅ ĐÚNG: Private setter, ReadOnly collection
public class Order : Entity, IAggregateRoot
{
private readonly List<OrderItem> _items = new();
public OrderStatus Status { get; private set; }
public IReadOnlyCollection<OrderItem> Items => _items.AsReadOnly();
public void AddItem(Guid productId, int quantity, decimal price)
{
if (Status != OrderStatus.Draft)
throw new DomainException("Cannot modify non-draft order");
_items.Add(new OrderItem(productId, quantity, price));
}
}
Phase 2: Infrastructure Layer / Lớp Hạ Tầng
Goal: Triển khai persistence mà không làm ô nhiễm Domain
Key Skill: Repository Pattern
Checklist
-
EF Core Configurations
- Sử dụng
IEntityTypeConfiguration - Fluent API, không Data Annotations
- Sử dụng
-
Repository cho Aggregate Root
- Chỉ 1 repository per aggregate
- Implement
IUnitOfWork
-
Database Migrations
- Tạo và apply migrations
-
Idempotency (Optional)
IdentifiedCommandcho critical operations
Rules
// ❌ SAI: Repository cho từng table
public interface IOrderItemRepository { }
public interface IOrderPaymentRepository { }
// ✅ ĐÚNG: Chỉ repository cho Aggregate Root
public interface IOrderRepository : IRepository<Order>
{
Task<Order?> GetWithItemsAsync(Guid id, CancellationToken ct);
}
Phase 3: Application Layer (CQRS)
Goal: Tách biệt luồng Đọc (Query) và Ghi (Command)
Key Skill: CQRS MediatR
Checklist
-
Commands
- Tạo Command record
- Implement CommandHandler
- Gọi domain methods, save qua Repository
-
Queries
- Bypass Domain Model
- Sử dụng Dapper cho performance
- Return lightweight DTOs
-
Validators
- FluentValidation cho input validation
- Register trong Pipeline Behaviors
-
Pipeline Behaviors
- LoggingBehavior
- ValidationBehavior
- TransactionBehavior (optional)
Rules
// ❌ SAI: Business logic trong Handler
public async Task<OrderResult> Handle(CreateOrderCommand cmd, CancellationToken ct)
{
if (cmd.Items.Count == 0)
throw new Exception("Empty order"); // Logic nên ở Domain!
}
// ✅ ĐÚNG: Delegate logic cho Domain
public async Task<OrderResult> Handle(CreateOrderCommand cmd, CancellationToken ct)
{
var order = new Order(cmd.UserId, cmd.Address);
foreach (var item in cmd.Items)
order.AddItem(item.ProductId, item.Quantity, item.Price); // Domain validates
await _repository.AddAsync(order, ct);
await _repository.UnitOfWork.SaveChangesAsync(ct);
return new OrderResult(order.Id);
}
Phase 4: API Layer / Lớp API
Goal: Expose API đúng chuẩn với cross-cutting concerns
Key Skills:
Checklist
-
Slim Controllers
- Chỉ nhận request, gọi MediatR
- ApiResponse wrapper
-
Health Checks
- Endpoint
/hchoặc/health - Check DB, Redis, RabbitMQ connections
- Endpoint
-
Resilience (Polly)
- Retry với Exponential Backoff
- Circuit Breaker cho external calls
-
OpenAPI Documentation
- SwaggerOperation attributes
- SwaggerResponse cho từng status code
-
DI Registration
- Register MediatR, Validators
- Register Repositories, Services
Rules
// ❌ SAI: Fat controller với logic
[HttpPost]
public async Task<IActionResult> CreateOrder(CreateOrderRequest request)
{
var order = new Order(request.UserId, request.Address);
foreach (var item in request.Items)
order.AddItem(item.ProductId, item.Quantity, item.Price);
await _repository.AddAsync(order);
await _context.SaveChangesAsync();
return Ok(order.Id);
}
// ✅ ĐÚNG: Slim controller
[HttpPost]
public async Task<ActionResult<ApiResponse<OrderResult>>> CreateOrder(
CreateOrderRequest request,
CancellationToken ct)
{
var command = request.ToCommand(GetUserId());
var result = await _mediator.Send(command, ct);
return CreatedAtAction(nameof(GetOrder), new { id = result.OrderId },
ApiResponse<OrderResult>.Ok(result));
}
Common Mistakes / Lỗi Thường Gặp
| Mistake | Problem | Solution |
|---|---|---|
| Skip Domain Layer | Anemic model, logic scattered | Always start with Domain |
| Logic in Handler | Hard to test, duplicate | Move to Domain methods |
| Fat Controllers | Violates SRP | Use MediatR pattern |
| Query via EF Core | N+1, over-fetching | Use Dapper for reads |
| Repository per table | Breaks aggregate rules | Only for Aggregate Root |
Quick Reference / Tham Chiếu Nhanh
| Phase | Layer | Location | Key Patterns |
|---|---|---|---|
| 1 | Domain | ServiceName.Domain/ |
Aggregate, Entity, VO |
| 2 | Infrastructure | ServiceName.Infrastructure/ |
Repository, UoW, EF |
| 3 | Application | ServiceName.API/Application/ |
Command, Query, Handler |
| 4 | API | ServiceName.API/Controllers/ |
Controller, HealthCheck |
Resources / Tài Nguyên
- Detailed Checklist - Checklist từng giai đoạn
- Technical Reference - Chi tiết kỹ thuật
- Domain-Driven Design - DDD patterns
- Repository Pattern - Data access
- CQRS MediatR - Command/Query handlers
- API Design - Controller patterns
- Error Handling - Exception handling
- Testing Patterns - Unit/Integration tests
- Project Rules - Coding standards