Using Decision Services

In recent posts I reviewed the use and benefits of BKMs and contexts for DMN modelers and stakeholders. This time we'll continue that theme with an explanation of another of DMN's woefully underutilized features, decision services.

The introduction of decision service as a formal element in DMN came about in a surprising way. The spec's only real example of a decision model, a lending decision, featured a DRD meant to be executed in two or three steps. With reference to the diagram below, depending on the outcome of the decision Strategy, the decision Routing would be executed, and based on its outcome, a human decision, Adjudication, might be required.

While DRDs meant to be executed in multiple steps are technically allowed, it's rare to see them. One reason is that a DMN model meant to be executed all at once is instantly deployable as a REST microservice. In other words, a DRD containing no human decisions and in which all the input data is available up front implicitly defines a stateless decision service. In fact, the Trisotech tool allows you to publish such a DMN model as an executable cloud service in one mouse click.

However, the Lending example in the DMN spec was not meant to be executed all at once. The input data Bureau data, presumably because obtaining it incurs a cost, is not available up front, since depending on the outcome of Strategy it might not be needed. And the human decision Adjudication is only performed if Routing cannot make an automated determination.

None of that is obvious from the DRD, but this DRD is not meant to stand alone. It is meant to be paired with a process model - a decision flow - that executes the decisions Strategy, Routing, and Adjudication in the proper sequence and gathers the needed input data only when necessary. Putting aside the human decision, what the decision tasks in that process invoke are two decision services, one with Strategy and Bureau call type as the output and the other with Routing as the output. The original idea was to define the services by drawing a rounded rectangle enclosing the decisions in each one. Information requirements going into that rectangle would identify the service's input parameters. In practice, defining the service boundary this way requires a polygon with many twists and turns. Note that some decisions, like Application risk score and Required monthly installment, are included in both services. That means these polygons could possibly overlap, so a single decision could be enclosed by more than one.

Defining decision service boundaries in this way isn't really practical. If you need to extract a portion of a DRD as a decision service, Trisotech just asks, what are the output decisions - there could be more than one - and the encapsulated decisions, and the tool deduces the parameters. Once defined in this way, we can represent each decision service as its own separate DRD, using the expanded decision service shape, a rounded rectangle with a horizontal dividing line. Decisions above the line are output decisions, those below the line are encapsulated decisions, and information requirements from outside the service shape are the service input parameters. The three dots below the decision name means that additional details - such as BKM invocations - are not shown in the diagram.

Although this was how decision services found their way into DMN, it is not their typical use. Apart from the "whole model" service implied by any stateless decision model, the most prevalent use of decision services involves execution by another DMN element: a decision, BKM, or decision service. Like BKMs, decision services are decision logic modeled as a function, meaning they are invoked by passing in values for their parameters and receiving back values of the output decisions.

The expanded decision service shapes shown above are used to define the logic of a decision service, typically in its own DRD. To invoke a decision service within a DMN model, the invoking DRD contains the collapsed decision service shape, a small rounded rectangle with a thick border and a plus sign at bottom center. Like a BKM, the collapsed decision service is connected to the invoking element with a knowledge requirement, the dashed arrow. Also like a BKM, a collapsed decision service is opaque: You cannot see the logic inside it. Instead, it is hyperlinked in the tool to the expanded service DRD.

The benefits of using decision services in a decision model closely parallel the benefits of using BKMs, including business-friendliness, logic reuse, and delegated implementation.

The business-friendliness benefit arises because decision services do not have BKMs' constraint that its logic must be a single value expression. When BKM logic is complex, this requires a context, but the logic of a decision service is modeled as a DRD. Given a choice, non-technical modelers seem to prefer DRDs over contexts.

Any time some bit of logic is repeated - such as iteration of rows to construct a table - DMN requires use of a function, either a BKM, context entry function definition, or a decision service. Often creating that function as a decision service is the most business-friendly way. To illustrate this, let's revisit the decision model from last month's post. Given a table of mortgage loan products differing in interest rate, "points", and other fees, in combination with a specified purchase price and down payment, create a table showing the monthly payment for each loan product. The DRD from last time looked like this:

In last month's post, we modeled Mortgage payments by Lender as a context:

But now let's say the modeler has created this DRD as decision requirements but is unable to create the logic of Mortgage payments by Lender himself. He knows it requires iteration over Loan Products but is unsure how to calculate the monthly payment for a single loan product, what we called Table Row in the previous post. So he delegates the implementation to a more technical modeler in the organization. Previously, Table Row was a context entry function definition that creates a row of the output table given the purchase price, down payment, and a single row of the loan products table. Since it nests another context contextRow, business stakeholders might find it hard to decipher. It would be more understandable to them if modeled as a decision service.

It is quite common for a decision service requested in this way to be created in a separate DMN model and then imported into the original model for invocation. So let's see what that looks like.

In Table Row Service, we'll keep the same three parameters as in the original context entry function definition: Purchase Price, Down Payment, and Loan, where Loan is a single row of Loan Products.

Decisions below the line, called encapsulated decisions, are not returned in the service output. Here to keep things really business-friendly, we've split all the original context entries into separate encapsulated decisions with simple literal expressions:

 

We want our service to return two components, Lender and Payment. We could do this in two ways. We could give the service a single output decision Table Row with two components, modeled as a context with two context entries and no final result box. Alternatively, we could give our decision service two output decisions, Lender and Payment, as shown in the DRD above. A decision service with multiple output decisions creates a structure with one component per output decision, which is exactly what we want. Either way, the invoking DRD looks like the DRD below, and the call from Mortgage payments by Lender returns a structure with the same two components, Lender and Payment.

Now, in the original DRD, we need to import Table Row Service. The mechanics of import are tool-dependent. In Trisotech we click Include and navigate to the model and then the service we want to import. Imported models by default are prefixed with the name of their definition model, but we can edit it to something shorter, like service. This prefix is only used in the importing model.

This example combines two uses of decision services. First, it supports delegated implementation of decision logic, implemented as a function invoked by the original decision. Second, it supports reusable logic, such as an iterated expression, which also requires a logic function. In both cases, the larger and more complex the logic of the function, the greater the business-friendliness advantage of a decision service over a BKM. Also, unlike a BKM, a decision service can also be invoked by an external client, such as a BPMN process.

If you want to do real DMN modeling, you need to be able to use BKMs, contexts, and decision services, and know which one to choose in any situation. Our DMN Basics and DMN Advanced training teaches you that. Each class gives you 60-day use of Trisotech's DMN Modeler for hands-on exercises and post-class certification. Check it out!