很多代碼會用boolean當作回傳的成功或失敗,例如:我們使用者的訂單儲存到資料庫時,我們會想知道這個動作最後有沒有成功。
public interface IOrderRepository
{
bool Save(Order order);
}
或者是當SaveOrder需要告訴外部更多資訊時,我們也常搭配Enum使用錯誤碼來表示狀態,例如:訂單成功時回傳Success、訂單還在等待接受時回傳Waiting、訂單被拒絕時回傳Rejected。
public enum OrderStatus
{
Success,
Waiting,
Rejected
}
public interface IOrderRepository
{
OrderStatus Save(Order order);
}
public class OrderService
{
private readonly IOrderRepository _orderRepository;
...
public OrderStatus Save(Order order)
{
return _orderRepository.Save(order);
}
}
TransactionService就會拿到OrderStatus後判斷,並把錢退回給使用者。
public class TransactionService
{
private readonly OrderService _orderService;
...
public OrderStatus Save(int userId, int goodsId)
{
var order = new Order(GetUser(userId), GetGoods(goodsId));
var status = _orderService.Save(order);
if (status == OrderStatus.Rejected)
{
Refund(order);
}
return status;
}
}
這樣的設計容易造成一些問題,假設今天Refundu也會回傳狀態來表示其成功或失敗。
public class TransactionService
{
private readonly OrderService _orderService;
...
public OrderStatus Save(int userId, int goodsId)
{
var order = new Order(GetUser(userId), GetGoods(goodsId));
var status = _orderService.Save(order);
if (status == OrderStatus.Rejected)
{
Refund(order);
if (isSuccess)
{
return status;
}
return OrderStatus.Rejected;
}
return status;
}
}
就會被OrderStatus的回傳值限制,因為回傳值必須是OrderStatus,所以導致Refund的結果必須在Save中判斷處理。
另一種情況是當有其他類別使用到OrderServer.Save時,很容易也會需要把status繼續往外傳,讓更外面的類別可以根據status中的某一個狀態做處理。例如:
public class TransactionController
{
...
public IActionResult Confirm(int userId, int goodsId)
{
var orderStatus = _transactionService.Save(userId, goodsId);
if (orderStatus == OrderStatus.Success)
{
return Ok();
}
return BadRequest();
}
}
下訂單成功的時候,我們通常不會需要特別處理,直到UI要把成功訊息顯示到使用者面前,或者是Api要回傳response時,我們才會判斷狀態是否成功。為了傳遞OrderStatus,中間所有類別的所有回傳值都被限制成OrderStatus。
今天的問題稍微有點複雜,我們稍微整理一下回傳boolean或錯誤碼帶來的問題
我們明天會繼續聊到該怎麼更有效地處理這種狀況。