Agenda attached below
Introductions & Agenda Overview
Ideal Project Timeline
Airing of Grievences
Principle: Shared Value
1. No framework for creating dashboard and reports
2. Lack of 'offline first' functionality
3. Ability to contribute w/out toe-steping
4. Monolithic application tightly coupled with UI
5. Scant API and Doc
6. Country-specifc data collection forms w/out forking
Feature Variability Matrix Review
OpenLMIS Domains, as User Stories
See OpenLMIS Domains.
OpenLMIS Domain Modeling
Reviewed CRDM work and agreed on the following primary domains:
See Domain Modeling Technical Deep Dive
Key Items To Address Later in Design Session Week
Terminology
3.0 - re-architecture MVP release
3.x - 18 month scope window
4.x - belongs in the domain - not scoped for 3.1
AM Session - MVP Definition Wall Exercise
Sarah Jackson (Deactivated) to add photos
PM Session - Architecture
Principles for OpenLMIS Architecture:
Principles:
Requisition Service
“New Requisition with blank status” service endpoint
Refers to reference data for facility, program, commodity
Has-many Requisition Items
“Save Draft Requisition” service endpoint
“Submit Requisition” service endpoint
“Approve Requisition” service endpoint
(sync approach) Creates an Order object by calling another service
(async approach) publish “Feed of Approved Requisitions”
Fulfillment Service
(async approach) subscribes to the Requisition service’s feed of Approved Reqs
(sync approach) “Create Order”
“Query Unfulfilled Orders”
“View Order Details”
Scenario 1: add a new calculation algorithm for suggested order size
=> option: we planned for this, so this is its own microservice. You just replace it
=> option: we planned for this, so
Scenario 2: collection of varying-by-country program data, to be collected with requisition (as a separate, required, section/tab on the requisition form)
=> option: store that form submission as json (either in its own document DB, or as a free-text column in the requisition table)
=> option: first, user submits program data to its own service. Then, submit requisition to req service (which may check that other data was submitted before it accepts/approves a submission)
Scenario 3: additional approval step to compare to historic data from DHIS2
=> option: fork the requisition service and change a small piece of it
=> option: split the requisition service (pulling out the approval service)
How do we do reporting?
=> option: ETL process (where “E” calls API, not DB) and generates your cubes
=> option: data lake
Cold chain equipment:
Fulfilling needs to start querying cold chain to ensure machines available
R+R might be where you capture status of cold chain equipment
Standard layered architecture with proper object-oriented design at the domain layer.
Services used for orchestration (and for reference data, just for CRUD operations)
Tied together with Spring IOC container and application context or equivalent
Modules can include:
Java code (e.g. implementations of the Strategy pattern)
Instructions about which extensions attach to which (core) extension points
(HTML+JS+CSS) -OR- you fork/contribute to the reference UI
A module that adds significant functionality would add all layers (and it could add tables to the shared database)
Requisition Service & Fulmillment Service (actually these are the same)
Scenario 1: add a new calculation algorithm for suggested order size
=> implement the CalculationStrategy interface in your own module’s code, load this (instead) via the spring application context (your module is a JAR file)
Scenario 2: collection of varying-by-country program data, to be collected with requisition (as a separate, required, section/tab on the requisition form)
=> strategy pattern for “is the program data recorded, so I can save a requisition”; there is a part of the business layer
Scenario 3: additional approval step to compare to historic data from DHIS2
=>
Pros:
Allowing people to fork one microservice limits effect of bad forking behavior (many smaller repositories => people will tend to fork less/smaller)
Someone else can create a new service (or override one) in any language/framework
Cons:
Overriding one endpoint within a service requires “forking” the whole service if an extension point has not been created
Complex model compared to monolithic application
Pros:
Familiar model for typical Java developers
Easy to extend/configure at known/predefined points
Double-edged Swords:
Forced to go through shared governance process to change the monolithic domain model
Cons:
Must use Java (or other JVM languages)
(Without letting modules provide UI components) pushes forking of the reference UI
The above discussion didn't flow very smoothly, and we eventually realized that we're mainly arguing about different philosophies about the value proposition, rather than actual architecture...
Actually, we're really talking about Monolithic Core vs. Independent Services for Bounded Contexts
Independent Services for Bounded Contexts:
Reducing dependencies to allow more independent evolution of functionality without significant worry about breaking changes
Allows people to work in a smaller code repo => less stepping on toes
Shared value is the agreed-upon contracts (for state transitions)
Scale development better by letting different teams work on different services at different paces
Microservices are more complex, rather than simpler, as an architecture. (But they can allow an individual service to be simpler.)
Monolithic Core
Shared value is the shared core domain model
Architecture, continued...
How We Arrange OpenLMIS
Options:
a) Core - Without this, you don't have OpenLMIS. OpenMRS model.
b) Mix and Match Model - Use what you like. Salesforce model.
Definitions:
Discussion:
This table records the pros and cons that were mentioned about both approaches. In most cases there was no agreement about whether these are actually pros and fonts.
Pros | Cons | |
---|---|---|
Core Approach (OpenMRS Approach) | Encourages community to come back together on Core Higher reliability of core product (…?) | Is there really a well understood definition of what should be in Core? Higher merge cost for bringing in changes Slower pace of change – devs need to wait for updates from core – encourages forking If the extension points aren't there, you have to fork, or wait for global team to add the extension point |
Mix and Match Approach (Salesforce Approach) | Supports quick innovation and product evolution Enables multiple partners to work independently | Network effect between micro services - difficult to coordinate and ensure application works If data is in a shared data store, the micro services aren't really independent What is OpenLMIS in this scenario? Just the infrastructure? |
1) There will be several repositories that comprise OpenLMIS: > 1
2) The collection of repositories in the OpenLMIS org in github = the product (at least, the code of the product)
3) The governance of OpenLMIS comprehensively manages all of the repos in the OpenLMIS github – no matter the underlying architecture
4) The “core” is the set of headless modules/services/objects which implement the domain model
5) The reference UI comprises the set of code (which may be in multiple repos) that implements an out of the box UI exposing OpenLMIS functionality. The ref UI must also allow easy ability to override particular functionality/look/feel in the user interface w/o forking the whole reference UI
6) The domain model is defined as set of bounded contexts for logistics, and has extension points.
7) The number of bounded contexts and their definition is still TBD
8) We have still not decided whether to implement the domain model as a set of microservices or via a java object model with api interfaces
Break-out into technical design track, and product management track.
Product management
Discussed grant proposal, and aligning white label mobile app work with re-architecture:
Developed basic user stories list for Inventory Management domain
What to include in scope for 3.x? There is a feeling that what is currently in the 2.0 branch isn't completely sufficient, but in the absence of complete, multi-country requirements, we have a suggestion to ensure that what currently exists in 2.0 + the user stories being developed by Brian, Lakshmi and Sarah be considered for inclusion.
See Domain Modeling Technical Deep Dive
Lean towards continuing with AngularJS, for now. (Current team members are familiar with AngularJS, and we'd be able to preserve more of the existing front-end code.) A module UI could potentially let future UI screens be done in another technology.
Current UI is not using Angular routing, but rather is a collection of many single-page apps. (This might actually make it easier for us to move towards a modular UI.)
OpenMRS has already written a plugin module architecture based on Spring, that lets modules add Java code, and attach to extension points. If this is basically what we want to do, we can copy a lot of it. (E.g. some of this code.)
Goal was to develop a platform, but that was not achieved in the first cut, so there was a need to re-architect to introduce a modular architecture. The InfoPath form-entry was the first module introduced, and for a few years, most implementations simply used the core plus one of three Form Building options: InfoPath (first module); HTML; XFORM.
The UI needed to be redone to support real-time data entry eventually (vs supporting the paper form process).
Long process to make changes to OpenMRS core, which took on average about 6 months to move from ideation to release, and sometimes longer, which became a problem when the work on the UI and workflows picked up steam. Simply took too long, so the modular approach was needed and became the preference of many contributors.
2005 - 2011: Development occurred mostly on 'core'/trunk path, but then rapid and significant shift to modules as it provided contributors the ability to iterate rapidly and deliver their product faster. In retrospect, the 'shift' should have happened earlier.
Current State: Still concept of 'Core' (data model and Web Services exposing the Core), but most work is now done in modules. Core prioritizes stability over flexibility. Never envisioned that there would be so many modules, but the reference application now includes more than 30! (There are more than 100 modules altogether.)
Concept Dictionary: Core has no hardcoded data model tables, e.g. "Vitals" table with 'weight', 'height', etc.; rather there are 'entity', 'attribute' & 'value' tables, which makes it (much) easier to customize, though it makes analysis a bit more difficult. This is the 'heart' of OpenMRS Core – provide the building blocks for others to use to build their own pieces of functionality.
Logic Module: Should be able to manage "Calculations" (e.g. BMI, asthma, etc. – large variety of rules) as observations. Ultimately was only ever used in one place, however, as the project was under resourced, code was complex and was never abstracted for wider consumption. Was later removed from Core and into a module. In retrospect, even though it seemed like this functionality should be a 'Core' feature, it would have been better to have made it a module from the start to enable rapid iteration.
Lesson Learned was that no feature should be added to Core until it is "finished" b/c of the slow release cadence. Core prioritizes stability over flexibility, and thus if you need to iterate to get to a point of "completeness", then better to isolate the code into a module where it will be easier to work on and have more releases. Also, there is more value to put the interface into Core rather than the implementation itself.
'Allergy' Module: Example of a module that rapidly developed and matured to the point at which it was pulled into 'Core'.
Prefer Industry Standard Technologies & Solutions vs Custom Development, e.g.
Enforce modularity by separating them into separate code repositories