2

我有一堂课:

    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. 我应该允许可选属性上的公共设置器并在那里进行验证吗?
  3. 如果此人结婚并更改姓氏,我是否需要其他方法来更改姓氏,或者我是否也应该将此设置器公开,并且只在构造函数中要求它们?
4

3 回答 3

4
  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" }
于 2012-10-19T16:25:52.983 回答
3

AddOrChange相当于具有公共设置器的简单属性,因此您不需要这些方法。

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. 允许更改名称是可以的。通常名称不是此类实体的身份,因此它可能会更改。

此外,我还介绍了电子邮件和电话的价值对象。我认为验证电子邮件地址是否有效不是个人的责任。将其移至电子邮件类。与电话和地址相同。

于 2012-10-19T16:24:04.773 回答
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类型表示它们是可选的。SpecialAddress和类型表示这些参数已经有效PhoneMailAddress不需要在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)

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

于 2016-01-04T09:22:58.713 回答