Figure 6 illustrates the openEHR model of a Versioned object, and its constituent Versions. In this model, an instance of the class VERSIONED_OBJECT<T> provides the versioning facilities for one versioned item and is often referred to as a ‘version container’.
Figure 7 illustrates a single VERSIONED_OBJECT containing a number of VERSIONs.
The specifications later mention two VERSIONED_OBJECT examples representing “medications” and “problem list”. Let’s add another “current problem list”.
Can a single instance of VERSIONED_COMPOSITION belong to “problem list” AND be also associated with “current problem list”?
Or more abstract: can a single instance of VERSIONED_COMPOSITION belong or be associated with two VERSIONED_OBJECT containers?
Intuitively and they way the spec implies it to me, no. And I guess it’s specified by this description:
“ 1..1(abstract)uid (): OBJECT_VERSION_ID Unique identifier of this VERSION, in the form of an {object_id, a version_tree_id, creating_system_id} triple, where the object_id has the same value as the containing VERSIONED_OBJECT uid.”
It can’t have two uid’s (for two versioned object containers), so it can’t belong to multiple versioned object containers.
I would say no also. If you want to associate different compositions you can either use a contribution to commit both a problem list and an encounter as a changeset, or you can associate them on a long term basis using folders.
VERSIONED_COMPOSITION is just a type derived from the generic type VERSIONED_OBJECT<T> with COMPOSITION substituted for T. Any instance of VERSIONED_COMPOSITION is distinct from all others, and its constituent OBJECT_VERSION parts are as well.
Semantically though, the VERSIONED_COMPOSITIONs representing ‘master problem list’ and ‘current problem list’ (assuming these make sense as distinct lists) could easily contain a reference to the same ‘problem’, which is typically a COMPOSITION committed in an entirely different VERSIONED_COMPOSITION containing a problem/diagnosis EVALUATION. Assuming that the problem lists were constructed by reference to previously committed EVALUATIONs.
First @joostholslag pointed out the uid description that I missed. Based on this a VERSION can only belong to a single VERSIONED_OBJECT (because VERSION.uid contains VERSIONED_OBJECT.uid).
Then @thomas.beale pointed out what prompted this question – VERSION has a data() method that is a reference to COMPOSITION/FOLDER/EHR_STATUS/EHR_ACCESS. This means that two VERSION instances can point to the same COMPOSITION/…
My intuition is that the second use case is something that could happen. However, this is based on my experience in non-healthcare related domains. Clinicians are the ones to decide whether this scenario can happen.
On the other hand, the specifications define the VERSION.uid in such a way that the second use case is not possible (technically it is since the data() can reference anything, but by following the uid description, this should be prevented).
Only the first use case supports proper versioning.
I’ll implement the second use case to make it future proof (it supports both scenarios).
I checked my implementation and it turns out that it supports versioning e.g. a COMPOSITION instance once and referencing that version in two different VERSIONED_OBJECT containers.
Because per specifications COMPOSITIONs are wrapped inside VERSIONs, the same COMPOSITION has two separate versions.
My implementation uses VERSION<T> as an ancestor of COMPOSITION (instead of wrapping). This allows to version COMPOSITION once and reference it in different VERSIONED_OBJECT containers. I hope this is not a faulty design decision
They could theoretically, but that would mean your software and data handling was badly messed up
In a normal implementation of versioning, the content (i.e. data) is semantically inclusion by value, i.e. a composition relationship, not by reference. The data property should have a black diamond on it in the UML (like most other properties you see). It’s an error that it doesn’t.
VERSIONED_OBJECT 1 => * VERSION 1 => 1 LOCATABLE (in general T will be LOCATABLE)
As other mentioned, VERSIONED_XXX should just be interpreted as VERSIONED_OBJECT.
So one VERSION can’t be in two VERSIONED_OBJECT, since part of its UID (OBJECT_VERSION_ID) is the UID of the VERSIONED_OBJECT, that constraint alone doesn’t allow that double inclusion.
In general the first commit will create one VO, one VERSION and one, let’s say, COMPOSITION.
Then for modification commits, it will use the same VO, create a new VERSION, let’s say v2, and the payload will be the modified COMPO.
After a few more hours reading the specifications and the post about versioned folders I realized I misunderstood the use of VERSIONED_OBJECT. I missed that a single VERSIONED_COMPOSITION is a container of versions of the same COMPOSITION template.
I missed that there is a “Problem List” archetype. I thought that a “Problem List” can contain different COMPOSITION archetypes. The actual model is that the openEHR-EHR-COMPOSITION.problem_list archetype can contain any other archetype.
You’re very welcome.
Any recommendations to improve the spec so it’s easier to understand?
You’re also around 5 years of experience, so should’ve been easier for you I would say.
The specs are already clear how VERSIONED_OBJECT is a container of VERSIONs. It was my fault I misunderstood it. I should have checked the CKM to see it has COMPOSITION archetypes for “Problem list”, “Medication list”,… I somehow thought these are specified at the implementation level.
Maybe a third improvement (which is impossible to do) is to have all the Change Control Package specifications in a single document. I realized I was constantly switching between the COMMON and RM specifications. This might have contributed to losing the train of thought.
BTW the semantics of this is something different than intended by the versioning spec (which is aimed at versioning of content, i.e. data, more or less like Git and similar things) - it is versioning of references, which is what VERSIONED_FOLDERs (= versioned FOLDER structures) do.
Specifications are using clear modeling for versioning. However, going from UML diagrams to implementation requires some design decisions.
My experimental implementation goal is to implement everything with a pure relational SQL database (I might end up with a Domain Driven Design implementation – I know it is discouraged ).
To achieve good performance, this requires some flattening of the highly hierarchical RM.
Furthermore, by following the goal of a relational database, the primary keys are used instead of uid references found in the RM classes (using uid references is still possible).
In case of versions, the system cannot “move” previous versions to a “version history” table as it would break foreign key constraints (e.g. when a COMPOSITION is used in CONTRIBUTION, FOLDER, EHR).
The canonical content is still versioned in the ORIGINAL_VERSION.data attribute as per spec.
Note that this is still highly experimental and used to pass time doing something challenging. It is also a good learning experience – I have to go into every detail of the specifications.
However, there is a mention of 2 separate problem lists in the specifications:
The total number of Persistent Compositions is normally small for any given patient even with the possibility of more than one instance of some, e.g. multiple condition-specific problem lists.
Maybe a better example of multiple “lists” are care plans:
Care plan - Plan(s) produced by clinicians describing planned management of chronic problems.
I could imagine there are separate care plans for different chronic problems. During an encounter the same evaluation could be referenced by multiple care plans. Maybe others with clinical experience will add more to this.
I have in the past (as you know used the approach of defining a formal transform of the primary model, which is intended for sharing through an API and building software from. This is the P_XXX model that you see for AOM, and I’ve done this a few times in the past. The P_XXX model stands as a formal statement of a form of the model that can be used for serialisation (that’s what the P_AOM model is for) , DB persistence etc. We had a similar thing (so far not used AFAIK) called ‘simplified’ RM (S_XXX model). All that is required for this approach is that an instance of model A (e.g. AOM, i.e. actual archetypes) can be transformed bidirectionally between the two.
This is not the only way to do it. The other (probably more common) way is to define a set of rules that are machine-evaluable, that convert a source model (say the openEHR RM) to another form, e.g. a SQL DB schema. @borut.jures and some others here know ow to do this very well.
All I am noting here is that having some formal representation of the transform between a primary model and a DB or persistence model (or any other flavour of model, e.g. ‘web templates’) - because then we can regenerate e.g. the DB schema from a changed form of the RM.