As described in some detail in this earlier post on the FHIR formalism, a number of FHIR Resources contain ‘choice’ attributes of the form
attribute[x], such as the one shown above in Observation. These are mapped in the FHIR UML to a ‘Type’ type, as follows.
This is not particularly helpful to developers and does not make for software that can easily treat the value field as a ‘data value’, which is the clear intention. The problem occurs because, even though there is a well defined collection of FHIR data types, there is no parent type for them to use in other contexts. This post provides a proposal for how to fix this.
First, we create a new abstract type called
DataValue, with no properties, inheriting from
Then we create another type called
PrimitiveDataValue<T:Element>, which inherits from
DataValue, and carries an attribute value of type T. This is constrained to be
Element, which is pretty much anything, but we then use it to derive only the primitive-based types we really want. First,
Now, we make all the non-primitive data types FHIR already has (
Period, etc) inherit from
DataValue, and we create the primitive-flavoured ones we need as children of
PrimitiveDataValue. This gives us a universe of data types with a single parent:
Each of the
PrimitiveDataValue descendants looks like this:
and so on.
Note that with this approach, we can always create a new ‘primitive data value’ just by defining another Resource of the form
XDataValue inherit PrimitiveDataValue<X>. I.e. we don’t have to make
PrimitiveDataValue versions of all the primitive types until you know you want to use them. You can also make other kinds of ‘Data values’ this way, e.g. a family of
XSpecialDataValue based on
Observation.value is nice and simple:
Note the red-marked part – that’s another problem, to provide a type that represents time represented different ways. This is something everyone needs a nice model for, and a solution will clean dozens more attributes in the FHIR Resources. We should work on this across communities.
The above solution to
Observation.value, and anything else that looks like it, will add a little bit to the Resources model, but remove many hundreds of lines of code from any software implementation representing
Observation, making it a lot easier to use.