我已经看了两个很棒的视频(thisthis),它们有关依赖项注入(inject),得墨meter耳定律和全局状态(单子(monad)被视为全局)。

我想我已经有了基本的想法,但是我的图书馆中已经有一些单例类。但是,如果我想要一个可测试且“设计良好”或“耦合较少”的代码,则应使用DI和LoD。当然,这意味着Singletons(作为一种设计模式)是邪恶的,因为调用者现在没有实现,并且对全局事物的任何依赖都是不好的,至少从测试的 Angular 来看。

更具体地说,我正在构建一个简单的游戏引擎,而无需使用任何更大的第三方库。这意味着我还必须使用特定于平台的底层代码。

让我们更具体一点。我的图书馆中有一个Math部分,其中有Vector2类。当为其功能之一输入了无效数据时,它应该能够“抛出断言”。或者应该能够将其记录为错误。或两者。在此之前,我只使用了Singleton<Logger>,因此我可以在任何地方访问它。

但是我同意,这些东西不应该使用,DI解决了这些问题。例如。如果记录器尚未初始化怎么办?如果我想要虚拟记录器进行测试怎么办?依此类推...对于这些情况,您有什么建议(例如Logger和Assert类)?

此外,LoD表示我不应该将访问器用于对象(例如getObjectA()->getObjectB()->doSomething())。而是将它们作为参数传递给函数/构造函数。可以使所有内容的测试(和调试)更加容易,但是跳过这些功能可能会很痛苦。

考虑来自Unity引擎的示例。 GameObject具有从该对象获取组件的方法。例如。如果要手动转换对象,则别无选择,请调用“对象 getter ”,如下所示:

this.GetComponent<Transform>().SetPosition(...);

这违背了LoD,不是吗?

最佳答案



使用dependency inversion(不仅用于注入(inject))。



DI要求您更改您的API,以允许您在使用它们的地方注入(inject)事物。为避免必须添加许多额外参数(一个用于记录器,一个用于断言实现或全局配置设置等)的情况,请将它们组合在一起:

  • 创建运行​​时配置类
  • 向其添加服务(记录器服务,验证服务,配置服务等)
  • 传递运行时配置;



  • 这种类型的 call 链接存在一些问题:
  • 鼓励重复(如果您的代码中多次包含getObjectA()->getObjectB()->,那已经是维护问题)
  • 不能很好地替代不完整的设计。 LoD表示,如果需要从doSomething()实例开始的ObjectA,则ObjectA应该具有doSomething方法:
    void ObjectA::doSomething(ObjectA& a)
    {
        getObjectB()->doSomething();
    }
    

    (或类似)。

    这为扩展有益于维护的“如何从ObjectA实例开始完成doSomething”添加了自然点。
  • 它将所有需要doSomething的客户端代码强加到void SetPosition(Transform& t),这是它需要了解ObjectB接口(interface)的事实。这听上去很小,但问题无处不在,并且作为设计策略应用时,它的组合效果很差(如果您的ObjectA不仅具有ObjectB,还具有ObjectC和ObjectD,这可能足以迫使您花很多钱时间只是保持依赖关系)。



  • 是。可以按以下方式拆分代码:
    void SetPosition(Transform& t) { t.SetPosition(); }
    

    客户代码:
    SetPosition(this.GetComponent<Transform>());
    

    这样,就可以在客户端代码中设置位置,您不再关心Transform的界面。您也不必关心GetComponent的实现,因为有一个名为this的API。

    以上示例的替代LoD实现:
    void YourObject::SetTransformPositions()
    {
        GetComponent<Transformation>.SetPosition();
    }
    

    ...此处YourObject*的类型为ojit_code。

    关于c++ - c++依赖注入(inject)+ Demeter定律+ logger/assert,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39914190/

    10-09 03:32