3

我的 C++ 应用程序的很大一部分使用类来描述数据模型,例如 ClassType(它实际上模拟普通 C++ 中的反射)。

我想在我的应用程序中添加一个新模块,它需要使用这些 ClassType,但我不想在 ClassType 上引入新模块的依赖关系。

到目前为止,我有以下选择:

  • 不使其独立并引入对 ClassType 的依赖,有在我的应用程序中创建更多“意大利面条”依赖的风险(这是我最不喜欢的解决方案)
  • 引入一个新类,例如 IType,并让我的模块只依赖于 IType。然后 ClassType 应该从 IType 继承。
  • 使用字符串作为识别方法,并在需要时强制新模块的用户将 ClassType 转换为字符串,反之亦然。
  • 使用 GUID(甚至简单的整数)作为标识,还需要 GUID 和 ClassType 之间的转换

在应用程序中解耦模块时,您应该尝试多远?

  • 只是引入一个接口,让所有其他模块依赖该接口?(就像上面描述的 IType 一样)
  • 甚至通过使用其他标识(如字符串或 GUID)进一步解耦?

恐怕解耦得太远,代码会变得更不稳定,更难调试。我在 Qt 中看到过一个这样的例子:信号和槽是使用字符串链接的,如果你输入错误,该功能将不起作用,但它仍然可以编译。

你应该让你的模块解耦到什么程度?

4

3 回答 3

2

99% 的情况下,如果您的设计基于反射,那么您的设计就会出现重大问题。

一般来说,像

if (x is myclass)
elseif (x is anotherclass)
else

是一个糟糕的设计,因为它忽略了多态性。如果您这样做,则该项目x违反了 Liskov 替换原则。

另外,鉴于 C++ 已经有了 RTTI,我不明白你为什么要重新发明轮子。这就是目的typeofdynamic_cast目的。

于 2010-09-23T17:12:55.137 回答
1

我将避免考虑您的反射,而只看依赖关系的想法。

解耦什么是合理的解耦。耦合意味着如果一件事发生变化,另一件事也必须发生变化。所以你的 NewCode 正在使用 ClassType,如果它的某些方面发生了变化,那么你肯定必须改变 NewCode——它不能完全解耦。您想从以下哪一项中解耦?

  1. 语义,ClassType 的作用。
  2. 接口,你怎么称呼它。
  3. 实施,如​​何实施。

在我看来,前两个是合理的耦合。但可以肯定的是,实现更改不应该要求 NewCode 更改。所以代码到接口。我们试图保持接口固定,我们倾向于扩展它们而不是改变它们,尽可能保持它们向后兼容。有时我们使用名称/值对来尝试使界面可扩展,然后遇到您提到的拼写错误。这是灵活性和“类型安全”之间的权衡。

于 2010-09-23T17:50:53.873 回答
0

这是一个哲学问题;这取决于模块的类型和权衡。我认为我个人在不同时间都完成了所有这些操作,除了 GUID 到类型映射,在我看来,它与字符串到类型映射相比没有任何优势,并且至少字符串是可读的。

我会说你需要看看特定模块需要什么级别的解耦,考虑到预期的外部使用和代码组织,然后从那里开始。据我所知,您已经掌握了所有概念方法,并且它们在特定情况下都很有用。

无论如何,这是我的看法。

于 2010-09-23T18:20:59.987 回答