Work on your Vocabulary. The word for today is "CodableValue"

Vocabulary and CodableValue are two of the somewhat interesting types in the HealthVault platform, and I thought I'd spend a little time discussing them.

So, here's the problem they're designed to solve.

In medicine, there are sometimes long lists. The kinds of lab tests you can order, the kinds of medication that can be prescribed, or the specialties of physicians. Unfortunately, the actual names can be a bit unwieldy. For the last example, you see things like:

  • Medical Toxicology - Emergency Medicine
  • Neurodevelopmental Disabilities (Pediatrics)
  • Adult Reconstructive Orthopedics

So, to make things simpler, there are a set of codes - using one to three letters in this case - that are the "standard" ways of encoding the longer string (what I'll call the "Display Text"). Take that code, put it together with the display text (and sometimes an abbreviation), and you get a Vocabulary item. Create a list of a bunch of VocabularyItems (along with some other information I'll talk about in a minute), and you get a Vocabulary, which defines both a list of possible options and the accepted way of encoding them (the key).

To be a bit more concrete, here's how we can fetch a vocabulary describing the different kinds of aerobic activities:

Vocabulary vocabulary = ApplicationConnection.GetVocabulary("aerobic-activites");

foreach (KeyValuePair<string, VocabularyItem> item in vocabulary)
{
string key = item.Key;
string displayText = item.Value.DisplayText;
string abbreviation = item.Value.AbbreviationText;
}

If you looked closely at the foreach part, you noticed that item.Value is really a VocabularyItem, and that's where DisplayText and AbbreviationText came from.

Here's what I got back from executing that code:

Key DisplayText AbbreviationText
run running run
jog jogging jog
hike hiking hike
bike bicycling bike
spin spinning spin
swim swimming swim
walk walking walk
row rowing row

In addition to the information on a specific vocabulary item, there is some general information on the Vocabulary type.

Culture

The culture tells you the culture of the vocabulary. When you fetch a vocabulary, it comes back for the current Culture, and you can control whether there is a fallback to other culture's if there's not one specific to the current culture. Note that the key is culture-invariant, and therefore may not make sense to users in your current culture.

Family

Family defines the overall source for the vocabulary. If it's from HL7, this would presumably be for that. Or perhaps it might say "AMA", or something else. The family lets you understand where the vocabulary came from. If it's something the HealthVault team defined, the family is "wc".

Name

The name of the vocabulary. Together with the family, that should fully identify the source

Version

A string defining a version of the vocabulary.

Coded and Codable Values

How is a reference to a specific vocabulary item stored in HealthVault?

It is done through the CodedValue type. A quick look at the type shows the following properties:

  • Family
  • Value
  • Version
  • VocabularyName

As you probably figured out, Family, Version, and VocabularyName are used to indicate what vocabulary we are using, and Value is used to store the key for the specific vocabulary item. An application can figure out exactly you mean by looking at the CodedValue.

That works well when we have a vocabulary and we know exactly what code to use. But there are two more scenarios we need to support.

First, we might have an item to store, and it's either not in the vocabulary or we don't know what the appropriate vocabulary is. I might want to store my juggling exercise data, but that's not part of aerobic-activities vocabulary. Or, I'm adding the over-the-counter allergy medicine I take, and all I know is the name on the box.

In other words, sometimes we have very precise information, and sometimes it's less precise, but in both cases the platform and the applications that use the platform need to handle it well.

The second scenario - and this one's rarer - is that there are times where a single entry might need to store multiple values.

Both of these scenarios are supported through the CodableValue type, and that's the type that you'll see used in the data types. It provides a Text property and a way of having multiple coded values.

CodableValue.Text is always set for all codable values, and that's the one that you display when you're showing that value to a user. Any underlying CodedValue instances are of a "more information" category - the application can use them to find out more information about that Text.

All Vocabularies

You can fetch the list of all vocabularies with the following:

ReadOnlyCollection<VocabularyKey> keys = ApplicationConnection.GetVocabularyKeys();

Why would you want to do this? Well, it's useful for browsing to see if the vocabularly that you want is currently defined in the system. If there's one that's not in the system, you can request a new vocabulary using the same process you'd use to request a new data type.

Best Practices

  1. Always set the Text property on the Codable value, even if there are CodedValues underneath.
  2. Always display the Text property as the high-level summary of the CodableValue.
  3. Be thoughtful about displaying the key to a vocabulary item to the user. It might be a number - in which case it is probably okay - but it also might be a string that only works well in one locale.

Translation

One of the nice things about vocabularies is that there is are so many to choose from. There are several different coding systems - and therefore possible vocabularies - for medication. We've talked about providing translation services between different vocabularies - so that an application could easily get hte information in the vocabulary it understands best.

Would you find that to be a useful feature?