我知道您在思考(或大喊大叫),“不是另一个问题,它要求验证在分层体系结构中属于什么?!?” 好吧,是的,但是希望这会在这个问题上有所不同。
我坚信验证的形式多种多样,是基于上下文的,并且在体系结构的每个级别都有所不同。这是后期的基础-有助于确定应在每个层中执行哪种类型的验证。另外,经常出现的一个问题是授权检查在哪里。
示例场景来自餐饮业务的应用程序。白天,司机可能会不定期地将卡车上载到现场的任何多余现金上交办公室。该应用程序允许用户通过收集驾驶员的ID和金额来记录“现金下降”。这是一些基本代码来说明涉及的层:
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
...
}
}
我指出了在代码中放置过验证检查的10个位置。我的问题是,在给定以下业务规则的情况下,您将对每种业务进行哪些检查(以及对长度,范围,格式,类型等的标准检查):
- 现金下降额必须大于零。
- 现金滴必须有一个有效的驱动程序。
- 必须授权当前用户添加现金滴(当前用户不是驱动程序)。
请分享您的想法,您对这种情况的看法或处理方式以及选择的理由。
CashDropAmount
值对象而不是使用来利用值对象Decimal
。检查驱动程序是否存在将在命令处理程序中完成,授权规则也是如此。Approver approver = approverService.findById(employeeId)
如果员工不在批准者角色中,您可以通过执行类似的操作来免费获得授权。Approver
只会是一个价值对象,而不是一个实体。你也可以得到在AR摆脱你的工厂或工厂的使用方法,而不是:cashDrop = driver.dropCash(...)
。