Modularizing code: Same #include into various files, does it negatively affect performance?

 

Hey all!

I'm doing a refactoring of my code base to improve my developer experience. I just had a thought and struggled to find any relevant information to get some clarity.

Suppose the following:

  • A base file exists, containing various defines and declaration of custom enums
  • 3 separate files are created, they have a #include "base-file.mqh" and they create class-specific defines
  • 3 classes are created, each as a separate module (and therefore on a separate file) that includes their own #include "defines-specific-to-class.mqh"

So far so good, I'm aware that during preprocessing, each of the files with the classes will get only one instance of the code from the base defines and the specific defines. Here's where I'm getting tangled:

Given the above suppositions, suppose the following:

  • A new class is created on it's own file, called CImplementationClass
  • The new class has #include "specific-class-1.mqh", #include "specific-class-2.mqh", and #include "specific-class-3.mqh" (referring to the classes created on the previous bulleted list)

The idea is that CImplementationClass would be a class that serves as a "hub" to connect the specific-to-a-task classes as they are required by the program. 

However, my question is, on the example of CImplementationClass, the fact that the header files used call separately to a common files in various instances would imply that the final compilation of the program will have repeated defines or larger than needed file size, or the preprocessor takes care of analyzing the code to where if I have X #include calls to files that each use the same header file, then it will just insert that common header file once?

I notice this is a programming pattern in many large libraries, including the standard library, for example, if I build a dialog window (let's call it CExampleDialog) using CAppDialog, and include the ComboBox.mqh and DateDropList.mqh controls, since both files contain a #include "WndContainer.mqh" I'd end up on a similar situation. Since I see the pattern being used in many instances, I decided to use it as well, but before doubling down on a structure I'd like to make sure I'm using the proper practices.

Thanks in advance!!

Documentation on MQL5: Standard Library / Panels and Dialogs / CAppDialog
Documentation on MQL5: Standard Library / Panels and Dialogs / CAppDialog
  • www.mql5.com
CAppDialog - Panels and Dialogs - Standard Library - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
As far as I am aware, this is exactly how it works.

Usually, in other languages, you'll find some #ifdef at the beginning of each include file, making it only included once.

In MQL, as far as the doc goes, this is not needed, still i personally use this strategy.

The preprocessor and compiler will arrange for any duplicates.

Although MQLs compiler is not as versatile as ie a C compiler, it serves enough features to have flexible include libraries. I can compile my personal library as binary, use it as header include for a project or use the same header to include the binary library as a shared resource into a project.

Only namespaces need to be considered carefully for such an endeavor, since binary included import declarations get an implicit namespace definition. But this can be managed with some macros on a preprocessor level.




 
Dominik Christian Egert #:
As far as I am aware, this is exactly how it works.

Usually, in other languages, you'll find some #ifdef at the beginning of each include file, making it only included once.

In MQL, as far as the doc goes, this is not needed, still i personally use this strategy.

The preprocessor and compiler will arrange for any duplicates.

Although MQLs compiler is not as versatile as ie a C compiler, it serves enough features to have flexible include libraries. I can compile my personal library as binary, use it as header include for a project or use the same header to include the binary library as a shared resource into a project.

Only namespaces need to be considered carefully for such an endeavor, since binary included import declarations get an implicit namespace definition. But this can be managed with some macros on a preprocessor level.




Thanks in advance!

So, what you're saying is that as a good practice, you create the include calls like this:

#ifndef base-header-file

    #include "base-header-file.mqh"
    #define base-header-file

#endif

Also, when you say that you could also use the library's binary as a shared resource in another project, I'm guessing you're referring to compiling the file into a .ex4/5 file, most likely from a .mq4/5 file instead of a .mqh file, I'm also guessing you mean too that you use your library that has includes that might be duplicated by other resources in addition to your library? Just want to make sure I'm understanding you correctly. :)

The only part where I got lost is on the namespace part, you mean that the libraries when imported in their compiled format are assigned a namespace that should be referenced when calling it's functions?

Thanks again for your time!

 
To the include files:

Inside the file .mqh which you include, you wrap the whole content into an ifndef define endif.

This way it can only be included once.

Shared library: Yes.
You create an mq4/5 file which includes all your header files. When doing so, there will be no descendants of include in sub files. You need to include all relevant headers inside the mq4/5 file.


Namespace:

Yes, it declares the library's binary name as the namespace in which the functions are imported into. Although the compile seems to use a "using namespace" declaration implicitly.


Reason: