Everything changes. The workflows from last year may not exist next year. There will be new reporting requirements, new data elements, new forms, and new coding systems. Creating software that grows gracefully with the times takes serious architectural thinking from the outset. Vendor pain due to changing MU certification requirements makes the case that flexible software designs are worth the time it takes to create them. Modular systems, where functionality is housed in well-defined, loosely-coupled components, are good for vendors and users. Many usability woes would be easier to address with modular systems. In fact, the AMA made modularity and configurability key elements of its call for better EHR systems.
It is no accident that current systems tend to be monolithic and hard to change without additional programming. As with most things in life, creating modular clinical systems is easier said than done. More importantly, modularity and configurability MUST be design goals from the very beginning, as they are not easily added after the fact. So, why are clinical systems not more modular and configurable? The reasons are both historical and technical. Software development has changed significantly over the last few decades, and especially over the last 10-15 years. Keep in mind that mass use of computers is a recent phenomenon. Before 1980, computers were used at work and, even then, mostly for specialized functions on mainframes and minicomputers. The introduction of personal computers created a huge market for software, and soon banks and insurance companies were not the only businesses with computers. Software development exploded and new programming languages, tools and software development methods appeared.
Of course, the move to computing did not come without headaches. Ambitious software projects tanked — some spectacularly so. The silver lining to these failures was the rise of software engineering and the search for principles, rules-of-thumb, and methods for reliably producing quality software. (Even though software engineering as a field has matured significantly, it still has a ways to go.) That being said, we are much better off than we were in 1980, or even 2000.
Java, released in 1995, deserves a lot of credit for helping to usher in the modern era of software design. Java is a completely object-oriented programming language. At its introduction, Java was (is) more comprehensible than C++ and more down-to-earth than Smalltalk, both of which predated it. Java helped to move programming discussions from pointers and records to objects and their interactions. Objects allow grouping of data with functions and make programming somewhat more indirect. One no longer simply saved a file, or created a form; instead, one asked an object to do these things by invoking the object’s method.
Java is not magical–anything one can accomplish in an OO language can be done in C/C++ or assembly language (very low-level). The difference is the ease with which one can model the real world in the language.
When using assembly language, the model of a patient in an EHR has to remain an image in the programmer’s head. In an OO language, one can create a patient object that has the patient’s medications and problems as collections of objects associated with the patient. Further, worries about managing the heap or bad pointers go away. The overall effect is that one can (has to?) spend more time modeling and thinking about the structure of the system and the way it behaves. Switching from a structured analysis/design approach to an OO analysis/design approach changed the way of thinking about software, about how the pieces come together to form a whole. Design thinking did not originate with OOP, but in OOP, design and architectural thinking are essential aspects of the culture. As someone who started with Fortran and Basic, I found much of the talk about architectural principles and design patterns to be too esoteric and impractical. As it turns out, I simply didn’t get it. Live and learn…
You are probably wondering what this has to do with modularity. Well, much of OO design consists of working out the associations between classes/objects, how those classes/objects interact, and the functionality they contain. For example, single responsibility principle is a fundamental OO design precept—every class or module should have one function or control a limited set of functionalities. Having a database object/module that all other objects send their data for submission to a database is an example of SRP. No other objects interact with the database, only the database object/module handles saving, reading, deleting, and updating data.
Consider two systems: One has all database access code contained in one object/module, the other has database access code distributed among all the individual forms that collect data. From which system would it be easier to migrate to a different database? Again, one can create modular systems without OOP, but OOP development holds this type of thinking as a central tenet.
Coupling, cohesion, and don’t repeat yourself are higher-level architectural principles that emphasize segregation of functionality into discrete chunks. Revisiting EHR system designs with these architectural principles in mind can lead to the type of software the AMA is demanding.
Consider something as basic to EHR systems as the problem list. Problem list functionality could be provided in any number of ways. The simplest would be to treat the list as an array/collection of terms with start/stop dates. In a relational database, such a list would be stored in a single table. At the user interface, rendering of the list could be done using a simple grid, a multi-line text box, or be printed plainly in a window. Here we have the list in three modalities: in memory, in a data store, and presented on screen. In each instance, the problem list is simply treated as data—a series of values to be stored or displayed.
However, what if we decide to make the problem list (PL) a component? We know what the information role of the problem list is for users, but what is the functionality of a PL computationally? Here the question becomes what role the PL plays as a component of the EHR beyond its role as an information source for the user.
Now, consider this scenario. Chronic renal disease is added to the PL. Should there be a function in the PL component that automatically checks meds to suggest dosage adjustments? Should a PL component have a function that scans new labs to look for undiagnosed problems?
Treating a PL as a component that controls all diagnosis/problem functions requires a completely different software design than one that acts as a list and simply records/presents what the user has entered. Now we are considering functions that happen independently of any user interaction with the PL. Going a step further, let’s make the PL swappable (i.e., third-party vendors could sell a PL component that snapped into the EHR). Providing users the ability to swap out components would require yet another architectural adjustment.
Two versions of modularity are illustrated above. The first version, where all problems/diagnosis functions are contained in a single module, isolates its programming code and functions from those of the remaining EHR. Such separation makes it easier for the EHR system vendor to update the PL module programming code while leaving the other EHR code untouched.
The second version of modularity allows one to add a PL module to an EHR system in a way similar to adding a new app to a smartphone. This second version would allow updates to be installed after the EHR system is up and running. Imagine how owning an EHR would be when one could buy the PL from one company and the medication list from another. Don’t like the labs display? Swap it! Both versions of modularity are helpful, but the latter also prevents users from being tied to the innovativeness, or lack thereof, of any particular vendor.
Configurability is a different problem, but still one addressable via component-based architectures. Simply put, configurable components allow important properties to be altered through a control panel or similar means. The most obvious candidate for configurability is the user interface. Allowing window sizes, colors, fonts, screen locations, and the data elements displayed to be adjusted via a control panel would be a huge boon to usability. How many user-centered design hours are spent addressing problems that are better addressed by configurable user interfaces?
Workflows are another candidate for configurability. Workflows hard-coded in EHR systems require far more hours to adjust than would those controlled by a workflow engine with configurable visual workflow models.
The architectural principles discussed above as well as the languages, tools and techniques that enable their application have evolved significantly since 1980. Even going back 15 years, one sees major strides (C# and .Net were introduced in 2002). The number of books, courses and training programs has likewise increased. Everything needed to usher in the next generation of clinical care systems is readily available.
While vendors will see value in renovating EHR systems designed more than a decade ago, those interested in next-generation systems have no reason to use aging designs as starting points. Using available tools and techniques, designers who wish to take the leap can build modular, configurable clinical care systems. User-center design processes (UCD) have an important role in bringing next-generation systems to market. However, without major, and I do mean major, architectural changes, UCD processes cannot overcome the design limitations of legacy EHR systems. As we look forward to the next generation of clinical care systems, let’s keep in mind the one enduring software truism: Tomorrow will be different and so must your software. Quality software is designed for change…