DDD会导致很多添加/更改方法和构造函数重载吗?

时间:2012-10-19 16:18:01

标签: c# domain-driven-design domain-model

我有一个班级:

    public class Person
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public string Email { get; private set; }
    public string Telephone { get; private set; }
    public Address Address { get; private set; }

    public Person(string firstName, string lastName)
    {
        //do null-checks
        FirstName = firstName;
        LastName = lastName;
        Address = new Address();
    }

    public void AddOrChangeEmail(string email)
    {
        //Check if e-mail is a valid e-mail here
        Email = email;
    }

    public void AddOrChangeTelephone(string telephone)
    {
        //Check if thelephone has correct format and valid symbols
        Telephone = telephone;
    }

    public void AddOrChangeAdress(Address address)
    {
        Address = address;
    }

不在构造函数中的属性是可选的,即该人不需要电子邮件,地址或电话。但是,我希望为类的用户提供创建对象的机会,而无需先提供所需的信息,然后必须找出用于添加信息的方法。

问题:

  1. 是否可以创建3个额外的重载来为它们提供选项?
  2. 我应该在可选属性上允许公共setter并在那里进行验证吗?
  3. 如果此人结婚并更改姓氏,我是否需要其他方法来更改姓氏,或者我是否应该公开此setter,并且只需要在构造函数中使用它们?

3 个答案:

答案 0 :(得分:3)

  1. 没有
  2. 公开。
  3. 假设您将在AddOrChange方法中拥有更多代码,例如格式化逻辑或验证,那么我将执行以下操作。否则,我完全摆脱了AddOrChange方法:

    public class Person
    {
        private string _email = string.empty;
        private string _telephone = string.empty;
        private Address _address = new Address();
    
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { 
            get { return _email }
            set { AddOrChangeEmail(value); }
        }
        public string Telephone { 
            get { return _telephone;}
            set { AddOrChangeTelephone(value); }
         }
        public Address Address { 
            get { return _address;  }
            set { AddOrChangeAddress(value); }
        }
    
        public Person(string firstName, string lastName)
        {
            //do null-checks
            FirstName = firstName;
            LastName = lastName;
        }
    
        private void AddOrChangeEmail(string email)
        {
            //Check if e-mail is a valid e-mail here
            _email = email;
        }
    
        private void AddOrChangeTelephone(string telephone)
        {
            //Check if thelephone has correct format and valid symbols
            _telephone = telephone;
        }
    
        private void AddOrChangeAddress(Address address)
        {
            _address = address;
        }
    }
    

    要使用此课程,您可以执行以下任何操作:

    Person p = new Person("Tom", "Jones");
    p.Telephone = "9995551111";
    

    Person p = new Person("Tom", "Jones") { Telephone = "9995551111", Email="spamme@ms.com" }
    

答案 1 :(得分:2)

AddOrChange等同于带有公共setter的简单属性,因此您不需要这些方法。

public class Person
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public Email Email { get; set; }
    public Telephone Telephone { get; set; }
    public Address Address { get; set; }

    public Person(string firstName, string lastName)
    {
        //do null-checks
        FirstName = firstName;
        LastName = lastName;
    }
}
  1. 如果用户在创建人员时希望在所需数据旁边提供其他内容,则可以使用类初始值设定项。您还可以向构造函数添加一些可选参数。

    var bob = new Person("Bob", "Uncle") { Address = someAddress };

  2. 如果人们可以重新安置,那么为什么不使用公共设置器来更改地址呢?当然,您应该检查地址是否有效。此外,如果重新定位是一个业务流程(即您正在重新安置酒店中的某个人),那么在域服务上进行此操作会更好(这将验证目的地房间是否为空并准备就绪)。

  3. 允许更改名称即可。通常名称不是此类实体的身份,因此可能会发生变化。

  4. 另外,我介绍了电子邮件和电话的价值对象。我认为验证电子邮件地址是否有效并非由此负责。将其移至电子邮件类。与电话和地址相同。

答案 2 :(得分:1)

  

很多添加/更改方法和构造函数重载是DDD的结果吗?

不,许多更新方法不是DDD的结果。

<强>代码

您的Person课程可以重写为只有2种更新方法:

class Person

    public function Rename(FirstName as Name, LastName as Name) as Person

    public function ChangeContacts(
        Address as Maybe(of Address), 
        Phone as Maybe(of Phone), 
        Mail as Maybe(of MailAddress)) as Person
end class

Rename方法接受特殊Name类型的两个必需参数。名称的验证检查在创建名称时发生,而不是在它们传递到Person类时发生。

ChangeContacts方法接受三个可选参数,其中任何参数都可以不存在。特殊Maybe类型表示它们是可选的。特殊AddressPhoneMailAddress类型表示这些参数已经生效,无需在Person类中再次验证它们。

用例

人结婚并更改姓氏

Person = Person.
    Rename(Person.FirstName, LastNameAfterMarriage)

人购买新电话号码

Person = Person.
    ChangeContacts(Person.Address, NewPhoneNumber, Person.Mail)

人丢失了电话号码

Dim NewPhoneNumber = Maybe.Create(Nothing)
Person = Person.
    ChangeContacts(Person.Address, NewPhoneNumber, Person.Mail)

模式是使用旧值+一些新值调用更新方法。