|
12 min de lecture
|

Terminology, c'est amusant : CodeableConcept.coding[]

Résumé de l'article

CodeableConcept est un protocole qui comble un fossé : le producteur connaît la réalité, mais pas les lecteurs ; chaque consommateur connaît son cas d'utilisation, mais pas les choix du producteur. C'est pourquoi un seul champ contient plusieurs codes, pourquoi aucun d'eux n'est « principal », et pourquoi l'ordre ne signifie rien. Règles du producteur : capturez tout ce que vous seul savez — le code le plus précis, les codes dans des systèmes alternatifs, le texte, userSelected, meta.profile. Règles du consommateur : l'interprétation est votre responsabilité — classifiez votre consommation (appartenance ? projection ? transit ?), testez l'appartenance par subsomption, jamais par .first().

Résumer cet article avec :
ChatGPTPerplexityClaudeGrok

Retirez d'une ressource FHIR ses éléments codés et il ne reste que la plomberie : identifiants, références, dates, statuts. Ce qu'est la condition, ce qui a été observé, ce qui a été prescrit — le sens des données de santé réside dans la terminologie. La structure vous indique qu'une Condition existe et à qui elle appartient ; les codes vous disent ce qu'elle est réellement.

Et presque partout où le sens apparaît dans FHIR, il apparaît sous la forme d'un seul type de données : CodeableConcept — Condition.code, Observation.code, Procedure.code, MedicationRequest.medication, AllergyIntolerance.code. Apprenez à lire correctement ce seul type et vous aurez appris à lire la sémantique de FHIR ; lisez-le incorrectement et la structure reste parfaitement valide tandis que le sens s'efface silencieusement.

Alors — comment lire et interpréter CodeableConcept correctement ? Par exemple, si j'examine un diagnostic en SNOMED CT ?

La première idée est d'utiliser code.coding.where(system='...snomed...').code.first(). Mais ce n'est pas correct. C'est ce que j'ai appris lors d'une réunion du groupe de travail HL7 FHIR-I de Lloyd McKenzie.

Il peut absolument y avoir deux ou trois codes SNOMED, et vous devez le prendre en charge.

Pour comprendre pourquoi — et quoi faire à la place — il est utile de prendre du recul et de voir les données codées comme une conversation entre deux parties qui ne se rencontrent jamais : celui qui écrit le code et celui qui le lit.

Ce que signifie coder des données

Coder, c'est remplacer le sens par un pointeur vers un dictionnaire partagé : un concept tiré d'un système de codes. Un code sans système est dénué de sens — la paire (système, code) est l'unité de sens. L'objectif est que deux systèmes qui ne savent rien l'un de l'autre comprennent les données de la même façon.

Trois éléments compliquent immédiatement le tableau :

Les concepts ont une granularité. Ils vivent dans des hiérarchies : « diabète » ⊃ « diabète de type 2 » ⊃ « diabète de type 2, bien contrôlé ». Choisir un niveau est une décision sur la quantité d'information capturée — et sur ce qu'on perd.

Les systèmes de codes sont construits sur des principes différents. La CIM est une classification : son objectif est de ranger chaque cas dans des compartiments mutuellement exclusifs sans reste (pour les statistiques et la facturation) — d'où les catégories « autre » et « non précisé ». Un cas → exactement un compartiment. SNOMED CT est une ontologie : son objectif est de décrire la réalité clinique — hiérarchies à parents multiples, définitions formelles, expressions composables. Un cas → une description aussi précise que nécessaire. Ces deux systèmes répondent à des questions différentes : la CIM — « dans quel compartiment pour le rapport », SNOMED — « qu'est-ce que c'est ». La correspondance entre eux est intrinsèquement avec perte et de type plusieurs-à-plusieurs.

Parfois le concept n'existe pas — mais vous pouvez le construire. C'est la post-coordination : la grammaire du système de codes vous permet de composer un concept à partir de concepts existants. L'expression SNOMED CT 81745001:272741003=7771000 — « œil : latéralité = gauche ». L'expression va, entière, dans un seul Coding.code — la spécification est explicite sur le fait qu'une « expression définie par le système de codes est toujours considérée comme un "code" et représentée comme telle » :

{
  "system": "http://snomed.info/sct",
  "code": "128045006:{363698007=56459004}"
}

Remarque : le résultat est tout de même un seul code. Ce ne sont pas deux codages « œil » + « gauche » dans un tableau — nous verrons ci-dessous pourquoi c'est interdit.

Ce qu'est réellement CodeableConcept

CodeableConcept porte un seul sens et contient ses représentations dans un tableau coding ainsi qu'un text lisible par un humain.

{
  "coding": [
    { "system": "http://loinc.org",      "code": "8867-4",    "display": "Heart rate" },
    { "system": "http://snomed.info/sct", "code": "364075005", "display": "Heart Rate" }
  ],
  "text": "Heart rate"
}

L'idée clé : plusieurs codages ne sont pas plusieurs concepts. Un concept, écrit dans différentes « langues » pour différents destinataires. Un code CIM-10 pour le payeur, un code SNOMED CT pour le système clinique, un code local pour le débogage — tout dans un seul champ.

Pourquoi un seul champ aurait-il besoin de tout cela ? En raison de qui se trouve à chaque extrémité.

Le fossé : un seul scripteur, de nombreux lecteurs

Voici l'asymétrie centrale de l'échange de données codées : le producteur écrit une seule fois — les consommateurs sont nombreux, et ils veulent des choses différentes. Le régulateur veut des compartiments grossiers pour un rapport, le chercheur veut un maximum de détails, la facturation veut la CIM, l'aide à la décision clinique veut SNOMED. Lloyd McKenzie, lors de la session FHIR-I :

Il peut absolument y avoir deux ou trois codes SNOMED, et vous devez le prendre en charge. Parce que vous allez vous trouver dans des situations où quelqu'un a un guide d'implémentation qui dit que je capture ceci avec uniquement des codes de haut niveau... J'ai besoin que vous m'envoyiez ce code pour que je puisse faire ce rapport gouvernemental. Et puis vous avez un autre cas d'utilisation, qui est que je veux savoir exactement quel type de cancer c'était, je veux savoir quel est son stade, je veux savoir s'il s'agit d'une récidive ou non. Et vous avez deux systèmes différents qui veulent tous deux des informations légèrement différentes, et la seule façon de le faire est d'envoyer les deux codes.

Et le producteur ne peut pas en choisir un « pour tout le monde » :

Quand vous créez une instance, vous la créez pour tous les destinataires — nous produisons la même chose pour tout le monde. Une telle interdiction n'est donc pas raisonnable.

Cette asymétrie explique toutes les propriétés « étranges » de CodeableConcept :

Il n'y a pas de code « principal » — parce que « principal » est une propriété de la paire (données, consommateur), et non des données. Le producteur n'a pas le droit de décider pour tous les lecteurs. J'ai demandé directement à Lloyd s'il existait un indicateur pour le code le plus précis :

Nous avons un élément de base qui vous permet de dire que c'est le code que l'utilisateur a sélectionné. Mais dans la situation où vous faites de la post-codification, il n'existe pas de mécanisme pour indiquer lequel est le plus spécifique. Et il peut exister des circonstances où ils sont également spécifiques, mais où ils vous disent simplement des choses différentes.

Un seul code « le plus spécifique » n'existe souvent même pas :

Les deux ont plus de détails que le code de base, mais vous ne pouvez pas en marquer un comme étant le plus détaillé, et il n'existe pas de code dans SNOMED pour la pression artérielle systolique de l'artère digitale droite en position assise. Ça n'existe pas.

L'ordre ne signifie rien — la version CI de la spécification le stipule normativement : « L'ordre des codages est indéfini et NE DOIT PAS être utilisé pour inférer un sens. » CodeableConcept.coding n'a pas d'orderMeaning (fil Zulip). Donc .first() ne récupère pas le code principal — il récupère un code aléatoire.

Les codes supplémentaires ne sont pas des synonymes. Elliot Silver, lors de la même réunion, a tendu exactement ce piège :

disons que nous avons votre CodeableConcept codé avec cancer du poumon, cancer, et maladies du poumon. Mon système ne reconnaît pas cancer du poumon. Il reconnaît maladies du poumon et il reconnaît cancers... Je vais voir une correspondance pour maladies du poumon là-dedans, et c'est celui que je vais conserver. Et je vais supposer que tout le reste là-dedans est un synonyme...

La correction de Lloyd est tout le propos :

Il encode un concept, mais il n'exprime pas nécessairement la même information avec chacun... un code transmet un aspect ou un ensemble d'informations que l'autre ne transmet pas, et vice versa. C'est ce qui se passe avec les systèmes de codes : ils ont différents niveaux de précision et différentes capacités d'expressivité.

Ainsi, lorsque le système d'Elliot sélectionne silencieusement maladie du poumon et rejette cancer du poumon comme « synonyme », c'est « maladie du poumon » qui se retrouve dans la base de données analytique au lieu de « cancer du poumon », et personne ne le remarque.

Le fossé s'étend dans le temps. Le consommateur d'aujourd'hui ne connaît pas les codes de demain dans le même champ. Lloyd :

les destinataires qui n'avaient peut-être eu à traiter qu'un ou deux codes initialement pourraient se retrouver face à 7 ou 8 codes éventuellement. En tant que consommateur, vous ne pouvez pas présumer que ce que vous voyez aujourd'hui sera la même chose à l'avenir.

Pourquoi FHIR a-t-il choisi ce modèle ? Grahame Grieve :

l'attente/le désir dans FHIR est que l'information soit robuste dans de multiples environnements en l'absence d'un contexte spécifique avec un accord personnalisé, parce que c'est ainsi que les gens utilisent réellement l'information de toute façon. Cela a un coût, et nous y voilà.

Le coût se répartit de façon asymétrique : le producteur paie peu (mettre tout dans le tableau), le consommateur paie cher (une politique de sélection, un serveur de terminologie, des correspondances). CodeableConcept est, en substance, un protocole pour communiquer par-dessus le fossé : le producteur maximise ses chances d'être compris ; le consommateur est tenu de savoir comment choisir.

Établissons donc les règles pour chaque partie.

La seule règle contraignante qui lie le tableau

Avant les règles — la seule contrainte que la spécification impose sur les codages multiples. Elle a été définie dans le fil Multiple codes in CodeableConcept (#terminology, 113 messages) et lors de la réunion FHIR-I, produisant deux billets JIRA — FHIR-50188 et FHIR-50189 — et une réécriture d'une partie de la spécification.

La spécification publiée (jusqu'à R5) indiquait que les codages « pouvaient avoir une granularité légèrement différente », et ce mot a semé la confusion chez les implémenteurs pendant des années. Rutt Lindström :

La plupart des discussions auxquelles j'ai participé (généralement à propos de Medication.code) se sont épuisées autour du mot « légèrement ». Est-ce que ce qui suit représente une différence légère ou une différence énorme ?

Grahame Grieve a répondu que la règle ne porte pas sur la taille de la différence :

ce qui est légal, c'est n'importe quelle différence de granularité tant que l'intersection n'est pas vide ; la bonne pratique est de ne pas pousser les limites ici, et de faire varier la granularité le moins possible.

« légèrement » a disparu : la version CI indique maintenant « Lorsque plusieurs codes sont présents, l'intersection de leurs sens NE DOIT PAS être vide. (Strictement, sur la base de l'ISO 704, l'intersection de leurs "extensions" n'est pas vide.) »

Valide : LOINC 8867-4 (fréquence cardiaque) + SNOMED CT 364075005 (fréquence cardiaque).

Non valide : LOINC 9279-1 (fréquence respiratoire) + SNOMED CT 364075005 (fréquence cardiaque). Michael Lawley :

il n'existe aucune chose qui soit à la fois une fréquence respiratoire et une fréquence cardiaque — strictement, le bas (⊥) est le concept qui est l'intersection de chaque concept, mais par définition n'a aucune instance.

Remarque : la règle n'est pas vérifiable par machine — c'est une directive, pas un validateur. Et il n'y a pas eu de vote formel lors de la réunion FHIR-I — le quorum a chuté à la fin. L'accord de fond a été atteint ; le texte réécrit de FHIR-50188 a déjà été intégré dans la version CI, tandis que les versions publiées jusqu'à R5 contiennent encore l'ancienne formulation.

Règles pour le producteur

L'asymétrie du producteur : vous êtes le dernier point où la connaissance existe. Le clinicien a vu le patient ; le dispositif a effectué la mesure. Le moment du codage est le moment de contact avec la réalité — après avoir écrit la ressource, la fenêtre se ferme. Tout ce que vous ne capturez pas maintenant est perdu, parce que :

  • Généraliser plus tard est calculable ; spécialiser ne l'est pas. N'importe quel consommateur disposant d'un serveur de terminologie peut remonter « diabète de type 2, bien contrôlé » vers « diabète » ($subsumes, la hiérarchie). La direction inverse est impossible en principe : l'information n'est pas dans les données.
  • La correspondance entre systèmes après coup est une loterie. Les ConceptMaps entre systèmes sont de type plusieurs-à-plusieurs avec des correspondances « plus large / plus étroit / inexact ». Le correspondant en aval ne voit que le code ; vous avez vu le cas. Vous résolvez l'ambiguïté avec la connaissance ; $translate la résout avec une supposition.

D'où la règle fondamentale :

P0. Capturez tout ce que vous seul savez, au moment du codage :

  1. Le code le plus précis que vous pouvez justifier. Personne en aval ne pourra jamais ajouter de la précision.
  2. Les codes dans les systèmes alternatifs que vous connaissez (compartiment CIM et concept SNOMED). Votre choix de compartiment est une connaissance ; une correspondance calculée plus tard est une supposition.
  3. Toujours text — le sens complet en mots. C'est le canal de dernier recours que 100 % des destinataires (y compris les humains) comprennent, et le seul endroit pour préserver les détails qui n'ont pas trouvé leur place dans un code : "text": "Negative for Chlamydia Trachomatis rRNA" à côté d'un codage qui dit simplement « Négatif ».
  4. Marquer la provenance : userSelected = true sur le code qu'un humain a réellement choisi. Dans un tableau où tous les codes sont égaux, il existe une asymétrie d'origine cachée — un code a été sélectionné par une personne qui regardait le patient, les autres ont été dérivés. Cela est indécidable à partir des données après coup. (Mais rappelez-vous : userSelected marque la source, non la granularité.)
  5. Déclarer les règles que vous avez appliquées : meta.profile. Trois codes dans un tableau — est-ce « ce que nous avions à disposition » ou « liaison requise par US Core + code hérité + traduction réglementaire » ? Structurellement indiscernables. La déclaration de profil indique au lecteur quel contrat vous exécutiez — et lui permet de le valider.

Et trois garde-fous contre la distorsion du sens lors de l'empaquetage :

P1. Chaque codage exprime le concept entier à lui seul. Pas des parties, pas des modificateurs. Lloyd, sur l'astuce « œil » + « gauche » (fil) :

Vous ne les interprétez pas en les combinant. Parce que ces codes sont en SNOMED, vous pouvez combiner les concepts par post-coordination : 81745001:272741003=7771000 — « œil:latéralité=gauche ». Il n'y a pas d'élément "modificateur" dans Coding.

Pourquoi c'est la règle numéro un : le consommateur est garanti de prendre un seul code dans le tableau — c'est son algorithme. Si vos codes sont des parties, l'interprétation erronée n'est pas un risque, c'est une certitude.

Et si le système de codes n'a pas de grammaire de post-coordination — par exemple, un code LOINC qui a besoin d'un qualificatif SNOMED — vous ne pouvez pas non plus le simuler avec deux codages, ni inventer un code combiné. Lloyd, répondant exactement à cette question dans le fil Handling post-coordination in CodeableConcept :

Si vous souhaitez envoyer une expression post-coordonnée, le Coding.system doit être un système de codes qui définit la syntaxe de post-coordination et la façon d'interpréter l'expression... Dans votre cas, il n'existe pas de syntaxe publiée par LOINC ou SNOMED pour ce que vous faites, donc vous ne pourriez pas appeler le résultat un code LOINC ou SNOMED... Envoyer un code LOINC avec une extension (ou utiliser les éléments "method" ou d'autres éléments sur Observation) pour transmettre votre qualification sera probablement mieux compris.

Les échappatoires légales se trouvent en dehors de coding[] : une extension pour le qualificatif, des éléments de ressource dédiés (Observation.method, bodySite), ou une ressource liée séparée (Observation.hasMember). La grammaire appartient au système de codes, pas à vous.

P2. Les codes ne doivent pas se contredire — la règle d'intersection non vide ci-dessus. C'est ce qui rend P1 possible : « n'importe quel code est vrai » ne fonctionne que si tous les codes portent sur la même chose.

P3. Restez dans la portée de l'élément, et surveillez la direction de la granularité — surtout sous négation. N'insérez pas une racine de hiérarchie comme SNOMED 138875005 (SNOMED CT Concept) dans Observation.code (c'est FHIR-50189). Et le nouveau texte de la spécification porte un avertissement que l'ancien n'avait pas — la granularité mixte n'est pas seulement peu pratique, elle peut être dangereuse :

une ordonnance pour « APO Amoxicillin 250 mg capsule » (nécessaire pour exécuter l'ordonnance) pourrait également comporter sans risque un codage supplémentaire de « Pénicilline à large spectre » (peut-être nécessaire pour déclencher des protocoles de surveillance des antibiotiques). D'autre part, si une ordonnance disait « Ne pas administrer APO Amoxicillin 250 mg capsule », l'ajout d'une traduction de « Pénicilline à large spectre » pourrait être incorrectement interprété comme une interdiction de toutes les pénicillines à large spectre.

Mêmes deux codes, même intersection non vide — mais formulez l'énoncé en négation et le codage plus large élargit silencieusement l'interdiction. Lorsque l'énoncé est négatif, optez pour la précision.

Règles pour le consommateur

L'asymétrie du consommateur reflète celle du producteur : le producteur connaissait la réalité, mais pas l'application ; vous connaissez l'application — quelle analyse, quelle action, ce que coûte une erreur. Cette connaissance n'est pas dans les données, et vous seul pouvez l'appliquer.

C0. L'interprétation est votre responsabilité, et elle repose sur une politique explicite choisie à l'avance. L'algorithme de Lloyd, tiré du même échange FHIR-I :

La première chose que vous faites est d'écarter tous ceux que vous ne comprenez pas. Idéalement, vous voulez tout, même ce que vous ne savez pas, parce qu'un destinataire en aval pourrait le comprendre. [Si] je ne peux pas interpoler le sens à partir de plusieurs concepts, alors je dois choisir lequel de ces éléments est le plus préféré pour le type d'analyse que je fais. Et vous auriez pris cette décision à l'avance en termes de quelle est ma terminologie la plus préférée.

L'expression clé est à l'avance. La politique de préférence (systèmes → ensembles de valeurs → granularité → userSelectedtext) réside dans votre configuration de correspondance — versionnée et révisée — et non dans une expression FHIRPath au moment de la lecture. .first() est une politique que personne n'a approuvée.

Classifiez d'abord votre consommation

Avant de sélectionner des codes, demandez-vous quelle opération vous effectuez réellement sur le tableau. Il n'existe que quelques classes de consommation, et chacune a sa propre sémantique et son propre risque :

ClasseCodes nécessairesAvec perte ?Risque principal
Test d'appartenance — « est-ce que ça relève du concept X ? » (déclencheur d'aide à la décision clinique, inclusion dans une cohorte)n'importe lequel (∃)nonnégation
Projection — « donnez-moi exactement un code dans le vocabulaire Y » (ETL, FHIR-vers-OMOP, facturation)exactement unouichoisir sans politique
Agrégation — « dans quel compartiment ? » (rapports, statistiques)exactement un compartimentouidouble comptage
Transit — stockage et transfert, passerelletous, y compris les non comprisnon« nettoyer » le tableau
Affichage — montrer à un humainaucun (text)nontexte vide
Inférence — raisonnement par subsomption, fusion de détailstous + serveur de terminologienoncoût

Deux observations découlent de ce tableau.

Premièrement, l'appartenance est la classe la plus sûre — aucune sélection de code, aucune perte : un OU sur le tableau, où les codages supplémentaires ne font qu'aider (plus de représentations → plus de chances d'atteindre votre ensemble de valeurs). Toutes les difficultés de cet article — « quel code est le principal, lequel est le plus précis » — sont des difficultés de la classe projection. La moitié du remède consiste à réaliser que votre tâche est en réalité une appartenance, et que vous pouvez cesser de choisir un code là où vérifier la containance suffit.

Deuxièmement, .first() est une projection réalisée sans politique — la pire classe exécutée de la pire façon.

L'appartenance signifie subsomption, pas égalité

Et ici notre propre P0 revient en jeu : nous avons dit au producteur de coder aussi précisément que possible — donc un consommateur qui teste l'égalité ne trouvera presque rien. Vous cherchez « diabète » (73211009), mais les données disent « diabète de type 2, bien contrôlé », parce que le producteur a honnêtement suivi P0. Égalité → faux → le patient sort de la cohorte. Meilleures sont les données, moins bon est le consommateur naïf.

Le test d'appartenance doit donc être :

∃ coding : subsumes(X, coding)    — « le code est X ou un descendant de X »

Mécaniques, à votre choix : $subsumes pour une vérification ponctuelle ; un ValueSet avec un filtre is-a ou SNOMED ECL << 73211009 plus $expand / $validate-code pour un ensemble matérialisé ; dans OMOP, concept_ancestor — la même fermeture transitive précalculée comme table.

Où ça se brise :

  • La hiérarchie vit à l'intérieur d'un système. Il n'existe pas de subsumes direct (SNOMED-X, code-CIM) — il faut d'abord faire correspondre, puis remonter la hiérarchie, et les pertes des deux étapes se multiplient. Un argument de plus pour P0 : un producteur qui a inclus un code SNOMED vous a donné une entrée dans une bonne hiérarchie.
  • Les hiérarchies ne sont pas équivalentes. Le is-a de SNOMED est une ontologie formelle ; la « hiérarchie » de la CIM est une organisation par chapitres — bien pour les rapports, pas pour la logique clinique. Choisir un système pour l'appartenance = choisir une hiérarchie en qui vous avez confiance.
  • La post-coordination ne correspond jamais par égalité — mais la subsomption basée sur ECL la capture, si votre serveur de terminologie gère les expressions.
  • La négation amplifie encore : un critère d'exclusion par subsomption sur un concept large exclut tous ses descendants — rappelez-vous l'amoxicilline. Inclure par un ancre large est sûr ; exclure par une ancre large est dangereux.

Encore une chose que $translate ne fera pas pour vous — la généralisation. Michael Lawley, répondant à Lloyd :

Il n'y a rien dans la définition de $translate qui suggère qu'il fait quoi que ce soit de « sémantique »... $translate de B devrait-il retourner à la fois X et Y ? C'est susceptible de mener à un comportement très bruyant et ingérable.

Si vous avez besoin de concepts ancêtres, c'est un ensemble de valeurs avec un filtre generalizes (ou ECL) — pas un appel à $translate.

Lisez à travers le profil — et l'écart de projection

Si le producteur a déclaré meta.profile, utilisez-le : un profil réduit « tableau inconnu » à « minimum garanti plus extras possibles ». Une liaison requise vous indique qu'au moins un codage provient d'un ensemble de valeurs connu ; le découpage vous indique que le tableau a des rôles nommés (« le code LOINC obligatoire » dans les Vital Signs) reconnaissables par des discriminateurs.

Notez toutefois ce qui manque dans l'outillage. Le profil décrit une projection — le découpage partitionne coding[] en parties nommées — mais il n'existe pas d'opération standard pour l'exécuter. Les validateurs résolvent les tranches en interne (ils le doivent, pour vérifier les cardinalités) et jettent l'affectation, ne retournant que oui/non. Il n'existe pas de $project(profile) qui retourne la ressource vue à travers le profil, chaque codage annoté avec son nom de tranche. Aujourd'hui, vous réimplémentez les discriminateurs à la main (coding.where(memberOf('http://...vs'))) ou encodez la politique de sélection dans une ViewDefinition SQL on FHIR. Un profil est un contrat ; la validation est la vérification du contrat côté producteur ; la projection serait l'exécution du contrat côté consommateur — les deux premières existent dans la spécification, la troisième pas encore.

Les garde-fous restants

C1. La structure du tableau ne porte aucun sens. L'ordre, le nombre, la composition — rien de tout cela n'est un signal. Le tableau reflète l'ensemble de consommateurs du producteur, pas vos priorités.

C2. Choisir un code est une perte délibérée des autres. Chaque codage peut porter des détails que ses voisins n'ont pas (cancer du poumon ≠ maladie du poumon). En prendre un — sachez ce que vous avez rejeté. Et conservez les codes que vous ne comprenez pas lorsque vous transmettez les données : vous n'êtes pas le dernier lecteur.

C3. Connaissez votre direction d'erreur sûre. Pour les actions positives, interpréter d'après le code plus large est conservateur et sûr ; pour les actions négatives (interdictions, exclusions, filtres « tous sauf ») — uniquement le code étroit, sinon vous élargissez l'interdiction.

C4. La branche « rien compris » doit exister et être significative. Longueur de tableau inconnue, systèmes inconnus, nouveaux codes demain. Aucune correspondance → text → humain → refus explicite. Pas une exception et pas un saut silencieux — sinon .first() s'insinue à nouveau comme « au moins quelque chose ».

En conclusion

CodeableConcept est un protocole qui comble le fossé producteur/consommateur. Le devoir fondamental du producteur — capturer la connaissance qui n'existe qu'au moment du codage : le code le plus précis, les codes dans les systèmes alternatifs, le texte complet, la provenance, le profil. Chacun d'eux répond à une question d'un consommateur qui serait autrement sans réponse : « quelle précision ? », « quel compartiment ? », « qu'est-ce que ça signifie en mots ? », « quel code l'humain a-t-il choisi ? », « quelles règles étaient en vigueur ? ».

Le devoir fondamental du consommateur — appliquer la connaissance qui n'existe que de son côté : le cas d'utilisation. Classifiez la consommation, testez l'appartenance par subsomption plutôt que par égalité, projetez à travers les profils là où ils existent, et choisissez les codes selon une politique explicite — jamais par position dans le tableau.

Terminology, c'est amusant, comme aime à dire Lloyd McKenzie. Surtout quand l'amusement arrive sous la forme du septième code dans un tableau pour lequel votre analyseur syntaxique n'a pas été conçu.

Sources

Fils chat.fhir.org (connexion Zulip requise) :

HL7 JIRA :

  • FHIR-50188 — nouveau libellé pour les codages multiples dans CodeableConcept.
  • FHIR-50189 — portée/granularité pour Observation.code.

Spécification FHIR :

  • CodeableConcept, version CI — la section « Multiple Codings » réécrite avec la règle d'intersection et l'avertissement sur la négation.
  • CodeableConcept, R5 — l'ancienne formulation « granularité légèrement différente », pour comparaison.
Partager cet article
Comments
Comments
Sign in
Loading comments...
Subscribe to our blog

Get the latest articles on FHIR, interoperability, and healthcare IT.