我想知道设计DTO对象构造函数的最佳实践是什么。
说我有这样的Dto对象:
class CustomerDto
{
public string Name { get; set; }
public string Surname { get; set; }
public string Phone { get; set; }
...
}
有几种方法可以构建对象:
我可以声明一个构造函数:
public CustomerDto(string name, string surname, string phone, ...)
{
this.Name = name;
this.Surname = surname;
this.Phone = phone;
...
}
当您看到此构造函数并立即结束SRP(单一责任)违规时?
尽管这些属性都是相关的。
还可以说没有必要验证属性,因为这是一个DTO并且没有行为,而且行为应该放在这个映射的域对象上。
在C#中,我们也可以更优雅地构造这个对象:
var dto = new CustomerDto ()
{
Name = "Some name",
Surname = "Some surname"
}
或者使用流畅的构建器或框架,例如NBuilder。
还有Automapper等自动映射框架的用法。问题还在于使用Ioc容器,ctor变得复杂,以及交换参数的风险,例如,你传递姓氏在哪里,反之亦然,验证可能会错过这个更容易然后如上所述的显式映射。
请帮助说服我哪种方式更好。
答案 0 :(得分:12)
示例中的值类型不是依赖项。依赖项为消费者提供功能(或配置)。在您的情况下,它们只是分配给DTO的正常值。只要数据属于一起,即使在构造函数中分配了大量值,也不会违反SRP。在这种情况下,唯一的责任是保存数据。
此外,DTO不应由IoC容器创建,也不应具有真正的依赖关系。您应该通过持久性框架或使用自动映射手动创建它们。
如果使用构造函数或属性分配值更好取决于用法。如果需要它们,构造函数变体更好。如果它们是可选的,那么物业方式会更好。
答案 1 :(得分:5)
我建议使用不可变数据结构,这样DTO实体就不会暴露任何setter,显然这样构造函数应该能够初始化给定DTO的所有底层属性。
所以我更喜欢:
public CustomerDto(string name, string surname, string phone, ...)
DTO是一个数据传输对象,尤其用于表示要在系统(分布式)边界上传递的一组属性,因此不要过多关注SRP违规。 这就像Facade设计模式,它取消了一组操作/服务以简化使用。所以在这个kase Keep It Simple赢了。