Many programmers consider writing a good program a work of art – much like writing a good article is not only about stating facts but also about presenting them in a comprehensible way.
BASIC is supposed to be an easy language as it has only a small number of keywords and Texmate Tiger macros are relatively short so that it is pretty easy to write a working program without loosing the overview of all its functions. But what about six months later when some changes have to be made?
So here are a few suggestions how you can improve the readability of your code. Some of them are very general but a few are specific to our BASIC language.
Comments, comments, comments:
Where do you need a comment? Ask yourself:
Did it take me more than 5 minutes to figure out how to implement a function?
Does the macro rely on a specific meter setup to work properly?
What is this macro all about?
When did I do the last changes? What has been changed?
If somebody asked me about a specific function, could I find the corresponding code within 5 seconds?
Highlighting important sections
When you create longer macros it is sometimes hard
to find a certain section (e.g. the MAIN_MACRO) of your code. You
can use comments and empty lines to make a clearer distinction
between sections. For example:
//////////////////////////////////////////////////// MAIN_MACRO: ////////////////////////////////////////////////////
or
REM ++++++\\\\////++++++ MAIN_MACRO: REM ++++++////\\\\++++++
Use meaningful names for constants and variables and rename registers according to your application
REG &WATER_LEVEL = &CH1 REG &TEMPERATURE = &CH2 BIT |EMERGENCY_SWITCH = |CAPTURE_PIN
Use constants for array indeces or timeouts wherever possible
Many macros make use of constants, e.g. the timeout for pressing the Program button to enter the edit menu, or text array indeces, or states when in edit mode. If you have to ask yourself what &STATE=14 is, you should try to use a constant with a more meaningful name. Because constants are evaluated at compilation time their use does not affect the meter performance. So do yourself a favor and give those numbers a name.
DIM YesNo[] = [ " Yes", " No" ] CONST YES = 0 CONST NO = 1 // edit modes CONST eNONE = 0 // leave edit mode CONST ePASSWORD = 1 // enter password CONST eCHANGE_PASSWORD = 2 // ask user if she wants to change the password? CONST eNEW_PASSWORD = 3 // enter new password ... EDIT_MACRO: SELECT &STATE: CASE ePASSWORD: EXIT_EDIT if &EDIT_VALUE = &PASSWORD then EDIT NO // always start with NO for this request &EDIT_MIN = YES &EDIT_MAX = NO &EDIT_DEF = NO EDIT_TEXT YesNo[] &STATE = eCHANGE_PASSWORD write "CH_PWD" else &STATE = eNONE endif ... END
Logic/structural indentation
Use indentation (tab or spaces) for code segments that depend on a condition to be executed: IF..THEN, SELECT..CASE, REPEAT, FOR..TO. This makes it easier to get the right amount of closing commands (ENDIF, ENDSEL, UNTIL, NEXT), too.
IF |SP1 = on THEN SELECT &ALARM_LEVEL CASE LOW, MEDIUM: write " warning " CASE HIGH: |SIREN = on write " alarm " CASE EMERGENCY: gosub shutdown_sequence ENDSEL ENDIF
Identify your code including its version
During the development process you will probably end up with different versions of your macro. And even after your sent your Tiger out to the customer there might still be changes due to changes in the application requirements.
Using a version control system (even as simple as keeping different files) for your basic files is good idea but you still have to be able to identify the macro you are running on a specific meter.
The obvious solution is to make use of the CUSTOMER_ID_MACRO that is triggered when you press the PROG+UP+DOWN buttons simultaneously:
CUSTOMER_ID_MACRO: write " Pump Alarm 2.4 " END
Another option (especially with the newer Tiger series) is to use a text register that can be read directly with a single serial command.
If you don't like the 3-button trigger you can of course implement another trigger in your macro. But the meter operating system and version (including subversion) are only available using this built-in mechanism.