must have
This helps to reduce amount of header dependencies, and compile definitions exactly once. Also this helps to follow ODR (One Definition Rule).
RULE: it is always an error to place definitions with external linkage to .hpp files. (hyperledger-iroha/iroha#787, rule 1)
must have
forward declarations reduce amount of dependencies for clients.
RULE: include what you use -- if in cpp file you use model::Block, you MUST include header, which defines Block.
In the project should be minimum transitive dependencies, rule above helps to achieve this.
3. use technique with extern template declaration and explicit template instantiation to decrease compilation time.
must have
Article https://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html says that gcc uses Borland model, which has a downside:
Borland C++ solved the template instantiation problem by adding the code equivalent of common blocks to their linker; the compiler emits template instances in each translation unit that uses them, and the linker collapses them together. The advantage of this model is that the linker only has to consider the object files themselves; there is no external complexity to worry about. The disadvantage is that compilation time is increased because the template code is being compiled repeatedly. Code written for this model tends to include definitions of all templates in the header file, since they must be seen to be instantiated.
If we create hpp/cpp, explicitly instantiate template in cpp and use "extern template" in hpp, then all hpp clients will not instantiate this template and compilation time will be significantly lower. Template code will be linked.
Note: more detailed process is described in the article above, "item 1".
RULE: explicitly instantiate templates in cpp + use "extern template" for big or often-used templates, which have been declared in external libraries (such as boost::optional or rxcpp).
Note: code will not be changed, only some includes will be changed in the project. It is not "so hard" to do.
4. we need to reduce number of static targets. I propose to create OBJECT targets (https://cmake.org/Wiki/CMake/Tutorials/Object_Library) for small targets.
could have
Example: We have stateless_validator (big target), which consists of
- stateless_validator_block_validator
- stateless_validator_proposal_validator
- stateless_validator_query_validator
We make stateless_validator_*_validator as OBJECT targets and link them exactly once in one big target stateless_validator.
RULE: small targets, which are intended to be linked exactly once and do not link anything to themself should be marked as OBJECT targets.
could have
It removes additional dependency. Less dependencies = better.