Good DMN Begins with Datatype Assignment

In my DMN Method and Style training, we cover a lot of advanced topics, including calendar arithmetic, iteration, filters, and data validation. But I have found that problems in students' certification exercises more often relate to something much more basic, which we discuss at the very beginning of the course: assignment and naming of datatypes. Actually, the runtime engine often does not care whether you've assigned some decision to a datatype or not. But I care. I insist that students properly assign datatypes to all variables in the model, not just decisions and input data, but BKMs, context entries, and function parameters as well. In this post, we'll discuss why that's important and some basic points to keep in mind.

Returning the correct output on execution of your DMN model is a must, obviously. But equally important, in my view, is transparency of your logic. It should be readily understandable by any other modeler who knows DMN, and datatype assignment plays a big part in that. Moreover, in practice incorrect datatype assignment often leads to incorrect decision logic. So my "methodology", if you want to call it that, for good DMN modeling starts with datatype assignment.

DMN's expression language FEEL defines a relatively short list of base types: Text, Number, Boolean, plus a few related to dates, times, and durations. If you want to assign constraints such as a numeric range or enumeration of allowed values, or define the variable as a structure containing components, you need to define a named custom type, or item definition. And if the variable is a list of items of the same base type or item definition, its type is defined as a Collection of the item type.

The DMN ribbon in the Trisotech Decision Modeler lists all the types defined in the model, and this list can be quite long. You just need to name and assign them properly. Here are a few things to keep in mind:

1. Assign types to all model variables.

This includes not only decisions and input data, but BKMs, decision services, context entries, and BKM parameters. For DRD elements, the tool provides a datatype overlay that lets you see in the diagram their assigned type, so you don't miss any.

2. A variable consistent with a base type without constraints should be assigned to the base type, not an item definition.

In other words, don't create an item definition when the base type will do. An exception to this rule is when the value has a special meaning. For example, I often use the item definition tPercent for a number interpreted as a percent.

3. Variables sharing the same base type and constraints should use the same item definition.

For example, if a model contains multiple variables defined as positive numbers, all should use the same item definition, such as tPositiveNumber, not a separate item definition for each variable.

4. The type definition must be consistent with the variable value.

This is fundamental, but not always remembered. I sometimes see a decision defined as type Number contain logic that returns a structure or a date, or a decision defined as type Text with logic that returns a Collection of Text. Errors like these defeat transparency and usually lead to the model logic going off the rails.

5. The type name should suggest the type definition.

Moreover, the variable name should also suggest the type. These rules are violated far more often than I'd like. For example, the variable Age suggests a Number, so its type should not be a date or a duration. A plural name suggests a collection, so don't use this for a structure that is not a collection. The type name tRiskScore suggests a Number, so don't use it for a decision that returns a category, which is enumerated Text. In that case, call it tRiskCategory. Making variable and type names consistent with the type definition is key to logic transparency.

6. If a decision returns the value of an invoked BKM, the decision and BKM must have the same type.

This seems obvious, but students sometimes feel obligated to give each variable its own item definition. So this is a special case of item #3 above.

7. A Structure is not the same as a Collection.

I was a little taken aback that some business users are confused by this. A structure means the variable contains attributes called components. For example, the variable Customer (structured type tCustomer) might have components id, name, and email, each referenced by name:, etc. Each component may contain a value or may itself contain other components. In contrast, a Collection is a list of items of the same type. For example, the variable Customer ids (type Collection of Text) is a list of id values. List items don't have individual names, but are referenced by position: Customer ids[1] references the first id on the list. A plural name typically implies a Collection, so it is best not to use a plural name for a structure.

8. The type of a table is a Collection of the row type, which is a structure, one component per table column.

A table is a Collection of rows, where each row is the same structured type. Table variables play an important role in DMN. When a variable is a table, you should first define the row type, a data structure with a component for each table column. Then the table type is a Collection of that type. So if Customer Table is type Collection of tCustomer, then Customer Table[1] refers to the first row of the table, the first Customer, and Customer refers to the id column of the table, type Collection of Text. If the variable Order represents a list of order items, it should be named type Collection of tOrderItem, where tOrderItem contains one component per table column. Naming the row type tOrder would not be correct, since Order refers to the collection.

9. Assigning a variable to a type does not transform the value to the type.

This relates to rules 4 and 5 above. If the decision Borrower Risk returns a Number, assigning it to tRiskCategory does not turn that Number to an enumerated Text value. Type assignments are not magic! They describe the modeler's understanding of the data, but they don't change the data. To change Borrower Risk from a Number to a category, you need another decision - typically a decision table. Similarly, type assignment cannot change an item to a list or vice versa. Only decision logic can change the actual datatype.

On the Trisotech platform, proper type assignment is key to another aid to modelers, the FEEL Expression Editor. As you enter a literal expression, the code completion feature of the editor continuously suggests variables allowed at that point by the FEEL syntax. This is especially helpful with structured variables, where the allowed variables often are the names of components. Clicking on a suggestion enters the variable in the expression, letting you work faster and decreasing the likelihood of typos. This is possible only when the variables have been properly assigned datatypes.