Encapsulation and State Variables¶
Whilst the C
-Programming language is not an Object-Oriented language, we
will borrow key concepts from object-orientation to ensure well controlled
state variables.
Our state variables will be global in scope (preface with the keyword static
).
This ensures that across all scopes (i.e. all files) every function can access
the state variables
However, to ensure we keep tight control over the state variables we will encapsulate this and only expose interfaces to use them (see wikipedia).
Key to this is our SystemState
global
Note
The team should consider exposing the SystemState
variable to the files that
need them, and instead require that other functions that should only have read-only rights
to use exposing functions
In the core header:
/*******************************************************************************
* STATE CONTROL
******************************************************************************/
typedef struct {
int _config_set_flag = 0;
int *_config;
int _sys_sleepguard = 0;
int _sys_ready_flag = 0;
} sys_state;
static sys_state SystemState;
All variables that are prefaced with are underscore character are considered private. Because C is not OOP, we can’t strictly enforce this at compile time. We require that developers be aware that every time they are using a variable/function with a underscore character in-front, and that they must check they have the rights to the variable.
A preliminary example of exposing/encapsulating these state variables may be in the sleep management module
/*******************************************************************************
* sleep.c
******************************************************************************/
#include "main.h"
int sys_sleep(int time_milliseconds)
{
//Put micro-controller to sleep
// ...
// ...
//System is not ready for operation
SystemState._sys_ready_flag = 0;
return 1
}
int sys_reboot(void)
{
//Wake the micro-controller
// ...
// ...
return 1
}
void is_sys_ready(void)
{
return SystemState._sys_ready_flag;
}
Notice that the is_sys_ready()
function seems rather pointless.
However this is the function that ‘exposes’ the private _sys_ready_flag
to
outside users. This ensures they never need to use the variable _sys_ready_flag
and can determine the value of this through the public function is_sys_ready()
.
So a caller routine may look like this
/*******************************************************************************
* Someone using our API
* test.c
******************************************************************************/
#include "main.h"
#include "sleep.h"
int main(void)
{
sys_sleep(1000);
//... Wait for interrupt
//...
sys_reboot();
while (is_sys_ready() != 1){} //Hold until system is ready
}