Blog 4 min read

Discover your C++ project internals: POCO case study

Share this article
Discover your C++ project internals: POCO case study

The POCO C++ Libraries are a collection of open source class libraries for developing network-centric, portable applications in C++.

POCO stands for POrtable COmponents. The libraries provide functionality for threads, thread synchronization, file system access, streams, shared libraries and class loading, sockets and network protocols (HTTP, FTP, SMTP, etc.). They also include an HTTP server, an XML parser with SAX2 and DOM interfaces, and SQL database access.

The modular and efficient design and implementation make the POCO C++ Libraries well suited for embedded development.

Let’s take a look inside POCO using CppDepend and discover some facts about its implementation and design.

POCO Implementation

Number of lines of code

Methods with many lines of code are difficult to understand and maintain. Let's search for methods with more than 60 lines.

Less than 1% of methods have more than 60 lines.

Cyclomatic Complexity

Cyclomatic complexity is a popular procedural software metric equal to the number of decisions that can be taken in a procedure.

Let's execute the following CQLinq request to detect methods to refactor:

So, only 1% of the methods can be considered complex.

Which methods are complex and insufficiently documented?

Methods with many variables

Methods where NbVariables is greater than 8 are difficult to understand and maintain. Methods where NbVariables is greater than 15 are extremely complex and should be split into smaller methods (unless they are automatically generated by a tool).

Only 8 methods have too many variables.

Types with many methods and fields

Only 3% of the types have many methods.

And we can do the same search for fields.

Less than 1% of the types have many fields.

We can conclude that POCO is well implemented: few methods are considered complex, its types are simple and have relatively few methods and fields, and the code is well documented.

DESIGN

Abstract vs instability

The “Abstractness vs Instability” graph can be useful to detect projects that will be difficult to maintain or evolve. The following post describes the utility of this graph and how to exploit it to improve the design.

For POCO, here is the “Abstractness vs Instability” graph:

Only Foundation is inside the Zone of Pain, which is understandable because it is heavily used by other projects.

Inheritance

Multiple inheritance increases complexity and should therefore be used carefully.

Let's search for classes with many base classes.

The blue rectangles represent the result.

Only a few classes derive from more than one class.

Type cohesion

The single responsibility principle states that a class should not have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class. There are several LCOM metrics. LCOM takes its values in the range [0-1]. LCOMHS (HS stands for Henderson-Sellers) takes its values in the range [0-2]. Note that the LCOMHS metric is often considered more efficient at detecting non-cohesive types. An LCOMHS value higher than 1 should be considered alarming.

Only 1% of the types are considered non-cohesive.

Efferent coupling

The efferent coupling of a particular type is the number of types it directly depends on. Types where TypeCe > 50 depend on too many other types. They are complex and have more than one responsibility. They are good candidates for refactoring.

Let’s execute the following CQLinq request.

And the result is empty, so no class has many responsibilities.

Types most used

It is useful to know which types are used most frequently; for this, we can use the TypeRank metric.

TypeRank values are computed by applying the Google PageRank algorithm to the graph of type dependencies. A homothety of center 0.15 is applied so that the average TypeRank is 1.

Types with high TypeRank should be more carefully tested because bugs in such types will likely be more catastrophic.

Let's search for types that are both heavily used and complex.

The result is empty, so no class is both heavily used and complex.

Layering and level metric

This post explains the level metric and how to exploit it to improve design.

Let's search for dependency cycles; for that we can execute the following CQLinq request:

Only a few methods are involved in dependency cycles. Let's take the Zip project as an example and look at its dependency graph.

Only 1 dependency cycle exists in this project.

In conclusion, POCO is also well designed: it is highly cohesive and loosely coupled.

Share this article