Organising code for a large-scale, modular project

So, there are lots of opinions and techniques regarding large project organization.

My personal preference is the method used by nearly all Arduino libraries as well as by professional programmers working on large software projects in industry.

I break the program's functionality into logical modules that ideally can be developed and tested stand-alone / individually -- even by different people.

Each module has a .h file and a .cpp file. The .h file contains the module's interface -- i.e. only the information that other modules need to use this module's public functionality. After the #include guards, this typically means:

  • Prototypes for public functions.
  • Class declarations.
  • 'extern' declarations of global variables.

The .h file may also contain class method implementations within the class declaration - but only if said implementations are short (couple of lines). It should also contain #include directives of any .h files needed by the contained declarations or by modules that use the interface. If there are any .h files only required by the implementations, then they should NOT be #included in the .h file but in the .cpp file.

The .cpp file should contain:

  • #include of the associated .h file.
  • #includes of any .h files required by the implementations but not the interface.
  • Function implementations.
  • Class method implementations.
  • Class static variable definitions.
  • Definitions of global variables declared as 'extern' in the associated .h file.

Not only does this method provide superior modularity, but it allows you to take advantage of file-level scope control using the 'static' directive. This lets you keep functions and global variables private to the implementation file if other modules have no need for them.

Using this method there should only be ONE .ino file -- the main one that contains setup() and loop().

7 Likes