昨天提到回傳boolean或錯誤碼帶來的問題
今天我們會針對上面的問題,使用Exception改善這些問題。以昨天的例子來說
public class OrderService
{
private readonly IOrderRepository _orderRepository;
...
public OrderStatus Save(Order order)
{
return _orderRepository.Save(order);
}
}
如果把它調整成使用Custom Exception
public class OrderService
{
private readonly IOrderRepository _orderRepository;
...
public void Save(Order order)
{
var orderStatus = _orderRepository.SaveOrder(order);
if (orderStatus == OrderStatus.Rejected)
{
throw new OrderRejectedException(order);
}
}
}
這樣一來TransactionService就可以透過catch攔截OrderRejectedException來處理異常流程。如果外部需要知道Rejected狀態時,也能透過throw把Exception再次丟出。
public class TransactionService
{
private readonly OrderService _orderService;
...
public void Save(int userId, int goodsId)
{
var order = new Order(GetUser(userId), GetGoods(goodsId));
try
{
_orderService.Save(order);
}
catch (OrderRejectedException e)
{
Refund(order);
throw;
}
}
}
在Action就不需要接取orderStatus處理成功的情況,而是利用try catch處理錯誤情況。如果是ASP.NET就能使用ActionFilter把錯誤流程移出去,讓Action裡面只剩下主要流程。
public IActionResult Confirm(int userId, int goodsId)
{
try
{
_transactionService.Save(userId, goodsId);
return Ok();
}
catch (OrderRejectedException)
{
return BadRequest();
}
}
假設Refund也有錯誤流程需要處理時,也能透過拋出Exception讓其他方法去處理。
讓錯誤流程透過拋出Exception的方式來控制流程,這種做法最大的好處就是需要處理的地方透過try catch的方式去處理,其他中間類別或方法就能維持其正常流程,不需要每個環節都要考慮異常狀態時要如何傳回錯誤碼。
另外一個優點是能將主要流程凸顯在try中,讓閱讀代碼的人可以一看明白什麼是主要流程、什麼是錯誤處理流程。