POCO C++库是一组用于开发以网络为中心、可移植的 C++ 应用程序的开源类库集合。
POCO 代表可移植组件(POrtable COmponents)。这些库提供了线程、线程同步、文件系统访问、流、共享库和类加载、套接字和网络协议(HTTP、FTP、SMTP 等)等功能。它们还包括一个 HTTP 服务器、一个带有 SAX2 和 DOM 接口的 XML 解析器,以及 SQL 数据库访问功能。
模块化且高效的设计和实现,使 POCO C++ 库非常适合嵌入式开发。
让我们使用CppDepend深入 POCO 内部,了解其实现和设计中的一些事实。
POCO 的实现
代码行数
代码行数很多的方法难以理解和维护。让我们搜索超过 60 行的方法。


不到 1% 的方法超过 60 行。
圈复杂度
圈复杂度是一个流行的过程式软件度量,等于一个过程中可能发生的决策数量。
让我们执行下面的 CQLinq 查询,检测需要重构的方法:


所以,只有 1% 的方法可以被认为是复杂的。
哪些方法既复杂又文档不足?


变量过多的方法
局部变量数 NbVariables 大于 8 的方法难以理解和维护。NbVariables 大于 15 的方法则极其复杂,应该拆分为更小的方法(除非它们是由工具自动生成的)。


只有 8 个方法变量过多。
方法和字段过多的类型


只有 3% 的类型拥有大量方法。
我们可以对字段做同样的搜索。


不到 1% 的类型拥有大量字段。
我们可以得出结论:POCO 实现得很好——很少有方法被认为是复杂的,它的类型简单且方法和字段相对较少,代码也有良好的文档。
设计
抽象性与不稳定性
"抽象性与不稳定性"(Abstractness vs Instability) 图对于检测难以维护或演进的项目很有用。下面这篇文章介绍了这张图的用途,以及如何利用它来改进设计。
对于 POCO,下面是"抽象性与不稳定性"图:

只有 Foundation 位于痛苦区(Zone of Pain)内,这是可以理解的,因为它被其他项目大量使用。
继承
多重继承会增加复杂性,因此应谨慎使用。
让我们搜索拥有多个基类的类。

蓝色矩形代表查询结果。

只有少数类继承自多个类。
类型内聚性
单一职责原则指出,一个类不应该有超过一个变更的理由。这样的类被称为内聚的。高 LCOM 值通常表明类的内聚性较差。LCOM 度量有好几种。LCOM 的取值范围是 [0-1]。LCOMHS(HS 代表 Henderson-Sellers) 的取值范围是 [0-2]。请注意,LCOMHS 度量通常被认为在检测非内聚类型方面更有效。LCOMHS 值高于 1 应被视为警示信号。


只有 1% 的类型被认为是非内聚的。
扇出耦合
某个特定类型的扇出耦合(efferent coupling)是它直接依赖的类型数量。TypeCe > 50 的类型依赖了太多其他类型。它们很复杂,承担了不止一个职责。它们是重构的良好候选。
让我们执行下面的 CQLinq 查询。

结果为空,所以没有任何类承担过多职责。
最常用的类型
了解哪些类型被最频繁地使用是很有用的;为此,我们可以使用 TypeRank 度量。
TypeRank 值是通过将谷歌 PageRank 算法应用于类型依赖图计算得出的。应用了以 0.15 为中心的相似变换,使平均 TypeRank 为 1。
TypeRank 高的类型应该经过更仔细的测试,因为这类类型中的 Bug 可能会造成更严重的后果。

让我们搜索既被大量使用又很复杂的类型。

结果为空,所以没有任何类既被大量使用又很复杂。
分层与层级度量
这篇文章解释了层级(level)度量,以及如何利用它来改进设计。
让我们搜索循环依赖;为此,我们可以执行下面的 CQLinq 查询:


只有少数方法涉及循环依赖。让我们以 Zip 项目为例,看看它的依赖图。

这个项目中只存在 1 个循环依赖。
总而言之,POCO 的设计也很出色:它具有高内聚、低耦合的特点。
