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 cover functionality such as threads, thread synchronization, file system access, streams, shared libraries and class loading, sockets and network protocols (HTTP, FTP, SMTP, etc.), and include an HTTP server, as well as 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 explore a code snippet from the POCO source code:

This implementation is characterized by:
- The function has only a few parameters.
- Assertions are used to verify that the inputs are valid.
- The variable naming is easy to understand.
- The method is short.
- There are no unnecessary comments in the body: the code speaks for itself.
- The function body is well indented.
- The well-established STL is used where appropriate.
As we navigate through the POCO source code, we can see the consistency of the implementation: the same best-practice rules are applied to every function.
Let’s take a look inside POCO using CppDepend and discover some facts about its design and implementation.
DESIGN
ABSTRACT VS INSTABILITY
Robert C. Martin wrote an interesting article about a set of metrics that can be used to measure the quality of an object-oriented design in terms of the interdependence between the subsystems of that design.
Here’s what he says in the article about the interdependence between modules:
What is it that makes a design rigid, fragile and difficult to reuse. It is the interdependence of the subsystems within that design. A design is rigid if it cannot be easily changed. Such rigidity is due to the fact that a single change to heavily interdependent software begins a cascade of changes in dependent modules. When the extent of that cascade of change cannot be predicted by the designers or maintainers the impact of the change cannot be estimated. This makes the cost of the change impossible to estimate. Managers, faced with such unpredictability, become reluctant to authorize changes. Thus the design becomes rigid.
And to fight rigidity, he introduces metrics like afferent coupling, efferent coupling, abstractness, instability, the “distance from the main sequence” and the “Abstractness vs Instability” graph.
The “Abstractness vs Instability” graph can be useful to identify projects that are difficult to maintain and evolve. Here’s the “Abstractness vs Instability” graph of the POCO library:

The idea behind this graph is that the more popular a code element of a program is, the more abstract it should be. In other words, avoid depending too directly on implementations; depend on abstractions instead. By a popular code element, I mean a project (but the idea also works for packages and types) that is massively used by other projects in the program. It is not a good idea to have widely used concrete types in your codebase. This creates Zones of Pain in your program, where changing the implementations can potentially affect a large portion of the program. And implementations are known to evolve more often than abstractions.
The main sequence line (dotted) in the above diagram shows how abstractness and instability should be balanced. A stable component would be positioned on the left. If you check the main sequence you can see that such a component should be very abstract to be near the desirable line – on the other hand, if its level of abstraction is low, it is positioned in an area called the “zone of pain”.
Only the Foundation project is inside the zone of pain, which is normal because it’s widely used by other projects.
INHERITANCE
Multiple inheritance increases complexity, so it should be used carefully.
Let’s search for all 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. The LCOM takes its values in the range [0-1]. The 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 types are considered non-cohesive.
EFFERENT COUPLING
The efferent coupling of a particular type is the number of types it directly depends on. Types for which 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 query.

And the result is empty, so no class has too 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 the most used and complex types.

The result is empty, so no class is both widely 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 query:


Only a few methods have 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.
POCO Implementation
NUMBER OF LINES OF CODE
Methods with a large number of lines of code are difficult to understand and maintain; let’s search for methods with more than 60 lines.


Fewer than 1% of methods have more than 60 lines.
CYCLOMATIC COMPLEXITY
Cyclomatic complexity is a popular procedural software metric that measures the number of independent paths through a procedure.
Let’s execute the following CQLinq query to detect methods to refactor.


So only 1% of methods can be considered complex.
Which methods are complex and not commented enough?


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 types have many methods.
And we can do the same search for fields.


Less than 1% of 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 commented.
