What are the affects of using global or local variables in a custom VFE form but never declaring them "global" or "local".
Example 1:
problist = getfield(PROBS_AFTER("delimited","|", "")
Example 2:
for a=1, a<= size(problist), a=a+1
…..
shouldn't each of these explicitly declared like this ?
global problist = arrary()
problist = getfield(PROBS_AFTER("delimited","|", "")
local a = 1
for a=1, a<= size(problist), a=a+1
Would this have any affect on any other forms within the Document Template / Encounter?
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.
Lee,
Thanks for the detailed response. I have found that the newly released COVID-19 Telehealth Screening form from Athena causes my encounter to hang up. In looking at this Athena-supplied form, there are no Global or Local declarations; the variables are just used. My customized forms work well in the absence of the COVID-19 Telehealth form. Once I load the COVID-19 Telehealth form into my encounter it causes issues/form will just hang up.
When I originally submitted this Forum item, I compared my custom form to the COVID-19 TH form, and found that the two forms shared one variable. In my form, it was declared locally within a function and the COVID-19 TH form just used it in a watcher function. Since then, I have changed the variable name within my form as to not conflict with the COVID-19 TH form.
As of today, my custom form works well but (as stated above), once I add the COVID-19 TH form into the encounter, the whole encounter freezes up when I press any button on my form.
I believe that the issues resides in the COVID-19 TH form (i.e., not declaring the variables properly). I am going to download the most recent version of the COVID-19 form and take another look at it, with possibly explicitly declaring the variable to see if it changes how it operates.
Do you think this is worth the effort? What other troubleshooting steps are needed to figure out where the problem lies?
I think it will be worth the effort, if at the least, you are able to identify and strengthen any vulnerabilities in your own code. Nice catch on the variable name too!
If the issue persists, you should run a MEL trace and search for the word "ERROR: ". If there is an issue, it should appear there. If there is no issue, then a line by line analysis is warranted. If you want, you can post the trace here in zip format and I will be happy to look it over as well. If you do post it, be certain to use a test patient for HIPPA compliance. 😉