Archive for the ‘test driven development (TDD)’ Category

An Opinionated Approach to OpenMRS Customization

This is my opinionated guide to OpenMRS (http://openmrs.org) customization for multiple sites, may work for a single site if developer resources are available. This guide is based on 3 years working with the UgandaEMR distribution (https://wiki.openmrs.org/display/docs/UgandaEMR+Distribution) for the Ministry of Health of Uganda, currently in 650 sites across the country (December 2017).

Background to OpenMRS 

OpenMRS is a electronic medical records solution, which runs on Java 8, Apache Tomcat 7 and MySQL 5.x (we are using 5.5 and 5.6). The solution is based on openmrs-core (the platform) and modules which extend the platform providing key functionality such as look and feel, REST API, data collection tools, dashboards, patient management workflows.

OpenMRS releases the Reference Application (RefApp) a collection of modules that showcases how the EMR can be setup for clinical workflows, and which is usually the starting point for implementations. The RefApp is released twice a year, April and October, with enhancements that are prioritized by the community and developed leveraging available resources.

I may be somwhat biased due to my role as Reference Application Lead from January 2017.

UgandaEMR

This is one of the nationally approved EMR solutions, which is being actively developed from August 2015, currently supporting HIV Treatment and Care including HIV Exposed Infants (babies born to HIV positive mothers), Safe Male Circumcision, Tuberculosis treatment, Maternal and Child Health (antenatal, maternity and post-natal care), Outpatient services among others.

Guiding Principles

This approach follows the list of principles below:

  1. Any distribution should only customize workflows, look and feel and provide metadata to the underlying EMR – any custom functionality belongs in the underlying core platform and modules. This rule means that the underlying code grows and evolves with time to meet needs of different implementations, may not be adhered to 100% but even 80% is sufficient
  2. “If you need to change the core, then you are probably doing something wrong” ~Daniel Kayiwa OpenMRS Core Contributor, which is probably true. There are multiple ways to skin a cat so skin it the “openmrs” way
  3. Use the OpenMRS SDK – this tool is what an SDK should be, allows you to create, run and test multiple variations and approaches using the openmrs-distro.properties file that allows the distribution to define and build its own war file and docker containers for shipping
  4. Leverage the new openweb apps (OWAs) approach to provide user interfaces with the REST APIs
  5. For concepts always refer to the CIEL dictionary (http://openconceptlab.org/) as your primary reference
  6. Contribute changes back to the platform and modules you are using rather than build your own – stand on the shoulders of giants, but feed them too so that they can grow stronger and carry others. This is a core opensource ethos
  7. Keep your distribution code public – share with others never know where the knowledge will come from. My personal technology experience has been that at some point in time, you will have to come out and find you missed alot of the magic
  8. Ask quesitons on design, approaches, best practices and collaborate with the community to grow your knowledge and others – Don’t build a wall fence around your house, raise your neighbors so that you do not need a wall fence

How to setup a Customization

  1. Setup OpenMRS SDK in your developer environment – by now you have figured that I love this tool
  2. Use the SDK to create a reference application module usually named openmrs-module-mydistribution using

    mvn openmrs-sdk:create-project -Dtype=referenceapplication-module

  3. Create a new OpenMRS SDK server following the steps at https://wiki.openmrs.org/display/docs/OpenMRS+SDK#OpenMRSSDK-Settingupservers
  4. Copy openmrs-distro.properties file from the server to api/src/resources for your module
  5. Add a build plugin in the omod/pom.xml folder such as below extracted from UgandaEMR
  6. <build>

    <finalName>${project.parent.artifactId}-${project.parent.version}</finalName>
    <plugins>
    <plugin>
    <groupId>org.openmrs.maven.plugins</groupId>
    <artifactId>maven-openmrs-plugin</artifactId>
    </plugin>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    </plugin>
    <plugin>
    <groupId>org.openmrs.maven.plugins</groupId>
    <artifactId>openmrs-sdk-maven-plugin</artifactId>
    <version>3.13.1</version>
    <executions>
    <execution>
    <id>build-distro</id>
    <phase>install</phase>
    <goals>
    <goal>build-distro</goal>
    </goals>
    <configuration>
    <dir>${project.build.directory}/docker</dir>
    <bundled>true</bundled>
    <distro>${project.build.directory}/classes/openmrs-distro.properties</distro>
    <batchAnswers>
    <param>n</param>
    </batchAnswers>
    </configuration>
    </execution>
    </executions>
    </plugin>
    </plugins>
    </build>
  7. Set your custom module to be watched by the server, so each time the server is started the latest version of the module is built and deployed also makes live reload of controllers and styling possible
  8. mvn openmrs-sdk:watch

  9. Add a .travis.yml file to provide integration to Travis CI a sample below
  10. language: java
    jdk:
    - oraclejdk8
  11. Traditional OpenMRS development approaches now follow 😉

More examples from UgandaEMR can be found at http://bit.ly/ugandaemr-technicalguide

In closing, these are my thoughts on how such customizations should be done, while they may need a developer available, they are bound to start the test of time.

Do share your thoughts and learnings from this and let me know how to improve, I may not be able to change though

Advertisements

Software Delivery Skills Plan 2018

If you fail to plan, you are planning to fail! ~Benjamin Franklin

A new year is upon me, and looking over the horizon I am looking to do the following work streams to help better my development skills

1. Work with a new age Javascript framework – vue.js seems the rage, this is also working with webpack and new Javascript build tools

2. Make docker part of my development workflow – this will be project based

3. Distributed ledger proof of concept – the distributed ledger is the rage now, but what can be achieved to prove its capability

4. API First project – this is a separatation of the backend REST APIs from the front end, may be combined with the vue.js to deliver a working project. I will also look to leverage the OpenAPI

5. Write a paper for a scientific journal leveraging the health informatics work I have been doing over the last 3 years and present it at a conference.

TechTip: Dbunit Export from Jetbrains DataGrip

I am an avid test driven development (TDD) advocate nowadays, with a pragmatic slant of course, looking to bullet proof the features that I deliver to ensure that they do what is expected, and work out edge cases.

A big challenge to testing is generating of test data, which is needed to setup some integration test work flows. I have been using Jailer (http://jailer.sourceforge.net/) to generate data from existing tables in a Dbunit format which can then embed in my test dataset xml files.

This is a challenge due to the mapping of relationships by Jailer (a neat feature by the way). So while working Datagrip, the database IDE of choice, we were struck by how to export different formats when looking at a table. This solution would allow us to leverage available filtering and searching features, to nail down the datasets that needs to be exported.

On contacting the support team through Twitter (https://twitter.com/0xdbe/status/853900122828222465/photo/1), the recommendation was to modify the existing XML groovy script to generate DBunit XML, following the steps at https://www.jetbrains.com/help/datagrip/2017.1/extending-the-datagrip-functionality.html

And well an hour later below is a groovy script to do just that can be found at https://gist.github.com/ssmusoke/ca4c55b4e52de97acb99a590644a677f

The code was not being well rendered hence the move to a Gist

%d bloggers like this: