Tôi biết bạn đang suy nghĩ (hoặc có thể la hét), "không phải là một câu hỏi khác hỏi xác thực thuộc về kiến trúc lớp nào?!?" Vâng, vâng, nhưng hy vọng điều này sẽ có một chút khác biệt về chủ đề này.
Tôi là một người tin tưởng vững chắc rằng xác nhận có nhiều hình thức, dựa trên ngữ cảnh và thay đổi theo từng cấp độ của kiến trúc. Đó là cơ sở cho bài đăng - giúp xác định loại xác nhận nào sẽ được thực hiện trong mỗi lớp. Ngoài ra, một câu hỏi thường được đưa ra là nơi kiểm tra ủy quyền thuộc về.
Kịch bản ví dụ xuất phát từ một ứng dụng cho một doanh nghiệp phục vụ ăn uống. Định kỳ trong ngày, tài xế có thể chuyển đến văn phòng bất kỳ khoản tiền thừa nào họ đã tích lũy trong khi đưa xe tải từ nơi này sang nơi khác. Ứng dụng cho phép người dùng ghi lại 'giọt tiền' bằng cách thu thập ID tài xế và số tiền. Đây là một số mã bộ xương để minh họa các lớp liên quan:
public class CashDropApi // This is in the Service Facade Layer
{
[WebInvoke(Method = "POST")]
public void AddCashDrop(NewCashDropContract contract)
{
// 1
Service.AddCashDrop(contract.Amount, contract.DriverId);
}
}
public class CashDropService // This is the Application Service in the Domain Layer
{
public void AddCashDrop(Decimal amount, Int32 driverId)
{
// 2
CommandBus.Send(new AddCashDropCommand(amount, driverId));
}
}
internal class AddCashDropCommand // This is a command object in Domain Layer
{
public AddCashDropCommand(Decimal amount, Int32 driverId)
{
// 3
Amount = amount;
DriverId = driverId;
}
public Decimal Amount { get; private set; }
public Int32 DriverId { get; private set; }
}
internal class AddCashDropCommandHandler : IHandle<AddCashDropCommand>
{
internal ICashDropFactory Factory { get; set; } // Set by IoC container
internal ICashDropRepository CashDrops { get; set; } // Set by IoC container
internal IEmployeeRepository Employees { get; set; } // Set by IoC container
public void Handle(AddCashDropCommand command)
{
// 4
var driver = Employees.GetById(command.DriverId);
// 5
var authorizedBy = CurrentUser as Employee;
// 6
var cashDrop = Factory.CreateCashDrop(command.Amount, driver, authorizedBy);
// 7
CashDrops.Add(cashDrop);
}
}
public class CashDropFactory
{
public CashDrop CreateCashDrop(Decimal amount, Employee driver, Employee authorizedBy)
{
// 8
return new CashDrop(amount, driver, authorizedBy, DateTime.Now);
}
}
public class CashDrop // The domain object (entity)
{
public CashDrop(Decimal amount, Employee driver, Employee authorizedBy, DateTime at)
{
// 9
...
}
}
public class CashDropRepository // The implementation is in the Data Access Layer
{
public void Add(CashDrop item)
{
// 10
...
}
}
Tôi đã chỉ ra 10 vị trí mà tôi đã thấy kiểm tra xác thực được đặt trong mã. Câu hỏi của tôi là những gì kiểm tra bạn sẽ, nếu có, sẽ được thực hiện tại mỗi quy tắc kinh doanh nhất định sau (cùng với kiểm tra tiêu chuẩn về độ dài, phạm vi, định dạng, loại, v.v.):
- Số tiền giảm phải lớn hơn 0.
- Việc thả tiền mặt phải có Tài xế hợp lệ.
- Người dùng hiện tại phải được ủy quyền để thêm tiền mặt (người dùng hiện tại không phải là tài xế).
Vui lòng chia sẻ suy nghĩ của bạn, cách bạn có hoặc sẽ tiếp cận kịch bản này và lý do cho sự lựa chọn của bạn.
CashDropAmount
đối tượng giá trị thay vì sử dụng a Decimal
. Kiểm tra xem trình điều khiển có tồn tại hay không sẽ được thực hiện trong trình xử lý lệnh và tương tự với các quy tắc ủy quyền. Bạn có thể nhận được ủy quyền miễn phí bằng cách làm một cái gì đó giống như Approver approver = approverService.findById(employeeId)
nơi nó ném nếu nhân viên không ở trong vai trò phê duyệt. Approver
sẽ chỉ là một đối tượng giá trị, không phải là một thực thể. Bạn cũng có thể thoát khỏi nhà máy của mình hoặc sử dụng phương pháp nhà máy trên AR thay thế : cashDrop = driver.dropCash(...)
.