DTO应该使用继承还是组合?

16
在SOA中,如果一些DTO类具有一些重复的字段,是使用组合还是继承更好,以便不重复,或者只是使用一个封装所有字段的DTO类。随着我的DTO类增长,我看到很多重复的字段名称和Sonar报告正在哭泣。最好的方法(或替代方法)是什么。
public class DocDto{
    private Long id;
    private String name;
    private String docType
}

public class DocReviewDto{
    private Long id;
    private String name;
    private String status;
    private String comment;
}

2
如果一个DTO与另一个DTO存在“是一个”的关系,那么它应该使用继承吗?如果一个DTO与另一个DTO存在“有一个”的关系,那么它应该使用组合吗?这些是你应该问的真正问题。继承或组合本身并不是目的。 - scottb
1个回答

21
"一种DTO类"的方法几乎肯定是不好的。它像是一个全能类(God Class)。许多专家强烈谴责DTO。你可以继承自某个基类,但对于值对象来说这并不真正合理。对于组合也是同样的情况。它会让你的代码变得更加复杂。在调试“DocReview”流程时,你可能需要查看两个、三个或更多的DTO类才能理解其含义。呕吐!此外,每个DTO通常处于单独的语义域:“Doc”和“DocReview”并不相同。因此,表面上的“共同”元素实际上根本不是共同的。它们只是共享了一种实现类型;它们的含义是完全不同的。

例如,如果成员类型本质上是组合的,例如许多领域共享标识符(Identifier)的概念,那么你可以将其作为一种类型进行组合,融入到这些领域的DTO中。在你的例子中,你可能会有

public class Identifier {
  long id; // should be a 'String', actually
  String name;
}

public class Doc {
  private Identifier identifier;
  private String docType
}

public class DocReview {
  private Identifier identifier;
  private String status;
  private String comment;
}

关键在于Identifier在两个领域中语义上是等价的,因此将其作为公共类型是有意义的。否则您不会这样做。

旁注:"Dto"(或"DTO")作为后缀并不是一个好的命名方式。


1
Lew说...一般情况下要避免继承,而倾向于组合。继承是实现多态性的好方法(汽车->法拉利->型号XXX)。 - Guillaume F.
4
提取出共同的字段组成一个类,并使用组合是有意义的。我同意命名规则xxxDto很尴尬,但我们的实体被命名为例如Doc,因此需要一些区别的方法。你说过 - 许多权威人士完全谴责DTOs - 为什么?我们有哪些替代方案? - pingu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接