Structure101 Studio provides model settings that influence, dramatically, how the structural model is composed. The options here are best explained in the context of an example.
// file a.h
class A{
doSomething();
}
// file a.c
#include a.h
A::doSomething {
// do something
}
// file b.h
class A; // forward declaration of A
class B {
public:
void doSomethingElse(A* a);
}
// file other.c
#include b.h
#include a.h
// Make sequence:
// 1. awkward.c
// 2. a.c
The interesting code items are the entities (class) A and (method) A::doSomething(), for each of which we have 2 occurrences in the code-base:
- Class A is defined in a.h and (forward-) declared in b.h
- A::doSomething() is defined in a.c and declared in a.h
Clearly, the method B::doSomethingElse(A* a) depends on A. But which A does it depend on?
If the compiler option is selected, then - as the name implies - the dependency handling reflects the compiler's view of the world. In this case, when other.c is compiled, the first A found (and therefore chosen by the compiler) will be the forward declaration of A in b.h. Note that, if the includes order in other.c is reversed, then the dependency would instead go to the definition of A in a.h.
It follows that - if your code-base makes some or extensive use of forward declarations -the compiler model may sometimes be counter-intuitive (with dependencies fluctuating if the includes or even make sequence is changed).
The compiler/linker option merges the declarations to the definition but does not remove the declaration nodes from the model. This is useful when trying to split or extract ‘modules’ of code wherein the focus is on identifying file content to be moved to another file or folder.
Note: In the event of symbol clashes (multiple definitions of the same entity), the linker and compiler/linker models defaults back to the compiler model.
- However, the best logical view of the code (leaving aside aspects like forward declarations as compiler optimizations) is likely the linker model in combination with header-body merging to get a Lakos-module view. Note that is not the same as a "pure logical" view (contains only entities and no files) which, even where namespaces are used, is invariably too "flat" to be of any benefit in the context of structural analysis.
- Conversely, the best physical view of the code (most suitable for e.g. redundant includes analysis) is likely the compiler option with no file merging.
Tip:
- To home in on differences between the various model options, create a local repository and publish snapshots with the various settings of interest and then switch on the structural differences.