DIVIDE & CONQUER IN THE MLM WORLD
By Irma Sutanto, Eclipsys Practice
Objective: This article will deal with creating an MLM that can be called from another MLM. This is a very
valuable tool for two primary reasons: 1) you can create a module that can be reused by other MLM(s), and 2)
you can break up MLM code into smaller modules. This is not the same thing as creating a “called”
MLM from a form; this process has been described extensively in the Eclipsys Clinical Decision Support
Configuration Guide. Instead, this article will explain why and how to create a called MLM that can be called
by other MLM(s).
Reason: There are several good reasons for the use of a called MLM. For example:
- Divide and conquer: As with other programming languages, large problems usually require large programs
and the easiest way to solve large problems is to divide it into smaller, less complex sub-problems. In the
programming world it is known as “divide and conquer”.
- Reuse, reuse, reuse: Use of a called MLM allows the programmer to write one MLM and then use it in
multiple places. This avoids duplication in coding.
- Reduce complexity: The maximum MLM size is 32 kb. Sometimes it is very easy to reach this size,
especially when dealing with complex clinical rules. The best solution to this size limitation is to break
the MLM into smaller, less complex MLMs.
- Tidy coding: The use of a called MLM allows for the programmer to create neat, clean code in the calling
MLM.
Terminology:
- The main MLM is called the Calling MLM
- The MLM that is called from the main, or calling, MLM is the Called MLM
Description: After several MLMs have been written the programmer may realize that there has
been duplication in a few lines code in some of the MLMs. If this is happening to you, then you may want to
consider placing the duplicate code in a called MLM. For example, a calculation for the patient’s age is
often used in an MLM. While it is true that you can easily get the information from ClientInfo object, some
MLMs require that the patient’s age use the year as the unit of measure and others require that the day
is used as the unit of measure (e.g., a Promethazine order uses the year to check the patient’s age while
a Blood Bank order will usually check the patient’s age using day unit of measure). Instead of repeating
a few lines of code in multiple MLMs to retrieve patient age, why not write a function MLM that calculates the
patient’s age based on arguments sent by the calling MLM.
The code to get patient’s age is:
(pt_guid, pt_name, pt_birthdate) := read last {ClientInfo: GUID, DisplayName, BirthDate};. Since the Birth Date
is not always entered in SCM, it is suggested to check for a NULL value or the existence of BirthDate value
before proceeding. It will be very important to do this check if it is decided to break the code into a called
MLM so that the calling MLM will not send a NULL value to the called MLM.
The following shows two examples for a Promethazine MLM. The first is created without a called MLM:
If NOT (pt_birthdate IS NULL) then
year_diff := (EXTRACT YEAR NOW) - (EXTRACT YEAR pt_birthdate);
pt_age := (year_diff/ 1 year);
endif;
Now, if the code inside the ‘If’ block is written in a called MLM, the main MLM will look like
this:
If NOT (pt_birthdate IS NULL) then
pt_age := CALL Patient_Age_Check WITH (pt_birthdate, "year" );
Endif;
In this example it is only one line of code (actually with a called MLM, it will always be one line of code,
CALL… unless the arguments are long, so the sentence wraps to the next line.), but the called MLM can
be reused every time you need a need to calculate a patient’s age.
In the above example, Patient_Age_Check is an alias of the called MLM name, the word ‘CALL’ at
the beginning and ‘WITH’ after the called MLM name are reserved words. You must use the word
‘CALL’ each time you invoke a called MLM. However, ‘WITH’ is optional.
‘WITH’ will be used only if the called MLM needs argument(s) to run; otherwise, it should be
omitted.
After the ‘WITH’ there are two arguments: ‘pt_birthdate’ and the string
“year”, because we want to reuse the called MLM. Next time you need to calculate patient’s
age with day unit of measure, you can simply call the same called MLM but sending different arguments, instead
of using a string “year”, change it to a string “day”. So the call will look like
this:
pt_age := CALL Patient_Age_Check WITH (pt_birthdate, "day" );
A called MLM normally returns a value to the calling MLM; in this case it is returning pt_age. This
particular called MLM only returns one variable, but you could return multiple variables when needed.
Before the MLM can be called it has to be declared at the beginning of the calling MLM. The code is
Patient_Age_Check := MLM 'XX_FUNC_PATIENT_AGE';. No arguments are needed in the declaration section.
The calling MLM looks like this:
maintenance:
title: Promethazine Contraindication MLM;;
filename: XXHospitalName_PROMETHAZIN_CONTRAINDICATION;;
arden: version 2;;
version: 1.0;;
institution: Hospital XX;;
author: Irma Sutanto (Vitalize Consulting Solutions);;
specialist: ;;
date: 2006-10-02;;
validation: testing;;
library:
purpose:
Display an alert when Promethazine (injection or oral) order is entered for patient younger than 12 year of
age.
;;
explanation:
This MLM will trigger when Promethazine (injection or oral) order is entered. A warning shows up if the
order is entered for patient younger than 12 year of age . On April 25, 2006, FDA revised their warning
against the use of Promethazine in infants and children less than two years of age. They also suggest
caution with it's use in children greater than 2 years. A restriction has been placed in Lexicomp regarding
this warning.
;;
keywords: Promethazine injection, Promethazine oral
;;
knowledge:
type: data-driven;;
data:
/* Set to true if a decision.log is needed.*/
log_execution_info := FALSE;
Promethazine_order := EVENT{OrderInit User Order: WHERE
TypeCode = "Medication"
AND Name IS IN ( "Promethazine Inj" , "Promethazine Oral")};
send_alert := "DoNotSend";
alert_response := "Must Acknowledge";
alert_dest := Destination{Alert: reminder,
"PROMETHAZINE CONTRAINDICATION", low, chart, "Promethazine Alert", 3, send_alert,
alert_response};
/********************************/
if called_by_editor
then
obj := read last {Order: THIS};
EvokingObject := obj;
endif;
/***** Declare MLM that can be called *****/
Patient_Age_Check := MLM 'XX_FUNC_PATIENT_AGE';
(order_name, order_guid, client_guid, order_status, start_date, dose_val, uom_val) := read last
{Order: Name, GUID, ClientGUID, OrderStatusCode, SignificantDtm, DosageLow, uom Referencing EvokingObject};
(patient_id, patient_name, pt_birthdate) := read last {ClientInfo:
GUID, DisplayName, BirthDate};
msg_alert := "";
isPediatricPatient := FALSE;
if NOT (pt_birthdate IS NULL) then
patient_age := CALL Patient_Age_Check WITH (pt_birthdate,
"year" );
endif;
if (patient_age <= 12) then
isPediatricPatient := TRUE;
// create the message here by populating msg_alert variable
endif;
;;
evoke: Promethazine_order ;
;;
logic:
if isPediatricPatient then
conclude true;
else
conclude false;
endif;
;;
action:
write msg_alert at alert_dest;
;;
end:
Now it is time to look at the code inside the called MLM. If the called MLM uses arguments to run (as in
this case), you have to put the list of arguments at the beginning of the data section.
A called MLM is not evoked by anything, so just leave this section blank.
The logic section is really important for a called MLM if it is to return a value to the calling MLM. This
section should have conclude true, otherwise the value is not going to be returned to the calling MLM.
The action section is where you put the variable(s) to be returned to the calling MLM. In this called MLM
there is only one variable returned, but you may put more than one according to your need. Just remember to put
the same number of return variables in the calling MLM.
maintenance:
title: Called MLM that will calculate patient's age;;
filename: XXHospitalName _FUNC_PATIENT_AGE;;
arden: version 2;;
version: 1.0;;
institution: Hospital XX;;
author: Irma Sutanto (Vitalize Consulting Solutions);;
specialist: ;;
date: 2006-10-02;;
validation: testing;;
library:
purpose:
Calculate patient's age with two different unit of measures.
;;
explanation:
Based on the arguments sent, this MLM calculates patient's age using year or day as unit of measures.
;;
keywords: Patient Age, year, day
;;
knowledge:
type: data-driven;;
data:
/* Arguments passed from calling MLM */
(pt_birthdate,
age_format):=argument;
/* Set to true if a decision.log is needed.*/
log_execution_info := FALSE;
if (age_format = "year") then
patient_age := floor (NOW - pt_birthdate) / (1 year) ;
elseif (age_format = "day") then
patient_age := floor (NOW - pt_birthdate) / (1 day) ;
else
patient_age := NULL;
endif;
;;
evoke:
;;
logic:
conclude true;
;;
action:
/* Return patient's age in numeric */
return (patient_age);
;;
end:
Once you have written a called MLM that can be reused you will be surprised how many functional MLMs
libraries you have in your collection for future use. You will save a lot of time the next time writing future
MLMs.
I could continue with the second objective which is breaking up MLM code into a few MLMs when the MLM size is
bigger than 32 kb. It would make this article even longer as the main MLM is very big and overwhelming. Check
our next Newsletter. Just bear in mind this is another way of using a called MLM. For the time being why not
give it a try and write a called MLM. You will have lots of fun reusing the called MLM again and again, so
enjoy!
If you would like additional information on this or another Eclipsys subject, please contact us
at vcs@getvitalized.com or
call our corporate offices at 610-444-1233. More information and education is available on our website
www.getvitalized.com.