Modularity is of course a very important computer design philosophy. It allows for code reuse and organization, as well as being typically more efficient and
less buggy. But sometimes the implementation of modularity on the TI platform can be awkward, as it is an environment where every byte counts.
My programs use an uncommon way of error handling. At any point of the program, if it encounters a fatal error it will set my error message global variable to something useful and then call exit(0). The function defined for exit by atexit() can properly clean up the program from any point. It then restores the home screen, displays the error message in the status line, and exits. Here's a simple example, without the screen handling:
--MAIN.H--
extern const unsigned char *errMessage;
--FILES.H--
void GetFile(void);
extern FILE *f;
--MAIN.C--
#include "files.h"
const unsigned char *errMessage = "thanks for playing!";
void exitfunc(){
if (f)
fclose(f);
ST_helpMsg(errMessage);
}
void _main(void){
atexit((void*)exitfunc);
GetFile();
}
--FILES.C--
FILE *f = NULL;
#include "main.h"
public void GetFile(void){
if ((f = fopen("test", "r")) == NULL){
errMessage = "cannot open file!";
exit(0);
}
}
This doesn't work well for modularity at all. Files.c and main.c are dependent on each other, and files.c would need to be worked on before use on another project. It isn't very elegant either. So let's look at the alternative, where files.c is independent, and will simply pass on any errors:
--FILES.H--
int GetFile(void);
extern FILE *f;
--MAIN.C--
#include "files.h"
const unsigned char *errMessage = "thanks for playing!";
void exitfunc(){
if (f)
fclose(f);
ST_helpMsg(errMessage);
}
void _main(void){
atexit((void*)exitfunc);
if (!GetFile())
errMessage = "cannot open file!";
exit(0);
}
--FILES.C--
FILE *f = NULL;
public int GetFile(void){
if ((f = fopen("test", "r")) == NULL)
return -1;
}
Now files.c is completely modular and can be used in other programs without modification, as long as the programs can deal with the errors it passes back. While this is good for modularity, it doesn't seem the best solution. Now the same error has to be checked and dealt with on two different levels of the program, wasting space. This waste can become a big problem in regular programs with many more possible errors in deeply nested functions having to pass themselves all the way back to _main.
So finally, my question is: will you waste space and clock cycles to preserve modularity? I'd like to hear your thoughts.
My programs use an uncommon way of error handling. At any point of the program, if it encounters a fatal error it will set my error message global variable to something useful and then call exit(0). The function defined for exit by atexit() can properly clean up the program from any point. It then restores the home screen, displays the error message in the status line, and exits. Here's a simple example, without the screen handling:
--MAIN.H--
extern const unsigned char *errMessage;
--FILES.H--
void GetFile(void);
extern FILE *f;
--MAIN.C--
#include "files.h"
const unsigned char *errMessage = "thanks for playing!";
void exitfunc(){
if (f)
fclose(f);
ST_helpMsg(errMessage);
}
void _main(void){
atexit((void*)exitfunc);
GetFile();
}
--FILES.C--
FILE *f = NULL;
#include "main.h"
public void GetFile(void){
if ((f = fopen("test", "r")) == NULL){
errMessage = "cannot open file!";
exit(0);
}
}
This doesn't work well for modularity at all. Files.c and main.c are dependent on each other, and files.c would need to be worked on before use on another project. It isn't very elegant either. So let's look at the alternative, where files.c is independent, and will simply pass on any errors:
--FILES.H--
int GetFile(void);
extern FILE *f;
--MAIN.C--
#include "files.h"
const unsigned char *errMessage = "thanks for playing!";
void exitfunc(){
if (f)
fclose(f);
ST_helpMsg(errMessage);
}
void _main(void){
atexit((void*)exitfunc);
if (!GetFile())
errMessage = "cannot open file!";
exit(0);
}
--FILES.C--
FILE *f = NULL;
public int GetFile(void){
if ((f = fopen("test", "r")) == NULL)
return -1;
}
Now files.c is completely modular and can be used in other programs without modification, as long as the programs can deal with the errors it passes back. While this is good for modularity, it doesn't seem the best solution. Now the same error has to be checked and dealt with on two different levels of the program, wasting space. This waste can become a big problem in regular programs with many more possible errors in deeply nested functions having to pass themselves all the way back to _main.
So finally, my question is: will you waste space and clock cycles to preserve modularity? I'd like to hear your thoughts.

