Excellent question!
It is imperative to declare variables properly in MEL. Failure to do so can risk inadvertent assignment of values and crossing data between patient charts. Neither produce reliable outcomes and both risk patient harm and, in my opinion, is one of the most important rudimentary syntax statements involved in MEL coding.
First: If the variable is not properly declared but it is called/assigned, it will undergo a recursive pass where the value of NULL is assigned before it can be assigned desired value. This can result in inadvertent FALSE results being interpreted by the MEL compiler. For instances where there is a single event trigger, this can be problematic.
MEL manages three types of variables, each with their own scope within the EMR:
- If the intent is to keep the variable isolated to the form, code statement or function, the the variable should always be declared as LOCAL.
- If the intent is to make the variable available to the entire update AND the EMR (i.e. handouts, letters, banners, etc.), the variable should be declared as GLOBAL (see Caution below).
- If the intent is to make the variable available to the update but not the entire EMR, you can simply declare the variable without the LOCAL or GLOBAL designation. This is a default 'declaration' for MEL.
Note: When using types 2 AND 3 above, it is important to ensure that you do not use the same name more than once. Doing so will reassign the scope of the variable depending on the last invocation.
Background - the purpose of declaring a variable in MEL is to assign a memory location and a name to that address so that when it is subsequently referenced, it knows where to read or write a value from or to. Without a 'full address', it would normally throw an error, but the MEL compiler defaults to the update wide value (third version) instead. This fail safe is convenient, but also risky in that most do not uniquely name their variables and risk unreliable results from their code due to the chance of duplicate variable names and different purposes.
This is more often than not masked because of the habit of evaluating non-empty results instead of an actual value (i.e. checkbox <> "" instead of checkbox <> "exclude"). If a different code string populates the variable with an unexpected value, one would never know it since it is not looking for a specific value. To the un-traced/un-validated view, the code simply 'works' when in reality, it is not functioning properly.
Caution: Use GLOBAL with extreme caution. If the right conditions are met, it is possible to move data from one patient update into another without realizing it (especially in Banner and Header code). If one is unable to envision a scenario where this is possible, I cannot recommend strongly enough how important it is that individual never invoke GLOBAL in their code until they are routinely able to do so. Instead, one can use a document variable or obsterm to cross the update/handout/letter barrier instead.
One last note: Variable names should be unique as possible unless there is intended sharing between forms due to the fail safe method and even then, to ensure full control over the data being assigned. If the same name is referenced for two different values, the results can be unexpected, especially with more complex and branching code. My rule of thumb for anything not local is to use a name and an abbreviated version of the form name as an underscored suffix. i.e. gHeader_THealth.
Inside of a function, I use local 99% of the time and prefix names with either str to indicate the variable holds a string or n to indicate the variable is numeric. I typically use i and ii as index counters for loops. Outside of a function, for the first letter, I use lower case L for locally declared variables, lower case G for the default version only, and lower case Z for the system wide global declarations. Regardless of your preference, it is important to establish naming conventions for later review and modification. This also makes it easier on the next person responsible for the task.
Bonus Trivia: If two functions share the same name in an update, the last version of the function loaded into memory will be referenced. To MEL, by using the same name, the new 'body' is supposed to overwrite the previous 'body' in memory. Therefore, I recommend devising a similar naming convention for functions (i.e. fnCalcBMI_VSE where VSE is Vitals Signs Extended). This even applies to function libraries, where I recommend that a reference to the library name be included in the function name. This small addition makes it exponentially easier to troubleshoot and follow code, an important tool in debugging when things are not going right.
Last tip: Case does not matter - gVar is seen as GVAR to the MEL compiler. We use case for readability of code more than anything.
I hope this helps.
Posted : April 27, 2020 2:04 pm