我有一个班级:
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;
}
不在构造函数中的属性是可选的,即该人不需要电子邮件,地址或电话。但是,我希望为类的用户提供创建对象的机会,而无需先提供所需的信息,然后必须找出用于添加信息的方法。
问题:
答案 0 :(得分: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;
}
}
如果用户在创建人员时希望在所需数据旁边提供其他内容,则可以使用类初始值设定项。您还可以向构造函数添加一些可选参数。
var bob = new Person("Bob", "Uncle") { Address = someAddress };
如果人们可以重新安置,那么为什么不使用公共设置器来更改地址呢?当然,您应该检查地址是否有效。此外,如果重新定位是一个业务流程(即您正在重新安置酒店中的某个人),那么在域服务上进行此操作会更好(这将验证目的地房间是否为空并准备就绪)。
允许更改名称即可。通常名称不是此类实体的身份,因此可能会发生变化。
另外,我介绍了电子邮件和电话的价值对象。我认为验证电子邮件地址是否有效并非由此负责。将其移至电子邮件类。与电话和地址相同。
答案 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
类型表示它们是可选的。特殊Address
,Phone
和MailAddress
类型表示这些参数已经生效,无需在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)
模式是使用旧值+一些新值调用更新方法。