我知道有一个类似的问题Here但我认为我会对此进行更多扩展。
我最近一直致力于一个已经投入生产大约一年的应用程序,没有任何问题,也没有真正的扩展计划。该应用程序具有很少的依赖性并使用DI但没有容器。
现在我正在将应用程序扩展到公司指令的更广泛范围,这促使我实现了IoC容器的使用。这里的问题是向我以前认为不需要的代码添加容器的开销。
我向前迈进的具体问题是:
在规划和编码可能不会扩展太多的较小应用程序时,我是否应该实现容器,以期预测这些场景可能会出现这种情况,并且在这样的预期中我最好从一开始就实现容器在扩展时,框架已经存在。
如果在扩展应用程序超出其初始意图时实现容器变得很麻烦,这是否表示设计不佳?
编辑:
我正在使用可靠的原则(尽我所能)并在我的应用程序中广泛接口,问题更多地与使用IoC容器有关,而不是DI本身。之前提到的应用程序是一个自己动手的DI风格,我正在添加一个容器,问题出现在哪里。
答案 0 :(得分:3)
我是Clean Code
的忠实粉丝,特别是YAGNI
。 “你不需要它”。如果项目中不需要DI,请不要使用它。如果您需要DI进行单元测试但不需要容器,请不要使用容器。简单是它自己的优点。保持尽可能简单。
如果为未来的可扩展性准备项目现在花费时间或金钱,请不要这样做。您可以在将来支付。因为未来可能永远不会到来。如果确实如此,它肯定不会像预测的那样,你的准备工作将没有你想象的那么有用。
我参与过那么多“可扩展性”代码的项目,你可以删除至少75%的源代码,所有必需的功能仍然存在。我没有想到项目经理想知道实施这样一个基本功能到底需要多长时间。不要那样做。计划您的项目,获得您的要求并实施它们。如果需要可扩展性,请计划,估计它,让您的经理知道。我的猜测是他们不想那么严重的可扩展性。他们宁愿换另一个工作计划。
那就是说,显然你在学习。如果它在时间或金钱方面没有任何成本,请继续开发下一个程序,以便更容易扩展。请密切关注成本。
答案 1 :(得分:2)
我认为使用DI即使在最小的应用程序中也是有益的,并且缺点很少(开销实际上很小)。使用容器可能总是比滚动自己更快(更不用说稳定)
理想情况下,如果您应用实体原则并且针对接口编程而不是具体类型,则只需修改组合根。这意味着你当然一直在使用没有容器的DI并且有一个DIY解决方案。如果没有,那么转移到DI可能会有点困难。
我建议不要立刻解决整个重构问题。一步一步地以小增量进行测试,然后进行测试。这是最有可能不破坏任何现有功能的,它可以让你在应用程序的整体设计中发现错误
答案 2 :(得分:1)
1. When planning and coding smaller applications that presumably will not expand much, should I implement a container in anticipation that scenarios such as these may present themselves and in such anticipation I would be better off implementing a container from the start so upon extension the framework already exists
。
为什么不为未来的成功定位?即使在一个小应用程序中,这些好处也很多,而且额外的工作很少。
2. Is it a sign of poor design if implementing a container when extending an application beyond its original intention becomes cumbersome?
有些人可能认为,由于没有使用容器,设计最初很差。您可能正在改进设计,因此如果正确完成,这不是一件坏事。最初的意图是什么?要紧密耦合,难以测试?我说,继续你的想法。
顺便说一句,如果您没有无偿使用接口,我建议现在是开始的好时机。答案 3 :(得分:1)
比较手动注射和自动注射:
1)
正如另一个答案中所提到的,在我看来,从一开始就使用容器进行验证是一个好主意。但是,我强烈建议您使用良好的编码标准文档进行跟进。为了说明这一点,请查看我在生产系统中看到的以下代码。
public class MyClass
{
IUnityContainer _container;
public MyClass(IMyDependentInterface dpenedentclass, IUnityContainer container)
{
_container = container;
//........
}
public void DoSomething()
{
var obj = _container.Resolve<ISomeOtherInterface>();
obj.DoAction();
}
}
在不知不觉中,这里建立了反模式(服务定位器?)。正如您所看到的,在这个世界中似乎没有失败证明设计。因此,请不要犹豫,在编码标准文档中添加看似明显的内容。
2)
如果难以进行自动注射,则表明存在不良情况。它可以是设计,但永远不要低估不良实现破坏设计的能力,如前面所述。