【问题标题】:Modularity: Using Interfaces or not?模块化:是否使用接口?
【发布时间】:2011-04-17 16:48:22
【问题描述】:

几年以来,常识似乎表明最好针对接口进行编程而不是针对实现进行编程。对于高级代码,这确实看起来合乎逻辑,例如如果我的应用程序中有一个复杂的求解器,最好有这样的东西:

ISolver *solver = solverFactory.getSolver();
solver->solve(inputdata);

而不是

Solver solver;
solver.solve(inputdata);

在第一个代码中,模拟求解器也更容易,因此也更容易进行单元测试。

但我的问题是:在哪个级别使用界面不再有意义。例如。如果我的应用程序中有一个 ComplexNumber 类(或 String 类,或其他),那么写这个:

IComplexNumber *complexNumber = complexNumberFactory.create(1,2);   // 1+2i

似乎比写作复杂得多(尤其是在性能方面):

ComplexNumber complexNumber(1,2);   // 1+2i

那么,哪些元素在决定是否应将某物放在界面后面以及何时不应将其放在界面后面时很重要?

【问题讨论】:

    标签: c++ interface dependency-injection modularity


    【解决方案1】:

    迁移到接口的原因是它使事情变得更简单或减少了耦合。 (这就是接口的用途)。

    放弃界面的原因是它会使事情变得更复杂或降低性能(但可以肯定的是)。我认为你的 IComplexNumber 类实际上使类层次结构更加复杂,除非你引入一个 MockComplexNumber,但我怀疑这样一个类是否有用......它可能会使事情变慢,但我会衡量.

    但不要认为您需要以一种方式做所有事情,或者您的决定是一成不变的。使用界面转换/转换非常容易。

    【讨论】:

      【解决方案2】:

      对于 C++,这无关紧要,因为 C++ 具有多重继承,因此接口是一个抽象类,您可以添加实现。我发现最常用的接口是 Java 和 C#,它们具有单一继承,如果你想让一个类实现几件事,那么只有一个可以是抽象类,其他的必须是接口

      【讨论】:

      • 原因1:编写可测试的代码,你应该能够使用mockobject创建单元测试,mock objects只是从你的实际模块中实现一些接口。原因 2:您应该能够使您的代码尽可能抽象。有时,除了功能之外,您对类一无所知,假设您有一个客户端,您不知道客户端是网络/tcp 客户端还是通过管道交互的 http 进程客户端或您只知道的其他东西主界面,connect,disconnect,sendData等方法...
      • 不依赖于语言,以策略、访问者模式为例。
      • @Alex 你仍然可以从抽象类创建模拟对象,不必是接口
      【解决方案3】:

      如果根据它们所扮演的角色将类分为“服务”类和“价值”类,那么答案很简单。仅在服务类上使用接口。在您的问题中,“求解器”是一项服务,“复数”是一个值。

      值类应该很容易使用 new() 创建,因为它们只接受构造函数中的基本类型和其他值类。值类对模拟没有用,因为您可以使用真实的东西。

      模拟服务类可能很有用,您可能需要多个实现。你的solverFactory可以返回一个naiveSolver、一个lookupSolver、一个geneticSolver、一个mockSolver等。这里的接口是有用的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-05
        • 2018-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多