c++依赖注入+得墨忒耳定律+ logger/assert
c++ Dependency Injection + Law of Demeter + logger/assert
我看过两个很棒的视频(这个和这个),关于依赖注入、德米特定律和全局状态(singleton被认为是全局的)。
我想我得到了基本的想法,但我已经有一些单例类在我的库。然而,如果我想要一个可测试的和"设计良好"或"耦合较少"的代码,我应该使用DI和LoD。这当然意味着单例模式(作为一种设计模式)是邪恶的,因为调用者不知道实现,任何对全局事物的依赖都是不好的,至少从测试的角度来看是这样。
更具体地说,我正在构建一个简单的游戏引擎,而不使用任何更大的第三方库。这意味着我还必须处理特定于平台和低级别的代码。让我们更具体一点。我有一个数学部分在我的库中,我有一个类Vector2。当为其中一个函数输入无效数据时,它应该能够"抛出断言"。或者应该能够将其记录为错误。或两者兼而有之。在此之前,我只是简单地使用Singleton<Logger>
,所以我可以在任何地方访问它。
但是我同意,这些东西不应该被使用,而DI解决了这些问题。如。如果记录器还没有初始化怎么办?如果我想为测试使用一个虚拟记录器呢?等等......对于这些情况(如Logger和Assert类),您有什么建议?
LoD还说我不应该为对象(如getObjectA()->getObjectB()->doSomething()
)使用访问器。相反,将它们作为参数传递给函数/构造函数。它使一切都更容易测试(和调试),这是好的,但是跳过这些函数可能会很痛苦。
this.GetComponent<Transform>().SetPosition(...);
这是违背上帝的,不是吗?
这意味着我还必须处理特定于平台和低级别的代码。
使用依赖倒置(不仅仅是注入)。
对于这些情况(如Logger和Assert类),您建议使用什么?
DI要求你修改你的api,以允许你在使用它们的地方注入东西。为了避免不得不添加大量额外参数的情况(一个用于记录器,一个用于断言实现,或全局配置设置等),将它们组合在一起:
- 创建一个运行时配置类
- 向其添加服务(记录器服务、验证服务、配置服务等)
- 传递运行时配置;
LoD还说我不应该使用对象的访问器(如getObjectA()->getObjectB()->doSomething())。相反,将它们作为参数传递给函数/构造函数。
这种类型的调用链有几个问题:
-
它鼓励重复(如果你的代码中多次出现
getObjectA()->getObjectB()->
,那已经是一个维护问题) -
是不完整设计的糟糕替代品。LoD说,如果您需要从
ObjectA
的实例开始doSomething()
,那么ObjectA应该有一个方法doSomething:void ObjectA::doSomething(ObjectA& a) { getObjectB()->doSomething(); }
(或相似的)。
这为扩展"如何从ObjectA的实例开始完成doSomething"增加了一个自然的点,这有利于维护。
-
它强加于所有需要
doSomething
的客户端代码,事实是它需要知道ObjectB的接口。这听起来很小,但问题是普遍存在的,并且当作为设计策略应用时,它会严重恶化(如果您的ObjectA不仅有ObjectB,而且还有ObjectC和ObjectD,这可能足以迫使您花费大量时间来维护依赖关系)。
this.GetComponent<Transform>().SetPosition(...);
这是违背上帝的,不是吗?
是的。代码可以分割如下:
void SetPosition(Transform& t) { t.SetPosition(); }
客户机代码:SetPosition(this.GetComponent<Transform>());
这样,要在客户端代码中设置位置,您不再关心Transform的接口。在void SetPosition(Transform& t)
的实现中,您也不关心有一个称为GetComponent
的API。
上面示例的另一种LoD实现:
void YourObject::SetTransformPositions()
{
GetComponent<Transformation>.SetPosition();
}
…其中this
的类型为YourObject*
- 定律余弦求解c,但得到奇怪的答案
- boost Logger出现问题
- 我仍然收到此错误未定义的引用:boost::log::v2_mt_posix::trivial::logger::get
- 霍纳斯定律需要代数帮助,显示错误的答案 c++
- C - 无法使用MSYS2和CMAKE链接到BOOST :: LOGGER
- 如何使用poco :: logger记录Unicode字符串
- log4clus:在Logger:上崩溃:在Windows上关闭
- 简单的Logger类VSNPrintf正在随着读取访问违规行为而崩溃
- 如何将其发送到Google Logger和Cout
- 我们可以为每个类对象创建每个Boost Logger实例吗?
- Boost Logger静态链接:不起作用
- 利用物理定律模拟轨道
- C++ 开普勒定律和牛顿定律
- 为什么stdlib中的rand不遵循大数定律
- Logger::getInstance导致log4cplus中出现bad_alloc异常
- 阿尔法-贝塔"breaking"阿姆达尔定律?
- 在德墨忒耳定律和过多的接口重复之间取得平衡的任何指导
- 试图理解得墨忒耳定律,因为它适用于我的代码
- "null logger" - 带有 ostream 运算符的空类会从优化的代码中编译出来吗?
- c++依赖注入+得墨忒耳定律+ logger/assert