DDD - 域如何接收客户端数据

时间:2017-12-08 03:04:44

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

我计划重构我正在维护的遗留.NET项目,主要涉及4个项目:

  • My.Company.Web - 表示层。 ASP.NET MVC。
  • My.Company.Service - 服务层,定义服务接口并包含命令处理程序。由网络层调用。
  • My.Company.DTO - 包含DTO类的程序集,用于域和Web层之间的数据传输。
  • My.Company.Domain - 域名图层。
  • My.Company.Data - 持久层。

当用户提交表单以更新某人的详细信息时,该过程看起来有点像这样:

  1. 使用提交的数据,控制器构造一个PersonDetailsDTO,其中包含多个简单字段,用于保存FirstNameLastNameAge等,以及一个名为的复杂类型对象保存地址详细信息的AddressDTOvar dto = new PersonDetails(...);
  2. Controller使用DTO调用服务层:

    _personService.UpdateDetails(dto);
    
  3. 在服务中:

    public void UpdatePerson(PersonDetailsDTO dto)
    {
        var person = _personRepository.GetById(dto.PersonId);
        person.Update(dto);
        _personRepository.Update(person);
    }
    
  4. 在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
        }
    }
    
  5. 正如您在此处所见,Person域引用了PersonDetailsDTO。这对我来说是错误的,因为DTO是将域中的数据呈现给其客户端而不暴露域本身的手段。域名应该关注它如何呈现给客户。

    另外IMO DTO应该住在My.Company.Service项目中,因为它是定义操作/数据传输合同的服务。

    但是,服务如何将详细信息传递给域?它是否必须是一个参数列表:person.Update(firstName, lastName, age, gender, street1, street2, state, postcode...)。这对我来说当然是错的。

    或者域名是否必须定义另一组自己的" DTO"接收客户数据?

    我已经完成了大量的教程和SO帖子,似乎没有人分享我的关注,所以我开始认为我在这里错过了一些东西,有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:2)

根据Dependency inversion principle和DDD,Value objects(您称之为DTOsPersonDetailsDTOAddress)应为 {域名{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实体将有两个行为,如PersonupdatePersonalDetails()。您的应用程序服务如下所示。

updateAddress()

答案 2 :(得分:1)

您需要实现Object to Object映射。这意味着Service层负责通过映射从客户端收到的DTO实例中的值来创建和填充基于DTO的域对象。

您可以利用Automapper库来简化对象到对象的映射。 当然,如果需要,它可以为DTO提供域名。