在我们的应用程序中,我们有一个场景,其中我们需要基于业务规则和当前用户的上下文来验证属性更新。我正在尝试确定进行验证的最佳方法,因为我认为域模型不应该知道当前用户。我们的正常授权与域是分开的,并且与此场景不同。
验证应该在哪里进行,有没有更好的方法来处理它?域模型应该知道用户的情况吗?如有任何帮助或建议,我们将非常感谢。
简单的例子:我们有一个具有批准数量的订单。只有特定用户类型才能在特定方向上更新数量。这是在域聚合中验证的正确方式吗?
public enum UserType
{
ViewUserType,
RequesterUserType,
SupplierUserType
}
public class Order
{
public int OrderId {get; private set}
public int RequestedQuantity {get; private set}
public int ApprovedQuantity {get; private set}
public void RequestQuantity(int quantity, UserType userType)
{
if (userType == UserType.RequesterUserType)
{
this.RequestedQuantity = quantity;
}
}
// Question: The direction that the approved quantity can change is a business rule
// but directly deals with the context of the user. Should the model know about the user
// or should this validation be pulled out to either the application service, a model extension,
// or maybe a specification?
public void ApproveQuantity(int quantity, UserType userType)
{
if (userType == UserType.RequesterUserType)
{
if (quantity <= this.ApprovedQuantity)
{
// Requester type user can only update if lowering the approved quantity
this.ApprovedQuantity = quantity;
}
}
else if(userType == UserType.SupplierUserType)
{
if (quantity >= this.ApprovedQuantity)
{
// Supplier type user can only update if increasing the approved quantity
this.ApprovedQuantity = quantity;
}
}
}
}发布于 2013-05-11 15:55:56
这稍微受到了Yves的回答和你的回复的启发。
我个人的信条是让隐含的东西变得明确,因为我喜欢应用这个原则后代码的结果:
public interface IProvideCurrentIdentityRoles
{
bool CanRequestQuantity()
bool CanApproveQuantity();
bool CanOverruleQuantityOnSubmittedOrder();
bool CanIncreaseQuantityOnFinalOrder();
bool CanDecreaseQuantityOnFinalOrder();
}
public class Order
{
public int OrderId {get; private set}
public int RequestedQuantity {get; private set}
public int ApprovedQuantity {get; private set}
public void RequestQuantity(int quantity, IProvideCurrentIdentityRoles requester)
{
Guard.That(requester.CanRequestQuantity());
this.RequestedQuantity = quantity;
}
public void ApproveQuantity(int quantity, IProvideCurrentIdentityRoles approver)
{
if (quantity == this.RequestedQuantity)
{
Guard.That(approver.CanApproveQuantity());
}
else
{
if (orderType == OrderType.Submitted)
{
Guard.That(approver.CanOverruleQuantityOnSubmittedOrder());
}
else if (orderType == OrderType.Final)
{
if (quantity > this.ApprovedQuantity)
{
Guard.That(approver.CanIncreaseQuantityOnFinalOrder());
}
else
{
Guard.That(approver.CanDecreaseQuantityOnFinalOrder());
}
}
}
this.ApprovedQuantity = quantity;
}
}发布于 2013-05-07 04:44:07
与其拥有这种类似枚举的类型(UserType),为什么不将这些角色演变成完全成熟的对象呢?你关心的是用户扮演的角色,而不是特定的用户。这将用户确实是提供者或请求者的身份验证和验证推送到上面的层(实际上是调用代码,在本例中可能是某种应用程序服务)。下面是一个非常粗糙的,第一次迭代的可能是什么样子:
public class Order {
public void RequestQuantity(int quantity, UserType userType)
{
this.RequestedQuantity = quantity;
}
public void ApproveToLowerOrEqualQuantity(int quantity) {
if (quantity <= this.ApprovedQuantity)
{
// Requester type user can only update if lowering the approved quantity
this.ApprovedQuantity = quantity;
}
}
public void ApproveToHigherOrEqualtQuantity(int quantity) {
if (quantity >= this.ApprovedQuantity)
{
// Supplier type user can only update if increasing the approved quantity
this.ApprovedQuantity = quantity;
}
}
}
//Calling code
public class ApplicationServiceOfSomeSort {
public void RequestQuantity(UserId userId, OrderId orderId, int quantity) {
var requester = requesterRepository.FromUser(userId);
requester.MustBeAbleToRequestQuantity();
var order = orderRepository.GetById(orderId);
order.RequestQuantity(quantity);
}
public void ApproveQuantityAsRequester(UserId userId, OrderId orderId, int quantity) {
var requester = requesterRepository.FromUser(userId);
requester.MustBeAbleToApproveQuantity();
var order = orderRepository.GetById(orderId);
order.ApproveToLowerOrEqualQuantity(quantity);
}
public void ApproveQuantityAsSupplier(UserId userId, OrderId orderId, int quantity) {
var supplier = supplierRepository.FromUser(userId);
supplier.MustBeAbleToApproveQuantity();
var order = orderRepository.GetById(orderId);
order.ApproveToHigherOrEqualQuantity(quantity);
}
}诚然,这个API周围仍然有很多“臭味”,但这是一个开始。
https://stackoverflow.com/questions/16400405
复制相似问题