我计划重构我正在维护的遗留.NET项目,主要涉及4个项目:
My.Company.Web
- 表示层。 ASP.NET MVC。My.Company.Service
- 服务层,定义服务接口并包含命令处理程序。由网络层调用。My.Company.DTO
- 包含DTO类的程序集,用于域和Web层之间的数据传输。My.Company.Domain
- 域名图层。My.Company.Data
- 持久层。当用户提交表单以更新某人的详细信息时,该过程看起来有点像这样:
PersonDetailsDTO
,其中包含多个简单字段,用于保存FirstName
,LastName
,Age
等,以及一个名为的复杂类型对象保存地址详细信息的AddressDTO
:var dto = new PersonDetails(...);
Controller使用DTO调用服务层:
_personService.UpdateDetails(dto);
在服务中:
public void UpdatePerson(PersonDetailsDTO dto)
{
var person = _personRepository.GetById(dto.PersonId);
person.Update(dto);
_personRepository.Update(person);
}
在Person域中:
public class Person : AggregateRoot
{
private string FirstName;
.... // other fields
private Address Address;
public void Update(PersonDetailsDTO dto)
{
FirstName = dto.FirstName;
.... // other fields
Address.Update(dto.AddressDTO); // update the value object - address
}
}
正如您在此处所见,Person
域引用了PersonDetailsDTO
。这对我来说是错误的,因为DTO是将域中的数据呈现给其客户端而不暴露域本身的手段。域名应该不关注它如何呈现给客户。
另外IMO DTO应该住在My.Company.Service
项目中,因为它是定义操作/数据传输合同的服务。
但是,服务如何将详细信息传递给域?它是否必须是一个参数列表:person.Update(firstName, lastName, age, gender, street1, street2, state, postcode...)
。这对我来说当然是错的。
或者域名是否必须定义另一组自己的" DTO"接收客户数据?
我已经完成了大量的教程和SO帖子,似乎没有人分享我的关注,所以我开始认为我在这里错过了一些东西,有人能指出我正确的方向吗?
答案 0 :(得分:2)
根据Dependency inversion principle和DDD,Value objects
(您称之为DTOs
:PersonDetailsDTO
和Address
)应为 {域名{3}} 。这意味着它们应该驻留在Domain命名空间/包/项目中。而顺便说一句,那些Value objects
可以一直用到表示层并返回。
其次,它们不是DTOs
(数据传输对象),因为没有涉及昂贵的远程调用,而是Value objects
(内聚数据和可能的行为);阅读更多owned如何不将它们用作反模式。
最后但并非最不重要的一点是,您应该使用无处不在的语言(person.Update
似乎不是来自UL)的术语来命名您的方法。我不是说100%是你的情况,因为我不知道你的域名,我只是说你应该注意这些重要的细节(命名事物)。
答案 1 :(得分:1)
您可以执行以下操作。
您已经拥有一个名为http://localhost:63037/api/exposureRuns/data/?id=3&secsymb=undefined&fund=EL&esectype=SWAP_CDS
的值对象,您可以将另一个值对象作为Address
,其中包含firstName,lastName,age,gender等,PersonalDetails
实体将有两个行为,如Person
和updatePersonalDetails()
。您的应用程序服务如下所示。
updateAddress()
答案 2 :(得分:1)
您需要实现Object to Object映射。这意味着Service层负责通过映射从客户端收到的DTO实例中的值来创建和填充基于DTO的域对象。
您可以利用Automapper库来简化对象到对象的映射。 当然,如果需要,它可以为DTO提供域名。