代码之家  ›  专栏  ›  技术社区  ›  n8wrl

界面疯狂

  •  8
  • n8wrl  · 技术社区  · 17 年前

    我喝着coolade,喜欢它——界面、IoC、DI、TDD等等,一切都很好。但我发现我必须与一种倾向作斗争 每件事 界面!我有一个工厂,它是一个接口。它的方法返回可能是接口的对象(可能使测试更容易)。这些对象是它们所需服务的DI接口。我发现,保持接口与实现的同步是在增加工作—将方法添加到类意味着将其添加到类+接口、模拟等。

    我是否过早地将接口分解出来?是否有最佳实践来了解什么时候应该返回接口和对象?

    8 回复  |  直到 17 年前
        1
  •  7
  •   Stuart Caborn    17 年前

    当您想要模拟对象与其合作者之间的交互时,接口非常有用。但是,对于具有内部状态的对象,接口中的值较小。

    例如,假设我有一个与存储库对话的服务,以便提取某个域对象,以便以某种方式对其进行操作。

    从存储库中提取接口具有明确的设计价值。我对存储库的具体实现很可能与NHibernate或ActiveRecord密切相关。通过将我的服务链接到接口,我完全脱离了这个实现细节。碰巧我也可以为我的服务编写超快的独立单元测试,现在我可以给它一个模拟IRepository了。

    考虑到从存储库返回的域对象以及我的服务所作用的域对象,其价值较小。当我为我的服务编写测试时,我希望使用一个真正的域对象并检查其状态。例如,在调用service.AddSomething()之后,我想检查是否向域对象添加了内容。我可以通过简单地检查域对象的状态来测试这一点。当我单独测试我的域对象时,我不需要接口,因为我只需要对对象执行操作,并测试它的内部状态。e、 如果我的羊在睡觉,它吃草是合法的吗?

    在第一种情况下,我们对 相互作用 基于测试。接口之所以有帮助,是因为我们想要截获被测对象与其具有mock的协作者之间传递的调用。在第二种情况下,我们感兴趣的是 基于测试。接口在这里没有帮助。试着意识到您是在测试状态还是交互,并让它影响您的接口或无接口决策。

    请记住(如果您安装了Resharper的副本),以后提取接口非常便宜。如果您决定根本不需要该接口,那么删除该接口并恢复到更简单的类层次结构也很便宜。我的建议是从没有接口开始,当您发现想要模拟交互时,根据需要提取它们。

    当你把IoC带到图片中时,我倾向于提取更多的接口——但尽量控制你把多少类塞进IoC容器中。一般来说,您希望将这些限制为基本上无状态的服务对象。

        2
  •  6
  •   Ed Guiness    17 年前

    BDUF .

    轻松使用coolade,让它自然流动。

        3
  •  6
  •   Pontus Gagge    17 年前

    请记住,虽然灵活性是一个值得追求的目标,但增加IoC和DI的灵活性(在某种程度上是TDD的要求)也会增加复杂性。唯一的灵活性是让下游的变化更快、更便宜或更好。每一个IoC/DI点都会增加复杂性,从而使其他地方的更改更加困难。

    这实际上是你需要一个大的设计在前面 一些 范围:确定哪些领域最有可能发生变化(和/或需要广泛的单元测试),并在那里规划灵活性。重构以消除不太可能更改的灵活性。

    现在,我并不是说你可以准确地猜测哪里需要灵活性。你错了。但你很可能会做对一些事情。当您以后发现不需要灵活性时,可以在维护中考虑到这一点。在您需要它的地方,可以在添加功能时将其考虑在内。

    现在,可能改变或不改变的领域取决于您的业务问题和IT环境。这里有一些反复出现的地方。

    1. 集成到的接口
    2. 任何代码都可以为 用户界面需要支持UI中的更改。然而,主要计划功能上的变化:不要过火,计划不同的UI技术(例如支持智能客户端和web应用程序的使用模式会有太大的差异)。
    3. 另一方面,为 平台是 通常 浪费 至少在公司里 可能存在哪些计划来替换或删除 您的软件的可能寿命。
    4. 对数据内容和格式的更改是一个棘手的问题 业务:数据将 大多数设计偶尔会改变 我见过处理这种变化 很糟糕,所以你得到了具体的 直接使用的实体类。

    但只有你才能判断什么可能改变,什么不应该改变。

        4
  •  5
  •   Jon Skeet    17 年前

    我通常发现我想要“服务”的接口,而主要是“数据”的类型可以是具体的类。例如,我会有一个 Authenticator 接口,但是 Contact

    不过我确实感觉到了你的痛苦-这有点像回到.h和.c文件的黑暗时代。。。

        5
  •  2
  •   Jesse Smith    17 年前

    我认为最重要的“敏捷”原则是雅格尼(“你不需要它”)。换句话说,在实际需要之前不要编写额外的代码,因为如果提前编写,当(如果!)您最终需要它时,需求和约束可能已经发生了变化。

    接口、依赖注入等等——所有这些都增加了代码的复杂性,使其更难理解和更改。我的经验法则是让事情尽可能简单(但不是更简单),并且不增加复杂性,除非它让我获得足够多的东西来抵消它带来的负担。

    因此,如果您实际上正在测试并拥有一个mock对象,那么一定要定义一个mock类和real类都实现的接口。但是,不要纯粹基于假设的理由来创建一堆接口,即它在某些时候可能有用,或者它是“正确的”OO设计。

        6
  •  0
  •   Manrico Corazzi    17 年前

    接口的目的是建立契约,当您希望动态更改执行任务的类时,接口特别有用。如果不需要更改类,接口可能会遇到阻碍。

    有自动工具可以提取接口,因此您最好在以后的过程中延迟接口提取。

        7
  •  0
  •   TofuBeer    17 年前

    这在很大程度上取决于你提供什么。。。如果你在处理内部事务,那么“在需要之前不要做”的建议是合理的。但是,如果您正在制作一个供其他开发人员使用的API,那么在以后将其更改为接口可能会很烦人。

    一个很好的经验法则是用任何需要成为子类的东西制作接口。这不是一种“在那种情况下总是制作一个接口”的事情,你仍然需要考虑它。

    一些通常不是接口的类是只保存数据的类,比如处理x和y的Location类。实现这一目标的可能性很小。

        8
  •  -1
  •   Community Mohan Dere    9 年前

    不要先创建接口-你不需要它们。您无法猜测哪些类需要接口,哪些类不需要接口。因此,现在不要花费任何时间用无用的接口来加重代码的负担。

    但是,在重构步骤中,当您觉得迫切需要这样做时——当您看到需要一个接口时——提取它们。

    Those answers

    推荐文章