0

I want to encapsulate global variables in a single "data-manager-module". Access is only possible with functions to avoid all the ugly global variable problems ... So the content is completely hidden from the users. Are there any existing concepts? How could such an implementation look like? How should the values stored in the "data-manager-module"?

Lundin
  • 195,001
  • 40
  • 254
  • 396
Mike
  • 1
  • 1
    Looks like you're inventing C++. Seriously, you can use `static` in source files for such variables: they will then not be visible to other compilation units. – Bathsheba Jul 07 '15 at 08:15
  • @Bathsheba OO is a way of doing program design and good program design is not language-dependent. Some languages merely offer convenient features that ease OO design. – Lundin Jul 07 '15 at 08:40
  • Especially for embedded C in *small* embedded systems, this is a bad idea. Access to global state only thru functions would often be slower than accessing global variables. However, you could have *few* global variables, by defining some `struct` to pack the global state, and have a single global of that type. – Basile Starynkevitch Jul 07 '15 at 08:54
  • @BasileStarynkevitch Performance shouldn't even be an argument, or the compiler is doing a poor job at inlining. Sadly, many embedded compilers are of questionable quality, so you might indeed end up adapting the program design to the compiler's crappiness. – Lundin Jul 07 '15 at 09:03
  • You'll get inlining only with link time optimization in that case (or by having some global and providing `static inline` functions to access it) – Basile Starynkevitch Jul 07 '15 at 09:05
  • You should read http://www.embedded.com/electronics-blogs/break-points/4025723/A-pox-on-globals - it exactly answerers your question. Although gathering unrelated globals into *one* module is probably a bad idea from a coupling/cohesion point-of-view. Data should be localised to where used to achieve minumum coupling, and maximum cohesion. – Clifford Jul 07 '15 at 13:41
  • Great article! Thanks for the hint. The discussion about "data manager module" came up as a new colleague joined the team. So I will keep my current design. Data is stored at the corresponding modules. Access only by set/get function. And nothing more ... :-) Thanks again! – Mike Jul 08 '15 at 09:40
  • http://stackoverflow.com/questions/23655421/does-c-provide-a-way-to-declare-an-extern-variable-as-read-only-but-define-it/23656041#23656041 – AlphaGoku Apr 20 '16 at 12:12

3 Answers3

6

A "data manager module" doesn't make any sense. Implementing one would merely be sweeping away a fundamentally poor program design underneath the carpet, hiding it instead of actually cleaning it up. The main problem with globals is not user-abuse, but that they create tight couplings between modules in your project, making it hard to read and maintain, and also increases the chance of bugs "escalating" outside the module where the bug was located.

Every datum in your program belongs to a certain module, where a "module" consists of a h file and a corresponding c file. Call it module or class or ADT or whatever you like. Common sense and OO design both dictate that the variables need to be declared in the module where they actually belong, period.

You can either do so by declaring the variable at file scope static and then implement setter/getter functions. This is "poor man's private encapsulation" and not thread-safe, but for embedded systems it will work just fine in most cases. This is the embedded industry de facto standard of declaring such variables.

Or alternatively and more advanced, you can do true private encapsulation by declaring a struct as incomplete type in a h file, and define it in the C file. This is sometimes called "opaque type" and gives true encapsulation on object basis, meaning that you can declare multiple instances of the class. Opaque type can also be used to implement inheritance (though in rather burdensome ways).

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

Declare and define all the variables in a header file that is included into the manager's .c file but not into its .h That way they will be only visible for the manager's functions.

SF.
  • 13,549
  • 14
  • 71
  • 107
0

You can keep all variables in a single source inside a struct with getters and setters

static struct all_globals{
  long long myll;
  /* ... */
} all_globals; /* Not _really_ global*/

long long getmyll(void){
  return all_globals.myll;
}

long long setmyll(long long value){
  return all_globals.myll = value;
}

similarly, you could use an internal header file that is not exported to the user API, then strip symbols from the resulting binary/library

/* globals.c */
struct all_globals{
  long long myll;
  /* ... */
} all_globals; /* Not _really_ global*/

/* globals.h */
#define getmyll() all_globals.myll
#define setmyll(value) all_globals.myll = (value)

This will still be technically visible to the end user with enough effort, but allows you to distinguish globals and keep them together.

technosaurus
  • 7,676
  • 1
  • 30
  • 52