This wiki has undergone a migration to Confluence found Here
<meta name="googlebot" content="noindex">

Difference between revisions of "FHIR conformance and cardinality"

From HL7Wiki
Jump to navigation Jump to search
(Created page with "{{FHIR Discussion Page}} Category:Active FHIR Discussion Back to FHIR = Introduction = As of v0.02, FHIR has the following fields that describe the rules around whether...")
 
Line 1: Line 1:
 
{{FHIR Discussion Page}}
 
{{FHIR Discussion Page}}
 
[[Category:Active FHIR Discussion]]
 
[[Category:Active FHIR Discussion]]
Back to [[FHIR]]
 
  
 
= Introduction =
 
= Introduction =
Line 49: Line 48:
 
** gg: no? So far, the cases in resources haven't often been as simple as (a xor b) - they've been more complicated.
 
** gg: no? So far, the cases in resources haven't often been as simple as (a xor b) - they've been more complicated.
 
** gg: todo - gather a list of observed cases for conditional so far
 
** gg: todo - gather a list of observed cases for conditional so far
 +
 +
Lloyd
 +
*'''Unstated'''
 +
** I don't think we should allow "conformance unstated".  For one thing, the behavior will be different in resource definitions vs. profiles.  In profiles, when you leave something out, it remains the same.  In profiles, it would become optional.  I'd also question the situation where we should have something that's structural with no meaning in a resource.  Can you give examples?
 +
*'''Conditions'''
 +
** Conditional is useful as a flag.  It's important to know that there are elements that may have tighter conformance expectations than they first appear.  However, it's orthogonal with the other cardinalities.  An element could have a base conformance of "Required" or even "Mandatory" and still have a conditional flag on it.  Therefore, suggest adding this as a separate flag on the element.  Ideally we could derive this by parsing the xPaths, but for now, manual maintenance is most appropriate.
 +
** Conditions should be melded into our general idea of Invariants.  There's no difference between them.  The things you'd want as a condition are a subset of the invariants and we don't want to provide two different ways to say the same thing.
 +
** Conditions as only text is not terribly useful.  Conditions should be capture formally so they can be tested as much as possible, though obviously some conditions may not be testable in a given formal language and some authors may not be capable of using the chosen language.  So capture constraints as XPath + human readable text, where the text is a positive assertion of the condition.  That will allow us to create Schematron (and maybe eventually Schema 1.1) rules.
 +
** Conditions/Invariants should be captured on the element in whose context they apply.  This is generally the common parent of all nodes influenced by the constraint.  So if you have a constraint that at least one of Foo and Bar must be present, the constraint lives on the parent of Foo and Bar, not on the Foo or Bar elements themselves (though the Conditional flag would of course be set on Foo and Bar)
 +
** We should think about what the rules are for how deep conditions can be asserted.  I think conditions should only be allowed to hold within your current resource, not across profiles.  However, I can see some situations where constraint across resources might be necessary.  Perhaps require that if you want to enforce a constraint on another resource, it's done by asserting a profile on that resource, not reaching inside the resource?  That simplifies maintenance.  It also avoids worrying about setting the Conditional flag on content where the condition is declared in a different resource from the element.
 +
** I think attempting to model out a subset of formal constraints has limited value.  We support choices of types within an element.  Choices of types across elements gets very ugly very quickly and also places constraints on order of appearance.  I think just using constraints is more appropriate.
 +
* '''Mandatory'''
 +
** In v3, we've always asserted that isMandatory="true" implies that conformance="Required" and minimumCardinality >= 1.  You're breaking that here.  You're asserting that "dataAbsentReason" can be constrained away in circumstances where minimumCardinality is still 0.  I'd like to assert that it's actually orthogonal.  There are elements where dataAbsentReason is unnecessary overhead.  And the cardinality and conformance expectations for those elements could be pretty much anything.
 +
** The name is poor.  First, it doesn't have the same semantic as "mandatory" in v3, which will confuse people.  Second, most people new to HL7 mentally interpret mandatory as the same as required, because that's what it means in standard english.  Suggest being explicit and saying something like "darProhibited".  Obviously this will require someone to look at the definition to understand that "dar" is the abbreviation for "dataAbsentReason", but that's a quick thing.  And once done, it's intuitive.
 +
*'''Prohibited'''
 +
**There are situations where a given implementer *cannot* accept data they weren't expecting.  Perhaps there's a regulatory need to share and expose whatever they're given or something.  So the solution is to reject instances that contain data they don't support.  We need to have a way to expose this behavior in FHIR, even if it's problematic from an interoperability perspective.  (See [[FHIR Conformance Levels Issue Page]]
 +
**Prohibited should mean "I'm going to raise an error if you send me the element at all".  Schema equivalent to maxOccurs="0"
 +
**This qualifies in the 80% because every implementer needs to know how to handle this situation, even if (hopefully) very few implementers declare profiles that use it.
 +
*'''Additional'''
 +
**V2 and V3 also have the concept of "Required for Sender" and "Required for Receiver".  These are used when creating a resource definition or a profile intended to define conformance from both a sending and a receiving perspective.  In some cases you want to say "You're non-conformant if you aren't capable of sending this element, but it's ok for receivers to ignore"; or "It's ok if you don't support sending this element, but receivers must be capable of processing it if sent".
 +
**These are definitely edge cases, but again they probably fall in the 80% because implementers need to know what to do if they encounter these concepts in the wild.

Revision as of 14:12, 27 May 2012

Introduction

As of v0.02, FHIR has the following fields that describe the rules around whether an element can or must be present or not:

  • Cardinality
  • Conformance: Mandatory | Required | Conditional | Optional | Prohibited.
  • condition field - must be present if Conformance is conditional

The interplay between these fields creates some interesting dynamics, and there's things you want to say that you can't, things you can say that don't make sense, and things that aren't clear. This page considers how to improve this.

Note that there's three separate issues at play here: how resources and profiles are authored, how they are presented, and how they are properly understood. Ideally, the last two should be the same, but not all presentation formats are capable of that. XML schema, for instance, knows only cardinality.

Cardinality

For authoring a resource, the only allowed min cardinality is 0 or 1, and the only allowed max cardinality is 1 or *. Other values are not allowed (build fails). This is equivalent to

  • must you have an element present
  • are you allowed to have more than one element present (i.e. implementations use some kind of list for the element)

In a profile, you can specify any combination of cardinalities, as long as min <= max, and min >= 0.

Cardinality is authored in the spreadsheets by entering the M..N values directly into the column entitled "Cardinality"

Conformance

Conformance is edited in the spreadsheet by entering a code into the "Conformance" column. The following codes are allowed:

  • Unstated - this element doesn't need to have a conformance flag on it. This means that the element is there fore purely structural reasons, has no inherent meaning, and is optional
  • Mandatory - if this element is present, it may not have a dataAbsentReason on it (it's quite common to have min cardinality = 0, but to be mandatory)
  • Conditional - the element has a minimum cardinality of 0. If the condition is true, then it must be present (or at least one must be present), and it cannot have a dataAbsentReason on it
  • Optional - if the element is present, it may have a dataAbsentReason on it
  • Prohibited - (only in a profile) if the element is present, it must have a dataAbsentReason on it. (when would you use this? -when the min cardinality of the content you are profiling is 1, and it is optional, and you don't want to use it. This is an edge case. - May be appropriate to remove prohibited?)

Condition

If the conformance type is conditional, then this is a human (english only in resources themselves) expression of the rules associated with the conditionality.

Problems

Enter your problems with this content here.

Grahame

  • should deprecate prohibited? the case it represents is really very edge case
  • do you ever want conditional to only refer to the cardinality, and not the dataAbsentReason as well?
  • mandatory has an overlaid meaning. Perhaps better names would be: Unstated | NoAbsent | MaybeAbsent | MustBeAbsent?
  • conditional is different - it applies to the cardinality as well as the dataAbsentReason. Should drop it, and be more explicit?
  • related problem: is there mileage in being explicit about co-occurent constraints and model choice directly?
    • gg: no? So far, the cases in resources haven't often been as simple as (a xor b) - they've been more complicated.
    • gg: todo - gather a list of observed cases for conditional so far

Lloyd

  • Unstated
    • I don't think we should allow "conformance unstated". For one thing, the behavior will be different in resource definitions vs. profiles. In profiles, when you leave something out, it remains the same. In profiles, it would become optional. I'd also question the situation where we should have something that's structural with no meaning in a resource. Can you give examples?
  • Conditions
    • Conditional is useful as a flag. It's important to know that there are elements that may have tighter conformance expectations than they first appear. However, it's orthogonal with the other cardinalities. An element could have a base conformance of "Required" or even "Mandatory" and still have a conditional flag on it. Therefore, suggest adding this as a separate flag on the element. Ideally we could derive this by parsing the xPaths, but for now, manual maintenance is most appropriate.
    • Conditions should be melded into our general idea of Invariants. There's no difference between them. The things you'd want as a condition are a subset of the invariants and we don't want to provide two different ways to say the same thing.
    • Conditions as only text is not terribly useful. Conditions should be capture formally so they can be tested as much as possible, though obviously some conditions may not be testable in a given formal language and some authors may not be capable of using the chosen language. So capture constraints as XPath + human readable text, where the text is a positive assertion of the condition. That will allow us to create Schematron (and maybe eventually Schema 1.1) rules.
    • Conditions/Invariants should be captured on the element in whose context they apply. This is generally the common parent of all nodes influenced by the constraint. So if you have a constraint that at least one of Foo and Bar must be present, the constraint lives on the parent of Foo and Bar, not on the Foo or Bar elements themselves (though the Conditional flag would of course be set on Foo and Bar)
    • We should think about what the rules are for how deep conditions can be asserted. I think conditions should only be allowed to hold within your current resource, not across profiles. However, I can see some situations where constraint across resources might be necessary. Perhaps require that if you want to enforce a constraint on another resource, it's done by asserting a profile on that resource, not reaching inside the resource? That simplifies maintenance. It also avoids worrying about setting the Conditional flag on content where the condition is declared in a different resource from the element.
    • I think attempting to model out a subset of formal constraints has limited value. We support choices of types within an element. Choices of types across elements gets very ugly very quickly and also places constraints on order of appearance. I think just using constraints is more appropriate.
  • Mandatory
    • In v3, we've always asserted that isMandatory="true" implies that conformance="Required" and minimumCardinality >= 1. You're breaking that here. You're asserting that "dataAbsentReason" can be constrained away in circumstances where minimumCardinality is still 0. I'd like to assert that it's actually orthogonal. There are elements where dataAbsentReason is unnecessary overhead. And the cardinality and conformance expectations for those elements could be pretty much anything.
    • The name is poor. First, it doesn't have the same semantic as "mandatory" in v3, which will confuse people. Second, most people new to HL7 mentally interpret mandatory as the same as required, because that's what it means in standard english. Suggest being explicit and saying something like "darProhibited". Obviously this will require someone to look at the definition to understand that "dar" is the abbreviation for "dataAbsentReason", but that's a quick thing. And once done, it's intuitive.
  • Prohibited
    • There are situations where a given implementer *cannot* accept data they weren't expecting. Perhaps there's a regulatory need to share and expose whatever they're given or something. So the solution is to reject instances that contain data they don't support. We need to have a way to expose this behavior in FHIR, even if it's problematic from an interoperability perspective. (See FHIR Conformance Levels Issue Page
    • Prohibited should mean "I'm going to raise an error if you send me the element at all". Schema equivalent to maxOccurs="0"
    • This qualifies in the 80% because every implementer needs to know how to handle this situation, even if (hopefully) very few implementers declare profiles that use it.
  • Additional
    • V2 and V3 also have the concept of "Required for Sender" and "Required for Receiver". These are used when creating a resource definition or a profile intended to define conformance from both a sending and a receiving perspective. In some cases you want to say "You're non-conformant if you aren't capable of sending this element, but it's ok for receivers to ignore"; or "It's ok if you don't support sending this element, but receivers must be capable of processing it if sent".
    • These are definitely edge cases, but again they probably fall in the 80% because implementers need to know what to do if they encounter these concepts in the wild.