c++ - 从实现中抽象出库依赖是一种常见的做法吗?

标签 c++ architecture frameworks software-design

我对这个问题的回答是“否”。但我的同事不同意。

我们正在重建我们的产品,并在近期内做出许多关键决策。

在做我自己的一些工作时,我注意到我们有一些内部 C++ 类来抽象一些 POSIX API(线程、互斥量、信号量和 rw 锁)和其他实用程序类。请注意,这些类是基本类,尚未从 Linux 移植(可移植性是重建的一个因素。)我们还使用 POCO C++ 库。

我将此事提请我的同事注意,并建议我们放弃内部类(class),转而使用 POCO 类(class)。我想充分利用我们已经在使用的库。他们建议我们应该使用 POCO 实现我们的内部类,并在必要时进一步抽象额外的 POCO 类,以免依赖于任何特定的 C++ 库(引用 future 的未知数——如果我们想使用不同的库/框架怎么办? QT或者boost,万一我们选的不好或者开发不活跃怎么办等等)

他们也不想重构遗留代码,通过用我们自己的类抽象部分 POCO,我们可以实现额外的功能(经典 OOP)。我可以理解这两个论点。但是,我认为如果我们正在重新编码,我们应该做大,或者回家。现在是重构的时候了,它真的不应该那么糟糕,特别是考虑到我们的类与 POCO 中的类(线程等)之间的相似性。我不知道关于第二点该说些什么 - 我们应该只使用需要功能的扩展类?

我的同事也不想到处乱扔 POCO 命名空间。我认为我们应该选择一个库/框架/工具包,并坚持使用它。充分利用其功能。这不是典型的做法吗?我见过的唯一一个抽象整个框架的项目是 Freeswitch(它提供自己的 APR 接口(interface)。)

一个建议是,我们向彼此和潜在客户公开的 API 应该没有 POCO,但它会出现在实现中(这是有道理的。)

我们当中没有人真正有过此类设计决策的经验,这在当前的产品中有所体现。我从小就从事这项工作,有些直觉让我来到这里,但也没有实际经验。我真的很想避免对已经解决的问题提出糟糕的解决方案。

我想我的问题可以归结为:在构建产品时,我们是否应该 a) 选择一个主要框架作为我们大部分代码的基础,并且 b) 期望该框架与产品紧密耦合?这不是框架的重点吗? (框架还是库更适合POCO?)

最佳答案

首先,您公开的 API 绝对应该不含 POCO、boost、qt 或任何其他不属于标准 C++ 库的类型。这是因为基础库有自己的发布周期,与您的库的发布周期不同。如果您的库的用户也使用 boost,但使用的是不同的、不兼容的版本,他们将需要花时间来解决不兼容问题。这条规则的唯一异常(exception)是当你设计一个库作为更广泛的框架的一部分发布时——比如,一个 POCO 工具包的补充。在这种情况下,您的库的发布与整个工具包的发布相关联。

但是,在内部,您应该避免使用自己的包装器,除非您要抽象出的库是真正的“商品库”1。这样做的原因是,当你在你的类后面隐藏一个外部库时,大多数时候你会模仿你所隐藏的库的抽象级别。使用包装器的代码将编程到外部库规定的抽象级别。当您将包装器背后的实现换成不同的框架时,您很可能会 (1) 调整新框架以适应旧框架的抽象级别,或者 (2) 需要更改你使用你的包装。这两种情况都非常可疑:如果您执行 (1),也许您一开始就不应该切换,如果您执行 (2),那么您的包装器将被证明是无用的。


1 我所说的“商品库”是指提供抽象级别的库,这种抽象级别在其他具有类似用途的库中很常见。

关于c++ - 从实现中抽象出库依赖是一种常见的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12372792/

相关文章:

c++ - 前向声明 : incomplete type 'enums::Category' used in nested name specifier 有问题

c - Y86 求和程序困惑

java - 设计 Bukkit 插件框架 - 通过注释处理子命令

c++ - 使用 vector 还是数组?

c++ - Google Protocol Buffers C++ 实现在面对恶意数据时的稳定性和安全性

c++ - 在游戏子系统中注册游戏对象组件? (基于组件的游戏对象设计)

php - 如何将已编写的 CodeIgniter 代码移至 Kohana?

python - Django ;我如何从自定义 'skin' 目录中提供模板/图像/css/js?

c++ - 来自 C++ 代码的预处理器指令 (_VARIADIC_MAX)

ruby-on-rails - 将 strip 添加到 Rails 应用程序