NHibernate - 领域驱动设计 - 业务规则问题

时间:2010-01-20 11:08:32

标签: .net nhibernate design-patterns domain-driven-design

我有一名员工在一个集合中拥有多个地址。

public class Employee
{
    public string Name { get; set; }

    public AddressCollection Addresses { get; }
}


public class AddressCollection : IEnumerable<Address>
{
    private readonly Employee employee;
    private IList<Address> items = new List<Address>();

    public void AddAddress(Address address)
    {
        if (items.Contains(address)) return;

        address.Employee = employee;
        items.Add(address);
    }

    public void RemoveAddress(Address address)
    {
        items.Removce(address);
    }

    /// further IEnumerable implementations
}

public class Address
{
    public AddressType Type { get; set; }
    public City City { get; set; }
    public string Street { get; set; }

    public DateTime ValidFrom { get; set; }
    public DateTime ValidTo { get; set; }
}

public enum AddressType
{
    Default,
    ShippingAddress
}

一次只能有一种类型的某个地址有效。因此,当在1-1-2009到15-1-2009之间添加类型默认有效地址,然后在10-1-2009到15-1-2009之间另一个类型默认有效的地址时,需要抛出异常。

从DDD的角度来看,最好的方法是什么?当然,在 AddAddress方法中,我可以遍历现有地址并抛出异常。

但是,由于需要在表示层上检查此业务规则以向用户显示消息,因此我不应该使用内部以及表示层中可以使用的规范吗?

你会如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

首先,我将摆脱您的AddressCollection类并在Employee上实现其成员。

为了验证这样的规则,我推荐specification pattern。它不需要像维基百科文章那么复杂,它可以简单地是:

public class CanAddAddressToEmployeeSpec
{
    public bool IsSatisfiedBy(Address candidate)
    {  // logic to check address }
}

然后,您可以使用该类检查在添加地址之前是否可以将地址添加到Employee中,以便您的Employee对象不会进入无效状态。我还经常将一个Messages属性添加到规范中,如果IsSatisifiedBy为false,则返回解释。

如果您需要更多信心,可以为EmployeeAddressesAreValidSpec创建一个类似的规范,将Employee作为IsSatisfiedBy的候选参数,并在持久化数据之前检查它。

答案 1 :(得分:0)

我建议使用Microsoft模式和实践团队发布的企业库中的Validation Application Block

这允许您将验证逻辑放在域对象上(维护DDD),还可以填充对象,然后然后询问它是否有效,而不是抛出异常。

我不确定您的UI是什么,但验证应用程序块可以与ASP.NET,Windows窗体和WCF集成。

答案 2 :(得分:0)

我同意里奇的观点。开始查看验证应用程序块。 This article可能对您有所帮助,因为它描述了如何将VAB与O / RM框架集成。虽然本文侧重于LINQ to SQL和Entity Framework,但我希望NHibernate没有任何意外。