DEV Community

Bukhori M. Aqid
Bukhori M. Aqid

Posted on • Originally published at Medium on

Design Patterns in Healthcare domain

Same old design patterns, from healthcare use cases

For those of you who don’t know, design pattern is one of the fundamental concepts in software engineering that will help you manage pieces of your system by reducing complexity and isolating independent components so that frequent change can be performed smoothly.

A pattern describes a problem that occurs over and over again in our environment, and then describes the core of the solution to that problem in such a way that you can use this solution a million times over, without ever doing it the same way, twice

 — Christopher Alexander, A Pattern language

Design Patterns by GoF

One of the famous books regarding software design pattern is created by Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson & John Vlissides).

A System of Patterns

There is also a good book by Gang of Five (5 completely different persons than Gang of Four) which gives a bigger scope perspective in software engineering patterns.

In this series of articles, I will try to dissect and discuss some of the patterns contained in those 2 books with sample cases/problems from the healthcare domain. I do realize that those books discussed more towards the context of Object-Oriented Principle and might not apply in some non Object-Oriented language. But the patterns alone are worth to discuss and might be beneficial in some general cases.

Before starting the pattern discussions, we have to know how to model real life concept/object type and phenomenon/object instance. We usually model those with UML (Unified Modelling Language) and that’s what we’ll use most of the time while discussing design patterns.

Since we’re going to work with lots of UML diagram in this article series, let’s recall some of the UML notation:

https://www.omg.org/spec/UML/2.5.1/PDF

There will be some UML doodle similar to the one above in this series so bear with my chicken scratch handwriting :)

Before crafting UML diagram, there are 4 important concepts that you need to remember for modeling:

  • Abstraction : Can the object instances be generalized into type or sub-type?
  • Inheritance : Which type is the ‘parent’ of the other type? (Car vs Sports Car)
  • Encapsulation : Which part of the data/behavior is exposed to the outer world?
  • Polymorphism

PSE 1920 TUM: Polymorphism hierarchy

Besides doing that, you also want to achieve low coupling and high cohesion. Having low coupling means that the dependencies between subsystems are low and high cohesion means that the dependencies among classes in one system are high. To achieve this property there are some things that you can do :

  • Principle of Least Knowledge/Law of Demeter The intuition for this is rather easy, if you call multiple objects e.g. objectA.getB.getC.doThings() then you might violate this principle.
  • Ask, don’t tell Instead of directly modifying object internals (tell), call a method/API that will modify such internal (ask).

In this article, I will take some of the patterns and try to give some context and examples related to healthcare domain.

I. Structural Patterns

This pattern group aims to reduce coupling between classes, enabling future extensions (by introducing abstract class) and encapsulate complex structures.

Delegation Pattern on Activity Delegation between Doctor and Nurses

In many states, physicians can delegate their activities to nurses, physician assistants or other medical professionals to deliver care more efficiently and effectively.

http://lawatlas.org/datasets/physician-scope-of-practice-1509022789

I can imagine that during the daily tasks of a doctor, there are some activities that can be delegated to another role that is better suited or even more skilled in that one specific action. That’s why sometimes you have doctor prescribe and/or apply the first medicine but then followed up by nurses.

We can model that kind of scenario using delegation pattern. Simply by having Doctor class to store reference to Nurse class and when needed, call the Nurse object for action delegation.

if (doctor.busy) nurse.apply()

Adapter Pattern on API Development in Legacy Hospital System

Consider this scenario:

A hospital has already been running for 100 years with stable in-place system.

You are a new and modern tech division in the hospital, wants to create mobile app, needing API that consumes the data from legacy system as well as collecting new data from other sources

some kind of UML Diagram

One way to connect those 2 systems is to create an adapter. In the UML diagram above, Legacy Adapter acts as a translator/connector between 2 systems. This can be done by implementing interfaces or extending parent class (and override some methods) from the new system and then make a delegation call (blue arrow) or calling the superclass method (inheritance green arrow) to get the value.

Please be aware that you might need to do some parsing/conversion process in the adapter to ensure that the request and response data is in a valid format.

Bridge Pattern on Medicine Procurement from Multiple Sources

Medicine procurement in hospital pharmacies of Nepal: A qualitative study based on the Basel Statements

It was found that the majority of hospital pharmacies in Nepal reported using an expensive direct-procurement model for purchasing medicines.

Since direct-procurement in Nepal is expensive, we want to provide cheaper option by having an auction based or competitive-procurement. But we don’t want to disrupt an already stable system. There is also a problem that some branches might already have their own customization. This calls for a Bridge Pattern.

In this scenario, our Bridge Pattern consists of

  • Application Domain: This is your hospital/hospital system
  • Solution Domain: This is where you get your medicines using some procurement model

Procurement can happen with direct or competitive procurement model, and in this case each hospital branch have the the liberty to choose any model they prefer.

By creating a bridge pattern between abstraction of hospital and procurement, we can strictly define each branch to have procurement model but since the subclass can override the superclass then each branch can choose their preferred model and new branch can also choose their preferred model. Changing model also easy, just add implementation of procurement and change branch that wants to use that new model.

But be careful with Degenerate Bridge : where the application or the solution domain doesn’t have a subclass/subtype (yet). This might increase complexity without any clear benefits.

In a sense, Adapter pattern might seem similar to Bridge pattern. But “Adapter makes things work after they’re designed; Bridge makes them work before they are. [GoF, p219]”

Proxy Pattern on Patient’s Guardian/Decision Proxy

Why all adults need a healthcare proxy

The article above argues that we should always have a healthcare proxy in for emergency cases. As a healthcare system developer, we want to cater to this scenario hence we’ll implement Proxy Pattern in our hospital system.

There are 3 types of Proxy Pattern:

  • Caching/Remote Proxy The proxy object is used for information caching (local representative for an object in a different location)
  • Substitute/Virtual Proxy This proxy is used for a stand-in object in case the real object takes quite a lot of time/memory to instantiate
  • Access Control/Protection Proxy This proxy provides access control to the real object

In this particular case, the guardian acts as access control proxy. If the real patient can actually do / willing to do said action that it will do it otherwise the proxy gets to decide.

scratch UML for proxy pattern

if (competent) inPatient.agreeToProcedure()

else patientP roxy.agreeToProcedure()

II. Behavioral Patterns

By applying patterns in this group you can answer “Who does what?” questions, e.g which algorithm is used for some problems, or which object instance to use. This will also simplify control flow and enable a better understanding of your program data flow.

Strategy Pattern on Patient-Centered Care approach

Eliciting patient treatment preferences: A strategy to integrate evidence-based and patient-centered care.

One of the strategy described in article above is to elicit patient preferences via written description. With some preferences given, there will be differences in patient care/treatment. During the hospital system development, this scenario can be handled by utilizing strategy pattern

The difference with Bridge Pattern is that if you use a bridge pattern, the patient (depending on the preference) will receive the type of treatment that he/she wants before system runtime while in strategy pattern, the treatment will be decided from patient preferences and can be changed at runtime if the preferences of the patient changed.

State Pattern on Medical State representation

Sometimes, hospital describe patient’s condition in a medical state jargon. Even though this is not commonly used clinical term, it will serve as a nice example for the needs of using State Pattern.

Medical state

State Pattern is used to help object control their behavior by changing its internal state.

Per Wikipedia’s description, there are several Medical States:

Undetermined

Patient awaiting physician and/or assessment.

Good

Vital signs are stable and within normal limits. Patient is conscious and comfortable. Indicators are excellent.

Fair

Vital signs are stable and within normal limits. Patient is conscious, but may be uncomfortable. Indicators are favorable.

Serious

Vital signs may be unstable and not within normal limits. Patient is seriously ill. Indicators are questionable.

Critical

Vital signs are unstable and not within normal limits. Patient may be unconscious. Indicators are unfavorable.

Dead

Vital signs have ceased. Patient has died.

scratch UML for Medical State

Every state can move to another state depending on the patient’s condition.

patientState.handle(…) can results in different actions depending on the current Medical State

There might be a question on where to handle state change, should it happen in the context class (TreatmentContext) or should it happen in concrete class (Medical States). I would say that this is up to personal preferences, but handling it in the concrete class will reduce the conditional block and making it simpler to add more state and/or see the limitation on each state.

Observer Pattern on Integrated Patient Information

Inadequate availability of patient information is a major cause for medical errors and affects costs in healthcare. Traditional information integration in healthcare does not solve the problem.

An improvement for the information exchange is needed. The goal is to provide better information exchange between institutions (see Broker Pattern), or in smaller cases — between displays in a hospital counter. Let’s discuss the this smaller scope using observer pattern.

There are 2 key parts in observer pattern:

  • Observable object / Publisher
  • Observers / Subscribers

Imagine that in the same examination room, you have different screen / Graphical User Interface (GUI) used by the nurse to take your blood pressure, check for previous diseases, etc. There is also another GUI for the doctor to input more extensive treatment and diagnosis.

Wouldn’t it be nice if when the nurse enters your measured data, the GUI for the doctor is also updated? We can achieve this by applying an observer pattern with patient information as observable object

scratch UML for publish-subscribe scenario

Each GUI must have Observer implementation so that they can observe the patient information. And since they also modifying the Observable object, all changes will be observed and updated by other GUIs.

III. Creational Patterns

Sometimes to create something there are complex process involved and Creational Patterns are one collection of design pattern trying to improve the implementation of those complex processes. By applying patterns in this group you can create a simplified view to understand those processes in a glance. This will also make the creation process independent hence reducing dependency and coupling.

Abstract Factory Pattern on Doctor Skills Composition

Doctor can have multiple skill set. How do we properly model this scenario using Abstract Factory pattern?

Before starting with this pattern, we need to address the difference between Factory (Method) pattern vs Abstract Factory pattern.

Factory Method

As the name implies, Factory Method is a method / function that has an objective to instantiate one object.

Abstract Factory

Utilizing full class as Abstract Factory, we can create more complex object instantiation consisting of different classes composing that said object.

Now let’s consider the action of adding new doctor to the hospital. Every doctor has their degree and specialization and we might encounter one situation where we have a very competent doctor with multiple and maybe specialized skills. How can we create new doctor object with all the skills information and dependencies?

In this case, we can generalize few things, such as:

  • Hospital has doctors
  • Doctor has Degree(s)
  • Degree has a specific Degree Factory extending default (general physician) degree factory
  • Degree factory returns degree containing multiple skills given specific factory class
  • For a new degree, it’s as easy as add new degree factory with composeSkills() method containing all the required skills

scratch UML for Abstract Factory Pattern

IV. Architectural Patterns

An architectural pattern is a special set of pattern applied to software architecture problem within a given context. In this section we will discuss several samples of Architectural Pattern.

Blackboard System for Evidence-Based Diagnosis

Understanding evidence-based diagnosis : Diagnosis

“ How do we minimize the cognitive errors inherent to a task like diagnosis? The answer is even less clear, but computerized diagnostic support tools may have a role.”

One approach to model computerized diagnostic support is by using Blackboard (behavioral) pattern implemented in Blackboard system (architecture). Intuitively, you can imagine blackboard system as a room filled with experts discussing problems and putting solutions and opinions in the blackboard to achieve one final consensus/result.

In general, blackboard system consists of 3 big elements:

  • Blackboard is the repository of the problem, partial solutions and new information (hypotheses, etc)
  • Knowledge Source that reads anything placed in the blackboard (input) and place new information created by them on the blackboard.
  • Control that governs the flow of problem-solving activity in the system.

Also in order to create blackboard system, there are 6 steps that will be beneficial to follow:

  1. Define the problem (and make sure there’s no algorithmic solution for it)
  2. Define the solution space
  3. Identify Knowledge Sources
  4. Define the Blackboard
  5. Define the Control
  6. Implement Knowledge Sources

Let’s apply those 6 steps in our case

  1. The problem : Evidence based diagnosis Domain: Healthcare Requirement: Given symptoms, patient health data & history, provide supporting diagnosis output Actors: Doctor, Patient, Nurses
  2. Solution space : In the solution space, we need to identify the existence of top-level and intermediate solutions. A top level solution might indicate a flu diagnosis while intermediate solution might specify more details like possibility of dengue fever. For a complex diagnosis, partial solution might be needed as well. Such as giving cluster of diseases might occur given the observed symptoms and patient’s history.
  3. Knowledge Sources: Different records of past diagnosis, organized (e.g. grouped by city) Inputs: Patient health data, Reported symptoms Outputs: Solution candidate as different diagnosis with confidence level
  4. Defining Blackboard: We need to decide the data representation used in the blackboard, such as JSON with added metadata.
  5. Defining Control: How are we going to process all the data provided from various Knowledge Sources? How and who are going to construct and verify the hypothesis? What constitutes an acceptable solution? In this stage, an expert help is necessary so collaboration is a must.
  6. Knowledge Source implementation To implement Knowledge Sources, we need to define condition and action. We can utilize multiple arrays of techniques such as Bayes rules, classification algorithms, rule based system, or any of the computational intelligence methods.

scratch UML for Blackboard System

Client-Dispatcher-Server for System with High Availability

Once, I visited a clinic because I got a fever. Their system is under maintenance from 11:00–13:00 and I need to wait until it’s up before my medical data can be processed.

True story. And we can avoid that by implementing simple client-dispatcher-server

Healthcare is a critical field. A single mistake can cost human life. When I check myself in that said clinic during mid day, I observed that they have tablets and laptop but not using it. Curious, I asked: why do you have those devices but not using it? Surprisingly they said: Our system is usually under maintenance during this time so just to be safe we use paper and we will process the data later. Of course there might be multiple reasons why this happen but having only one server without backup might be the cause, so when there is a scheduled update then the client will be unable to connect to that server. We should provide several servers as backup so we can have zero down time deployment and update. But how are we going to manage those servers and the client connections?

Client-Dispatcher-Server architecture will help manage your system by introducing a dispatcher subsystem that manages connection between multiple clients and multiple servers so that updates can be done without making the server down.

To implement Client-Dispatcher-Server there are some steps that is useful to follow

  1. Identify subsystem that act as clients, servers and dispatchers
  2. Decide on the communication mechanism to be used for the protocols
  3. Specify the protocols between components
  4. Decide naming scheme for dispatcher
  5. Implement the dispatcher
  6. Implement client and server

Note: To be technically accurate, client-dispatcher-server architecture should enable direct client-server connection after name resolve so if you’re using load balancer to manage multiple servers you need to configure direct server return (https://www.haproxy.com/blog/layer-4-load-balancing-direct-server-return-mode/), sticky session or the combination. But in real life this usually doesn’t matter much.

Broker Pattern for Integrated Patient History

While in Observer Pattern we discuss how each hospital units keep it touch with the data, there is also the need to have integrated patient history between hospitals which means all data must be passed remotely. The question is, how to accommodate this use case in our system?

Broker Pattern, specifically message broker pattern can be used in this scenario.

Message broker

While implementing the pattern you need to provide client proxy and server proxy in order to make sure that there is no compatibility problem between different platforms and implementations as well as hiding inter-process communication details between said party to broker. The proxy will also takes care of marshaling (serialize) and unmarshaling (deserialize) messages.

There are lots of existing libraries / tools that can help you with the implementation of message broker pattern. Some of the most popular ones are RabbitMQ and Apache Kafka, among many others.

By understanding several different patterns and actively implement them, we should develop an intuition on how to solve some problems. There are a lot more patterns than described in this article and I personally recommend SourceMakingas your first stop on understanding further patterns. But we have to be careful to not fall into AntiPatterns trap, especially since sometimes, detecting Anti Pattern is hard.

Hope this helps!

Top comments (0)