Pular para o conteúdo principal

Guia DMN

Guia completo para criar decisões usando DMN (Decision Model and Notation) é a linguagem FEEL (Friendly Enough Expression Language).

O que é DMN?

DMN é um padrão da OMG (Object Management Group) para modelar decisões de negócio de forma visual e executável. O Decision Engine utiliza o Camunda DMN Engine que implementa o padrão DMN 1.3.

Vantagens do DMN

  • Padronizado: Padrão internacional reconhecido
  • Visual: Pode ser modelado em ferramentas gráficas
  • Executável: O mesmo modelo é usado para documentação e execução
  • Auditável: Trace completo de todas as regras avaliadas

Estrutura do XML

Um arquivo DMN é composto por elementos XML que definem a estrutura da decisão.

Estrutura Básica

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
id="minha_decisao"
name="Minha Decisão"
namespace="http://minha-empresa.com/dmn">

<decision id="decisionId" name="Nome da Decisão">
<decisionTable id="tableId" hitPolicy="FIRST">
<!-- Inputs -->
<input id="input1" label="Label do Input">
<inputExpression typeRef="number">
<text>nomeVariavel</text>
</inputExpression>
</input>

<!-- Output -->
<output id="output1" name="resultado" typeRef="string"/>

<!-- Rules -->
<rule id="rule1">
<description>Descrição da regra</description>
<inputEntry><text>condição</text></inputEntry>
<outputEntry><text>"valor"</text></outputEntry>
</rule>
</decisionTable>
</decision>

</definitions>

Elementos Principais

ElementoDescrição
definitionsElemento raiz do DMN
decisionDefine uma decisão
decisionTableTabela de decisão com regras
inputDefine uma variável de entrada
outputDefine a saída da decisão
ruleDefine uma regra com condições

Decision Tables

A Decision Table é o coração do DMN. É uma tabela onde cada linha é uma regra e cada coluna é uma condição ou saída.

Estrutura Visual

Uma Decision Table é organizada como uma tabela:

Colunas:

  • Inputs (esquerda): Variáveis de entrada que serão avaliadas
  • Output (direita): Resultado retornado pela regra

Linhas:

  • Header: Define os inputs e output
  • Rules: Cada linha é uma regra com condições e resultado

Exemplo de Decision Table:

Inputs:

  • Input 1: Score de crédito (variável score)
  • Input 2: Renda mensal (variável rendaMensal)
  • Input 3: Ratio de endividamento (variável endividamento)

Output:

  • resultado: Status da aprovação

Rules:

  1. Regra Premium:

    • score >= 800 E rendaMensal >= 10000 E endividamento < 0.3"PREMIUM"
  2. Regra Aprovado:

    • score >= 600 E rendaMensal >= 5000 E endividamento < 0.5"APROVADO"
  3. Regra Fallback (catch-all):

    • Qualquer valor (-) E Qualquer valor (-) E Qualquer valor (-) → "NEGADO"

Inputs

Cada input define uma variável que será avaliada:

<input id="scoreInput" label="Credit Score">
<inputExpression typeRef="number">
<text>score</text>
</inputExpression>
</input>

<input id="incomeInput" label="Renda Mensal">
<inputExpression typeRef="number">
<text>rendaMensal</text>
</inputExpression>
</input>

Outputs

Define o resultado da decisão:

<!-- Output simples -->
<output id="resultOutput" name="resultado" typeRef="string"/>

<!-- Múltiplos outputs -->
<output id="statusOutput" name="status" typeRef="string"/>
<output id="taxaOutput" name="taxa" typeRef="number"/>
<output id="parcelasOutput" name="parcelas" typeRef="number"/>

Rules

Cada rule define uma combinação de condições e seu resultado:

<rule id="rule_premium">
<description>Cliente premium - score excelente</description>
<inputEntry><text>&gt;= 800</text></inputEntry> <!-- score >= 800 -->
<inputEntry><text>&gt;= 10000</text></inputEntry> <!-- renda >= 10000 -->
<outputEntry><text>"PREMIUM"</text></outputEntry>
</rule>
Escape de Caracteres XML

No XML, os caracteres < e > precisam ser escapados:

  • <&lt;
  • >&gt;

Hit Policies

A Hit Policy define como as regras são avaliadas quando mais de uma pode ser acionada.

PolicySímboloDescriçãoResultado
FIRSTFRetorna a primeira regra acionadaÚnico
UNIQUEUApenas uma regra deve ser acionadaÚnico
ANYAQualquer regra pode ser acionada (mesmo resultado)Único
COLLECTCColeta todas as regras acionadasLista
RULE ORDERRRetorna na ordem das regrasLista
OUTPUT ORDERORetorna ordenado pelo outputLista

FIRST (Recomendado)

A política mais comum. Retorna o resultado da primeira regra que satisfaz todas as condições.

<decisionTable id="table" hitPolicy="FIRST">
<!-- Regras são avaliadas na ordem, para na primeira que aciona -->
<rule id="r1">...</rule> <!-- Se acionar, retorna e para -->
<rule id="r2">...</rule> <!-- Só avalia se r1 não acionou -->
<rule id="r3">...</rule> <!-- Só avalia se r1 e r2 não acionaram -->
</decisionTable>

UNIQUE

Exige que apenas uma regra seja acionada. Útil quando as condições são mutuamente exclusivas.

<decisionTable id="table" hitPolicy="UNIQUE">
<rule id="r1">
<inputEntry><text>[0..599]</text></inputEntry> <!-- 0-599 -->
</rule>
<rule id="r2">
<inputEntry><text>[600..799]</text></inputEntry> <!-- 600-799 -->
</rule>
<rule id="r3">
<inputEntry><text>&gt;= 800</text></inputEntry> <!-- 800+ -->
</rule>
</decisionTable>

COLLECT

Coleta todos os resultados das regras acionadas.

<decisionTable id="table" hitPolicy="COLLECT">
<!-- Pode retornar múltiplos resultados -->
</decisionTable>

Tipos de Dados

O DMN suporta os seguintes tipos:

TipoDescriçãoExemplo
stringTexto"aprovado"
numberNúmero (inteiro ou decimal)720, 0.05
booleanVerdadeiro/Falsotrue, false
dateDatadate("2024-01-15")
timeHoratime("14:30:00")
dateTimeData e horadateTime("2024-01-15T14:30:00")

Sintaxe FEEL

FEEL (Friendly Enough Expression Language) é a linguagem de expressão usada no DMN.

Comparações Numéricas

ExpressãoDescriçãoExemplo
>= valorMaior ou igual>= 600
<= valorMenor ou igual<= 100000
> valorMaior que> 0
< valorMenor que< 0.5
= valorIgual a= 720
!= valorDiferente de!= 0
<inputEntry><text>&gt;= 600</text></inputEntry>
<inputEntry><text>&lt; 0.5</text></inputEntry>

Ranges (Intervalos)

ExpressãoDescriçãoExemplo
[a..b]Intervalo fechado (inclui a e b)[600..799]
(a..b)Intervalo aberto (exclui a e b)(0..1)
[a..b)Fechado-aberto[0..100)
(a..b]Aberto-fechado(0..100]
<!-- Score entre 600 e 799 (inclusive) -->
<inputEntry><text>[600..799]</text></inputEntry>

<!-- Percentual entre 0 e 1 (exclusivo nas pontas) -->
<inputEntry><text>(0..1)</text></inputEntry>

Strings

ExpressãoDescrição
"valor"String literal
"BMW", "Mercedes"Lista de valores possíveis
<!-- Marca igual a "BMW" -->
<inputEntry><text>"BMW"</text></inputEntry>

<!-- Output string -->
<outputEntry><text>"APROVADO"</text></outputEntry>

Wildcard (Qualquer Valor)

O caractere - significa "qualquer valor" (sempre match):

<!-- Aceita qualquer valor -->
<inputEntry><text>-</text></inputEntry>

Negação

Use not() para negar uma condição:

<!-- Não é "BMW" -->
<inputEntry><text>not("BMW")</text></inputEntry>

<!-- Não está no range -->
<inputEntry><text>not([0..100])</text></inputEntry>

Null Check

<!-- Valor é null -->
<inputEntry><text>null</text></inputEntry>

<!-- Valor não é null -->
<inputEntry><text>not(null)</text></inputEntry>

List Contains

Para verificar se um valor está em uma lista:

<inputEntry>
<text>list contains(["BMW", "Mercedes", "Audi", "Porsche"], marca)</text>
</inputEntry>
Sintaxe list contains

Use list contains([lista], variavel) quando precisar verificar se um valor está em uma lista de opções. A variável deve ser referenciada pelo nome definido no input.

Expressões Compostas

Combine expressões com and e or:

<!-- score >= 600 AND renda >= 5000 -->
<inputEntry><text>score &gt;= 600 and renda &gt;= 5000</text></inputEntry>

Boas Práticas

1. Use IDs Descritivos

<!-- Bom -->
<rule id="rule_denied_low_score">
<rule id="rule_approved_premium">
<rule id="rule_manual_review">

<!-- Evite -->
<rule id="r1">
<rule id="rule1">

2. Adicione Descriptions

<rule id="rule_denied_score">
<description>Negado - Score abaixo do mínimo permitido (500)</description>
...
</rule>

3. Ordene Regras Estrategicamente

Com hitPolicy="FIRST", coloque regras mais específicas primeiro:

<!-- 1. Regras de negação primeiro (mais específicas) -->
<rule id="rule_denied_score">...</rule>
<rule id="rule_denied_income">...</rule>

<!-- 2. Regras de aprovação específicas -->
<rule id="rule_approved_premium">...</rule>
<rule id="rule_approved_excellent">...</rule>

<!-- 3. Regras genéricas por último -->
<rule id="rule_approved_regular">...</rule>

<!-- 4. Fallback (catch-all) -->
<rule id="rule_manual">
<inputEntry><text>-</text></inputEntry>
<outputEntry><text>"ANALISE_MANUAL"</text></outputEntry>
</rule>

4. Use Hit Policy FIRST

Na maioria dos casos, FIRST é a política mais intuitiva e fácil de debugar.

5. Evite Condições Sobrepostas com UNIQUE

Se usar UNIQUE, garanta que as condições são mutuamente exclusivas:

<!-- Correto: ranges não se sobrepõem -->
<rule><inputEntry><text>[0..599]</text></inputEntry>...</rule>
<rule><inputEntry><text>[600..799]</text></inputEntry>...</rule>
<rule><inputEntry><text>&gt;= 800</text></inputEntry>...</rule>

<!-- Errado: regras podem acionar juntas -->
<rule><inputEntry><text>&gt;= 500</text></inputEntry>...</rule>
<rule><inputEntry><text>&gt;= 600</text></inputEntry>...</rule>

6. Sempre Tenha um Fallback

Inclua uma regra catch-all para evitar resultados inesperados:

<rule id="rule_fallback">
<description>Caso não coberto - análise manual</description>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<inputEntry><text>-</text></inputEntry>
<outputEntry><text>"ANALISE_MANUAL"</text></outputEntry>
</rule>

Ferramentas

Camunda Modeler

O Camunda Modeler é uma ferramenta gratuita para criar DMN visualmente.

Validação

O Decision Engine valida o DMN no momento da criação da versão. DMN inválido retorna erro 400.

Referências