依赖注入+完全虚拟vs接口

时间:2015-01-28 12:45:36

标签: c++ tdd inversion-of-control solid-principles

我经常发现自己正在创建我在签名处使用的接口,以注入依赖关系,最后得到class AIfaceclass AImpl : public AIface。而且我经常从不实现class AIface

的任何其他子类

与直接使用所有公共方法虚拟的实现相比,这种方法有什么优势吗?


更长的解释:
假设我们有一个提供清洁服务的动物园。我们做TDD,我们希望能够用假FeedingSvc测试Zoo,所以我们选择依赖注入。

有什么区别:

class FeedingSvcIface{
   virtual void performFeeding() = 0;
} ;
class RoboticFeedingSvc: public FeedingSvcIface{
           void performFeeding();
};
Class Zoo{
   Zoo(FeedingSvcIface&);
//...
};

VS

class RoboticFeedingSvc{
    virtual void performFeeding();
};
Class Zoo{
   Zoo(RoboticFeedingSvc&);
//...
};

(如果需要,将来提取界面)

在测试方面,前者似乎更容易。

我通常会发现,当我和一个“#34;穿越图层"但有时候它只是关于测试 我知道将来我可能需要实现其他类型的FeedingSvcs,但为什么要在今天做抽象,如果我真的不需要?,
我可能会拆分两个类来封装一些逻辑。

1 个答案:

答案 0 :(得分:3)

坚持最佳实践,设计模式或其他习惯用法的优势在于,尽管你现在做了一些额外的努力,但从长远来看,你获得了更多。

想象一下你在一个团队中工作的场景,有多个开发人员,有些经验丰富,有些没有。

您是Zoo机制的创建者,但您决定,暂时,您将在KISS原则上实现Zoo,而不添加额外的抽象。你为自己设定了一个心理记录(或者甚至是一个不错的小评论),指出“如果RoboticFeedingSvc有多个不同的行为,那么依赖注入就会有抽象!”。

现在,由于你真的很棒的工作,你可以去度假,一些初级开发人员将继续保留你的代码。

开发人员的任务之一是引入ManualFeeding选项和混合选项。您可以考虑多少种方法(忽视任何编码原则)?

因为你,创建者,没有强制机制增长的方式,初级开发人员会查看你的评论,添加“LoL u mad bro :)”评论,然后选择以下之一:

  • 创建一个由其他FeedingSvcs派生的基础界面(你很幸运)
  • 使用策略模式为RobotFeedingSvc创建依赖注入(根据如何提供某些内容设置一些仿函数)
  • 使RobotFeedingSvc成为Feeder,Feeded和某些Action函数之间的复合体
  • 让RobotFeedingSvc成为一个单独的工厂(因为单身人士工厂很棒且很花哨),不知何故在动物园内使用它来返回适当的喂养技术(这里重要的是他使用了单身和工厂)
  • 创建一个动画版本的动物园,它带有一个模板化的RobotFeedingSvc版本,根据给定的FeedingPolicy和Feeder进行部分专业化(因为他只是碰到模板,模板应该在任何地方使用)。

我想我们可以在几个方面总结一下这个故事:

初步努力正确地使应用程序中所需的抽象层在功能方面具有可扩展性,这将有助于其他开发人员(包括此处的未来)快速了解使用现有代码实现新功能的正确方法只是用一些疯狂的想法来破解它。

强制您的Zoo类采用接口而不是具体类几乎等同于留下评论说新功能需要实现此接口。

允许将一个具体类作为参数传递可能会将注意力转移到如何更改具体类而不是在其上实现某些内容。

另一个更为技术性的原因如下:

他需要添加新功能,但不允许他更改Zoo实现。现在怎么办?