Como construir um moderno motor de regras de negócio, uma rápida visão geral
Esta é uma visão conceptual de alto nível da arquitectura do motor de regras de negócio. Está acima do código real. Se você está construindo um mecanismo de regras de negócio – é altamente provável que você possa achar este texto útil.
Em pouco tempo, eu construí um mecanismo de regras de negócio que permitiu a automação de negócios para pequenas e médias empresas e também tinha todas as capacidades e potencial para servir bem a grandes empresas. Foi um caminho desde uma aplicação de software regular até uma solução sofisticada e complexa que satisfazia os exigentes requisitos de escalabilidade, manutenção e extensão de capacidade. Este texto fornecerá uma visão geral do que é o Business Rules Engine e descreverá uma das abordagens modernas para construí-lo que você pode considerar ao construir este tipo de software.
Para começar, é importante definir termos básicos. Os motores de regras de negócio existem na indústria há bastante tempo de uma forma ou de outra e existem algumas definições dadas para praticamente todos os termos que vamos utilizar. Vamos começar com uma “regra de negócio” – existe uma definição bem conhecida para este termo. Então uma “regra de negócio” é:
Uma declaração que define ou restringe algum aspecto do negócio. Ela pretende afirmar a estrutura do negócio ou para controlar ou influenciar o comportamento do negócio.
T. Morgan, Regras de Negócios e Sistemas de Informação. Boston: Addison-Wesley Publishing, 2002
As regras de negócios têm um escopo muito amplo e podem ser aplicadas a qualquer aspecto do negócio. Por exemplo, a regra “Quando um cliente entra, cumprimente-o com um sorriso caloroso e um “Olá” amigável é aplicada pelo funcionário da empresa quando se encontra com os clientes. Outra regra pode definir ou restringir as abordagens para resolver tarefas de rotina por uma função específica em uma empresa. Com o aumento constante da popularidade das soluções de software como os sistemas de CRM e com a integração total do software a uma variedade de domínios de negócio, a maioria dos processos de negócio tornou-se parcial ou totalmente orientada para os dados. Isto levou à transformação das regras de negócio para que se tornassem orientadas para o software, por exemplo, a regra de negócio “Quando um cliente compra algo da nossa loja, telefona-lhe mais tarde a perguntar se gostaria de comprar outros bens relacionados” transformou-se numa regra mais moderna “Quando um cliente compra algo da nossa loja online, envia-lhe um e-mail listando outros bens relacionados mais tarde”. Hoje em dia, muitas empresas lidam principalmente com dados nas suas operações diárias. Tendo em conta que a maioria das empresas de todos os tamanhos têm soluções de software integradas às suas actividades empresariais, a definição do termo “regra de negócio” pode ser definida de uma forma mais específica, acrescentando um esclarecimento (está em negrito) à definição acima referida por T. Morgan:
Uma regra de negócio é uma declaração que define ou restringe algum aspecto do negócio. Destina-se a afirmar a estrutura do negócio ou a controlar ou influenciar o comportamento do negócio. Ela é armazenada como uma construção de dados no armazenamento persistente e contém um pacote atômico de lógica de negócio. É gerenciado e aplicado aos processos de negócio da empresa automaticamente através de uma solução de software.
Ainda o termo “regra de negócio” definido, o termo “Business Rules Engine Management System” (BRMS) é definido como segue:
BRMS é uma solução de software para gerenciar (armazenar, editar e excluir, etc.) regras de negócio, bem como para aplicá-las aos processos de negócio da empresa.
BRMSs comerciais podem ser extremamente caros para adquirir a licença e integrá-los à infra-estrutura de TI da empresa, portanto as empresas freqüentemente implementam soluções internas quando encontram a necessidade de automatizar processos de negócios ou outros tipos de processos.
BRMSs podem se tornar uma parte essencial e vital de qualquer negócio. Às vezes o sucesso de um negócio pode depender das regras de negócio que ele tem e como essas regras de negócio são gerenciadas e aplicadas.
A construção de dados de regras de negócio
Uma regra de negócio pode ser representada como uma série conseqüente de comandos atômicos. Os comandos podem incluir análise de dados condicionais, comandos de tempo de espera, comandos de execução de ações, etc. O exemplo de regra de negócio “Quando um cliente compra algo da nossa loja online envia-lhe um email listando outros bens relacionados mais tarde” é bom e genérico e muitas outras regras de negócio podem ter uma estrutura lógica muito semelhante:
O fluxo de processamento de regras é iniciado quando uma compra é feita e alguma lógica de negócio é aplicada executando o comando “Enviar ao comprador um email com ofertas de mercadorias relevantes”. Pode acontecer assim, que o comprador tenha desativado a assinatura do e-mail. Então, a condição adicional tem que ser adicionada à regra de negócio – “se o comprador tem a subscrição de e-mail ativada”:
Os comandos são executados consequentemente e há agora um comando de análise de dados para verificar se o comprador tem uma subscrição de e-mail ativa. Se assim for – proceder à execução do próximo comando da regra de negócio. E se não – não prosseguir, a regra de negócio é considerada concluída, o fluxo de processamento pára, os comandos subsequentes não são executados.
O comprador também pode ter uma subscrição por SMS, e se estiver activa, também deve haver outro comando – “Enviar um SMS com oferta promocional relacionada”. Com isso, a ramificação é introduzida na lógica da regra de negócio:
As ramificações da regra são processadas independentemente umas das outras. O processamento de um dos ramos pode parar no comando de avaliação da condição e outro ramo pode ser processado até o final.
A IU da aplicação do lado do cliente BRMS para representar uma regra de negócio pode ser implementada de várias maneiras (qualquer tipo de representação gráfica em árvore irá funcionar):
A construção de dados de regras de negócio é um gráfico de árvore enraizada direcionada (um gráfico acíclico direcionado, que tem uma árvore como um gráfico não direcionado subjacente). Os vértices do gráfico de regras de negócio são representados com diferentes tipos de comandos: comandos de análise de dados, comandos de execução de ações, comandos de tempo de espera, etc. Cada árvore enraizada dirigida tem uma raiz – um vértice que tem todas as arestas apontando a partir dela. Assim, cada regra começa com um vértice especial (ou vértice raiz em termos da teoria dos gráficos) – o vértice que designa o ponto de entrada para o processamento da regra.
Operações deCRUD na construção de dados de regras de negócio
Desde que a construção de dados é representada com uma árvore enraizada dirigida e nunca com qualquer outro tipo de gráfico, isto alivia-nos dos inconvenientes que acompanham o armazenamento de estruturas gráficas gerais com RDBMS (como o armazenamento dos vértices e arestas em diferentes tabelas que podem resultar num aumento do número de pesquisas para uma única recuperação de regras, etc.). E isso é crítico porque é claro que durante as operações normais de busca de dados BRMS acontecem muito mais frequentemente, do que outras operações como inserções, atualizações ou exclusões.
Apenas como um lembrete – cada vértice da regra de negócio representa um comando atômico. Ele é salvo na tabela RDBMS como um registro com atributos como tipo de comando, descrição e outros dados suplementares. Em uma árvore cada vértice tem um único pai (exceto o vértice raiz, que não tem pais), assim cada registro deve conter um ID do vértice pai. Também é conveniente ter outra tabela que aloje os registros de regras com os dados relevantes à própria regra de negócio. Não há problema em armazenar as construções de dados das regras de negócio de qualquer complexidade com esta abordagem.
As operações do CRUD são bastante simples. As alterações de regras de negócio podem exigir atualizações em uma ou ambas as tabelas – regra ou comando. Ao eliminar ou inserir comandos é necessário manter as referências entre os comandos (isto é essencialmente eliminar ou inserir nós numa árvore).
Um dos componentes BRMS, vamos chamar-lhe um gestor, deve executar as operações de base de dados descritas e fornecer uma API para operações CRUD sobre regras de negócio.
O processamento da regra de negócio
O processamento da regra de negócio começa quando um determinado evento acontece. Pode ser qualquer coisa – um usuário fez o login, uma compra foi feita, alguma quantia de dinheiro foi transferida, etc. Este tipo de atividade deve ser rastreada e o BRMS deve ser informado sobre ela através de algum transporte. O AMQP é provavelmente o mais adequado para este tipo de tarefa.
1. Todo o conceito é construído sobre a arquitetura de microserviços. O microserviço do consumidor do evento ouve todos os eventos através da declaração de uma fila e a vincula a uma troca específica em um servidor de troca RabbitMQ. Quando uma atividade de negócios (que é considerada significativa e é rastreada) acontece no sistema de software principal, a mensagem é enviada para o servidor de troca RabbitMQ. Ele contém informações sobre o que aconteceu, bem como alguns dados complementares relevantes. O evento pode ser identificado com um atributo de qualquer tipo passado na mensagem ou utilizado como uma chave de roteamento, por exemplo, um string purchase.complete. A mensagem é então consumida pelo microserviço de consumo do evento BRMS.
2. Quando o microserviço de consumo do evento recebe a mensagem do sistema de software principal, ele então consulta o microserviço gerente se há alguma regra de negócio no banco de dados que tenha o gatilho de regra apropriado para o evento de atividade de negócio. E se houver uma regra de negócio correspondente, o micro-serviço gerente retorna os dados de comando iniciais para o micro-serviço de consumo do evento. Esta recuperação de dados do gerenciador é feita via gRPC e é visualizada com uma linha tracejada.
3. Logo após o microservice gerenciador responder com os dados de comando inicial, o microserviço consumidor do evento estará pronto para inicializar o processamento da regra de negócio. O consumidor do evento forma outra mensagem que encapsula os dados de comando inicial (recebidos do microserviço gerenciador), e os dados do evento, recebidos do sistema principal de software. Ele os envia através do AMQP para uma troca interna BRMS. A chave de roteamento da mensagem corresponde ao tipo de comando.
4. O microserviço de processamento inicial do comando consome a mensagem (ele escuta a fila onde as mensagens com chave de roteamento initial
são empilhadas). Então ele faz sua lógica (em um caso básico o bloco inicial não contém lógica) e o gerenciador de consultas se houver comandos subsequentes na regra de negócio (estes são os comandos com parent_id
igual a id
do comando que está sendo processado atualmente). E se assim for, ele recebe os dados do próximo comando e envia tanto os dados do evento quanto os dados do próximo comando para o servidor interno do RabbitMQ. Sim, agora parece uma travessia de lista ligada, e quando a regra tem ramos é uma travessia de árvore! É assim que a regra de negócio está sendo processada comando por comando. Outra coisa importante aqui – nesse contexto, os dados do evento são passados para cada comando filho. É um contexto da execução única das regras de negócio. Ele pode ser usado posteriormente no processador de comando de análise de dados e no processador de comando de ação.
Para fins ilustrativos vamos assumir que a regra de exemplo tem uma estrutura como esta: comando inicial -> comando de análise de dados condicional -> comando de ação de negócios. Então o próximo comando após o inicial é o comando de análise de dados.
5. O processador de comando de análise consome a mensagem com a chave de encaminhamento analysis
da troca interna. Com base na avaliação das condições, que são descritas no comando de análise da regra de negócio e usando os dados do evento, o fluxo de execução da regra pode continuar ou parar aqui. Se ele parar – nenhum outro comando de regra de negócio será executado. Se o fluxo de execução continuar, o processador de análise consulta o gerenciador de consultas para os próximos comandos de regras de negócio, os recupera e publica outra mensagem para o servidor de troca interno.
6. Finalmente, há uma mensagem na troca interna, que está pronta para que o processador de comandos de ação seja consumido. Se o fluxo de execução das regras de negócio chegou até este comando, isso significa que neste ramo da regra todas as condições que estavam lá no comando de análise de dados eram verdadeiras e o fluxo de execução não foi interrompido. O processador de comandos de ação executa a ação, por exemplo, envia um e-mail.
Este tipo de travessia gráfica é depth-first, e quando um comando com 2 ou mais comandos filhos é encontrado, a travessia simultânea depth-first começa para cada ramo devido à natureza assíncrona do processamento de regras de negócio no sistema descrito.
Escalonamento
A abordagem descrita permite não só uma grande separação de preocupações, mas também pode poupar muito dinheiro quando se trata de pagar as contas IaaS. Os utilizadores finais criam uma variedade de regras de negócio com diferentes números de comandos de diferentes tipos e diferentes números de ramos. Mas os cenários de escalas comuns são os seguintes:
1. O número de eventos aumenta – o consumidor do evento aumenta a escala.
2. O número de regras de negócio associadas (acionadas) pelos eventos aumenta – o processador de comando inicial aumenta junto com o gerente.
3. Há muitos comandos de análise nas regras de negócio – o processador de comando de análise aumenta a escala.
4. Muitos comandos de ação têm que ser executados – o processador de comando de ação aumenta a escala.
Reliabilidade
O vaso sanguíneo do sistema é o transporte. Para que o sistema se mantenha operacional sob carga alta, a troca interna de mensagens deve ser altamente confiável. O RabbitMQ fornece agrupamento e satisfaz bem os requisitos de confiabilidade (https://www.rabbitmq.com/clustering.html).
Outros tipos de comando
Ainda outra lógica de negócio pode ser introduzida no sistema. Um dos tipos de comandos populares e demandados é um comando de tempo de espera (por exemplo, ‘Esperar por 45 minutos, depois continuar’). Com a introdução do comando de tempo de espera, o processamento da regra de negócio não é mais em tempo real, uma vez que pode ser suspenso por algum tempo. Tais mudanças requerem processadores de comando adicionais e alguns ajustes nas estruturas de dados que estão fora do escopo deste texto. A manipulação do tempo pode ser difícil e escrever um serviço que opera os horários e o tempo pode ser um desafio, aqui está um exemplo de um bom serviço: https://github.com/nextiva/krolib
As alternativas de terceiros
Existem alternativas bem conhecidas de motores de regras/motores de fluxo de trabalho, aqui estão os 3 primeiros (IMHO):
1. Comunda – é um produto maduro com versões comunitárias e empresariais, que você pode querer usar. Obviamente, a versão empresarial é paga.
2. Luigi – é uma ferramenta de motor de workflow desenvolvida pela Spotify para as suas necessidades internas mas já utilizada por dezenas de outras empresas.
3. Apache Airflow – este é outro produto bem conhecido que provou ser capaz, conveniente e personalizável.
O que une estas ferramentas, é que todas elas utilizam gráficos acíclicos directos como a estrutura de dados que representa as regras de negócio ou fluxos de trabalho. Não é uma surpresa.
Pode haver outros produtos que merecem atenção, mas qualquer investigação deve começar com estes três.
Conclusão
Construir o seu próprio motor de regras de negócio pode ser um desafio, mas é gratificante. Não só obtém um sistema interno, mas também é construído de acordo com os requisitos específicos do seu negócio. Uma boa equipe DevOps é uma necessidade quando se trata de manter a confiabilidade, escalabilidade e monitoramento. Afinal, você obtém um produto fantástico do qual se pode orgulhar.