2024-11-06 025_在 ASP.NET Core 中實現 DDD(領域驅動設計)

2024-11-06 025_在 ASP.NET Core 中實現 DDD(領域驅動設計)

在 ASP.NET Core 中實現 DDD(領域驅動設計),我們可以通過分層架構來將系統中的各個領域邏輯與基礎設施分離。下面,我會用一個具體的情境來展示如何實現 DDD 原則。

情境範例:訂單管理系統

假設我們正在開發一個簡單的訂單管理系統,主要負責處理訂單的創建、取消、更新等操作。

1. 分層架構概述

DDD 的分層架構可以包括以下幾層:

  • 領域層(Domain Layer):這是業務邏輯所在的地方,處理與訂單有關的所有核心邏輯。
  • 應用層(Application Layer):負責協調應用程式的執行流程,不包含業務邏輯,只是調用領域層來執行具體邏輯。
  • 基礎設施層(Infrastructure Layer):負責資料庫訪問、第三方服務交互等技術細節。
  • 使用者介面層(UI Layer):包含控制器和 API 入口,處理請求和回應。

2. 實體(Entity)與值物件(Value Object)

在領域層中,我們定義了訂單(Order)這個實體。訂單包含唯一的訂單 ID,並且具有訂單狀態等屬性。另一個值物件可能是 Money,表示訂單的金額。

Order 實體範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class Order
{
public Guid OrderId { get; private set; }
public DateTime CreatedAt { get; private set; }
public OrderStatus Status { get; private set; }
public Money TotalAmount { get; private set; }

// 訂單的行為邏輯
public void Cancel()
{
if (Status == OrderStatus.Completed)
throw new InvalidOperationException("Completed orders cannot be cancelled.");

Status = OrderStatus.Cancelled;
}

public void Complete()
{
if (Status == OrderStatus.Cancelled)
throw new InvalidOperationException("Cancelled orders cannot be completed.");

Status = OrderStatus.Completed;
}

// 工廠方法來創建訂單
public static Order Create(Guid orderId, Money totalAmount)
{
return new Order
{
OrderId = orderId,
CreatedAt = DateTime.UtcNow,
Status = OrderStatus.Pending,
TotalAmount = totalAmount
};
}
}

public enum OrderStatus
{
Pending,
Completed,
Cancelled
}

public class Money
{
public decimal Amount { get; }
public string Currency { get; }

public Money(decimal amount, string currency)
{
Amount = amount;
Currency = currency;
}
}

在這裡,我們定義了 Order 實體,其中包含訂單的核心屬性和行為,例如取消訂單、完成訂單等。Money 是一個值物件,用來表示訂單的金額,具有金額和貨幣屬性。

3. 應用層(Application Layer)

應用層負責協調流程,它不包含業務邏輯,而是通過調用領域層的實體和服務來處理具體的業務操作。

應用服務範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class OrderService
{
private readonly IOrderRepository _orderRepository;

public OrderService(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}

public async Task<Guid> CreateOrder(decimal amount, string currency)
{
var order = Order.Create(Guid.NewGuid(), new Money(amount, currency));
await _orderRepository.AddAsync(order);
return order.OrderId;
}

public async Task CancelOrder(Guid orderId)
{
var order = await _orderRepository.GetByIdAsync(orderId);
order.Cancel();
await _orderRepository.UpdateAsync(order);
}

public async Task CompleteOrder(Guid orderId)
{
var order = await _orderRepository.GetByIdAsync(orderId);
order.Complete();
await _orderRepository.UpdateAsync(order);
}
}

這個 OrderService 類別作為應用層的一部分,負責處理訂單的業務流程,但具體的業務邏輯由領域層的 Order 實體來執行。IOrderRepository 是一個存儲庫介面,處理數據存取的具體實現。

4. 基礎設施層(Infrastructure Layer)

基礎設施層負責實現資料庫訪問和其他技術細節,具體實現 IOrderRepository

存儲庫實現範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public interface IOrderRepository
{
Task<Order> GetByIdAsync(Guid orderId);
Task AddAsync(Order order);
Task UpdateAsync(Order order);
}

public class OrderRepository : IOrderRepository
{
private readonly ApplicationDbContext _dbContext;

public OrderRepository(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}

public async Task<Order> GetByIdAsync(Guid orderId)
{
return await _dbContext.Orders.FindAsync(orderId);
}

public async Task AddAsync(Order order)
{
await _dbContext.Orders.AddAsync(order);
await _dbContext.SaveChangesAsync();
}

public async Task UpdateAsync(Order order)
{
_dbContext.Orders.Update(order);
await _dbContext.SaveChangesAsync();
}
}

這裡的 OrderRepository 使用 Entity Framework Core 作為數據訪問層,實現了 IOrderRepository 來處理訂單的存取和更新。

5. 使用者介面層(UI Layer)

在這一層,API 控制器負責處理 HTTP 請求,並調用應用層服務來執行操作。

控制器範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
private readonly OrderService _orderService;

public OrdersController(OrderService orderService)
{
_orderService = orderService;
}

[HttpPost]
public async Task<IActionResult> CreateOrder(decimal amount, string currency)
{
var orderId = await _orderService.CreateOrder(amount, currency);
return Ok(orderId);
}

[HttpPost("{orderId}/cancel")]
public async Task<IActionResult> CancelOrder(Guid orderId)
{
await _orderService.CancelOrder(orderId);
return NoContent();
}

[HttpPost("{orderId}/complete")]
public async Task<IActionResult> CompleteOrder(Guid orderId)
{
await _orderService.CompleteOrder(orderId);
return NoContent();
}
}

這個 OrdersController 負責接收來自用戶的 HTTP 請求,並且通過 OrderService 來調用領域層中的業務邏輯。

小結

  • 領域層:處理核心業務邏輯,確保所有業務規則在這裡實現。
  • 應用層:協調業務流程,調用領域層來執行操作,不直接實現業務邏輯。
  • 基礎設施層:處理資料庫交互,與外部服務的集成等技術細節。
  • 使用者介面層:通過 API 控制器處理用戶請求,調用應用層進行業務操作。

在這個例子中,通過使用 DDD 原則,我們將業務邏輯、數據訪問和應用程式邏輯明確地分離,實現了清晰的責任分層,使得系統更具可維護性和擴展性。

這樣的架構模式有助於處理更複雜的業務需求,你可以依據具體的場景進一步擴展領域模型和服務。