我和我的团队正在讨论是否使用DTO模型作为接口合同的方法参数。请记住,我们正在使用接口,因此我们可以使用依赖项反转并将其模拟为单元测试的依赖项。
public interface IContract {
object Method1(DTOModel model);
}
public class Implementation1 {
public object Method1(DTOModel model) {
//do stuff with Property1 and Property2
}
}
public class Implementation2 {
public object Method1(DTOModel model) {
//do stuff with Property3 and Property4
}
}
public class DTOModel {
public string Property1 {get;set;}
public string Property2 {get;set;}
public string Property3 {get;set;}
public string Property4 {get;set;}
}
场景是这样的:我们试图在我们的实现中保持灵活性,以便我们可以同时使用它们。我不同意这种方法,除非两种实现都要求合同中的相同信息。在我看来,这将是一个单独的合同/实施,或者当前合同必须改变,同时只应使用一个实施。
我的想法是,如果您以这种方式使用DTO,则通过允许两个不同的实现基于设置的属性而表现不同的行为来打败合同。它还意味着消费者必须知道正在使用哪个实现来知道要完成操作所需的属性。最后,这意味着两个实现都可以访问彼此不需要的属性。
我解决此问题的方法是将DTOModel
的属性传递给实现,并使Implementation2
遵守该合同:
public object Method1(string property1, string property2) {
//do stuff with property1 and property2
}
问题是:如果知道您的实施不依赖于整个合同和/或依赖合同的不同部分来执行不同的事情,那么传递上述DTO是否可以接受?或者合同是否应明确实施其工作需要什么?
提前致谢。
更新: 为了澄清,这两种实现具有相同的目的,但在不同的提供者上运行。例如,我们可能使用2个成员资格提供程序,而一个提供程序需要2个特定属性,另一个需要2个不同的属性。它们的目的是相同的,因为它们都将对用户进行身份验证,但是每种实现方式都是不同的。
答案 0 :(得分:2)
就个人而言,我同意你的分析。我会传递DTO的属性。我不确定传递DTO是否违反了特定的原则或模式 - 它可能是,它有一些代码味道,但我的问题是它含糊不清并且意图并不清楚实施合同在未来。
让我们说有人出现并实施Implementation3,他们就得到了这个DTO。他们拥有所有这些属性,他们不确定什么是有用的,什么不是。此外,随着需求的增长和变化,DTO肯定会增长和变化。在您知道之前,DTO没有4个属性。也许它有8或10个属性,因为构建实现的每个人对参数的要求可能略有不同。您最终可能会遇到某人实施合同并获取作为参数传递的对象,其中包含8个无用的属性。
我会传递对给定任何实现方法明确有用的特定属性,或者创建多个DTO并传递相关的任何一个。在这种情况下,DTO本身的合同可能是一种选择。如果每种方法的要求不同,请创建单独的方法。
答案 1 :(得分:1)
可替代性是面向对象编程中的一个原则,它指出,在计算机程序中,如果S是T的子类型,则类型T的对象可以用类型S的对象替换(即,类型为T的对象可以替换为子类型S)的任何对象,而不改变T的任何理想属性(正确性,执行任务等)。
在您的示例中,如果您使用Implementation1
更改Implementation2
,则此原则将不再受理。
答案 2 :(得分:1)
如果方法只需要几个参数,则直接将它们作为参数传递。如果它需要超过三个或四个参数,重构它以使用DTO可能不是一个坏主意。
但是,如果你走这条路线,创建特定于这些操作的DTO类(不要在整个地方共享一个庞大,凌乱的类)。如果你的实现是如此根本不同,以至于它们不能共享相同的输入参数,我会回到绘图板并检查它们是否应该共享相同的接口。此外,重要的是,不要传递您在任何其他层(传输,UI等)中使用的相同DTO - 这会导致不应存在的讨厌耦合。