Escolha uma Página

Hoje em dia, quando falamos sobre integração entre sistemas, principalmente sistemas corporativos, falamos muito sobre SOAP (Simple Object Access Protocol) e REST. SOAP por exemplo, é um protocolo de troca de mensagens baseado em XML e que utiliza um “envelope” para transmitir suas mensagens.

Na prática, quão simples é enviar e receber uma mensagem XML via SOAP?

 

Na realidade, este tipo de integração tem um contrato forte definido por outros dois arquivos: o XML e o WSDL. Eles mapeiam os serviços de um Web Service e os arquivos XSD, que fornecem o contrato para a troca de mensagens. Geralmente as IDEs de desenvolvimento como o Eclipse e o Visual Studio possuem ferramentas para o “bootstrap” da integração a partir de um arquivo WSDL. A ferramenta cria uma série de arquivos com todo o código necessário para fazer uma chamada ao serviço, bem como todas as classes que serão usadas na integração, parece bastante prático.

Mas será que precisaríamos ficar altamente dependentes das IDEs para fazer uma integração SOAP por exemplo? Precisamos de todo aquele código criado automaticamente para fazer uma simples “troca” de XML? Se nossa aplicação necessitar integrar com vários sistemas, como é o nosso cenário na MundiPagg? Já imaginou o quanto de código que será gerado por essas ferramentas?

Além disso, geralmente as classes de domínio das nossas aplicações não são as mesmas da integração. Quando integramos com algum outro sistema, temos que fazer um “mapper” que traduz o objeto vindo do sistema integrado para o nosso domínio. Isso resulta em mais código sendo escrito na nossa aplicação para ser testado e mantido pelo time de desenvolvimento.

Não teria uma forma mais fácil e com menos “overhead” de código para fazer uma simples integração?

 

Essa é uma pergunta que surgiu no nosso time de desenvolvimento. Aonde está o “Simple” da sigla SOAP? Porque até o momento, temos que gerar, mesmo que automaticamente, uma grande quantidade de classes, métodos e “mappers” para fazer uma simples troca de mensagens.

Pensando sobre como fazer uma integração de forma simples e rápida começamos a refletir o que, de fato, é uma integração e como ela deveria ser feita. Fomos pesquisando sobre algumas ferramentas e patterns específicos para integrações.

Existem uma série de padrões de código específicos para troca de mensagens entre sistemas: os chamados EIP’s (Enterprise Integration Patterns) que são padrões de códigos para resolver diversos problemas, tais como: fluxo de mensagens, roteamento, filtros, tradutores e outros. Estes padrões propõem resolver os desafios que envolvem troca de mensagens e fluxos de negócios complexos. A Figura abaixo mostra um exemplo de um fluxo usando um padrão Router do EIP.

Exemplo de roteamento de mensagens usando EIP

Uma implementação conhecida destes padrões é o Apache Camel. Esta biblioteca, feita em Java, implementa diversos EIPs para facilitar o processo e o fluxo de integração dentro de uma aplicação. Estas duas ferramentas foram de grande inspiração para o problema que queríamos resolver, que é facilitar o processo de integração com outros sistemas.

Nossa biblioteca, desenvolvida em Go, foi bastante inspirada nos conceitos e design do Apache Camel principalmente no que tange o design da API, conectores e fluxo de mensagens.

O que fizemos para fazer integrações de forma mais eficiente sem o “overhead” de código-fonte?

 

Começamos a pensar de forma simples: Primeiramente, toda integração SOAP/REST na sua essência são apenas protocolos de texto sobre HTTP, simples assim. Então, o que fazemos é: mandar um texto de um sistema A para um sistema B e ler um texto de volta como resposta, muito simples né?

Acontece que cada sistema entende apenas o seu próprio idioma, seu contrato de serviço, então temos que traduzir nossas mensagens para o idioma do outro sistema. Então, a partir do idioma da nossa aplicação (nosso objeto que será enviado) devemos escrever uma carta (seguindo o idioma do sistema de destino) e enviar para o nosso destinatário.

Como podemos fazer a tradução da nossa mensagem para uma mensagem legível por outro sistema?

 

Para isso, vamos pensar acerca das as aplicações web e o padrão MVC (Model View Controller). Basicamente, todos os frameworks MVC para web a camada de View faz uma tradução de um objeto do domínio da nossa aplicação para o idioma que é entendido pelo navegador, o  HTML (Hyper Text Markup Language), que por sua vez, traduz para uma linguagem que os usuários possam entender através da renderização da página.

Em outras palavras temos um objeto binário em memória que foi traduzido para um formato de texto (HTML) que foi traduzido para um formato visual para o usuário. A primeira tradução é feita por ferramentas de templates tais como: Mustache, Handlebars, Razor entre outras. A Figura abaixo mostra um exemplo de um template.

Exemplo de um template Handlebars

Quando o template é aplicado o campo “{{title}}” do template será substituído pelo valor do atributo “title” do nosso objeto e assim por diante.

Voltando ao nosso problema, começamos a usar uma template engine. No nosso caso, a template engine padrão do Go, para o processo de tradução. Essas ferramentas são extremamente poderosas pois podemos formatar o texto de saída com bastante liberdade. Nossa solução foi desenhada da seguinte forma: Nós temos um objeto de domínio, que através de um motor de renderização de textos, conseguimos traduzir uma mensagem para o idioma do sistema destinatário. A Figura abaixo ilustra o processo de tradução de mensagens usando nossa ferramenta simulando uma integração genérica.

Exemplo de uma mensagem que nossa API recebe

Exemplo de uma mensagem que nossa API recebe

 

Exemplo de template para uma requisição genérica.

Exemplo de template para uma requisição genérica.

No template acima as linhas que começam com “##” montam o cabeçalho HTTP da requisição e o resto da mensagem compõe o “body” da requisição HTTP. Além disso, pode-se observar que o formato de saída de uma requisição genérica é bem diferente do formato de nossa API, por exemplo, o valor a ser transferido deve ser representado com casas decimais e com “,” diferente da nossa aplicação hipotética que recebe o valor sempre em centavos. Essas variações no formato da informação acontecem de forma bastante frequente e pode variar de sistema para sistema. Os motores de renderização de texto através de funções chamadas (funcmaps), no caso do Go, conseguem traduzir de forma eficiente nosso idioma para qualquer outro idioma.

Sendo assim, conseguimos resolver a primeira parte de um processo de integração. A segunda parte do processo consiste em ler a mensagem de retorno e traduzir para o nosso idioma. Para resolver este problema foi implementado um extrator de informações baseado em templates. Este extrator funciona da seguinte forma: nós declaramos como esperamos que uma mensagem chegue ao nosso sistema (template da mensagem) e informamos no template todas as informações que queremos ler da mensagem de retorno. A partir do template de retorno podemos transformar as informações extraídas para nossa linguagem de domínio.

Os campos do template, da imagem acima, que iniciam com “@“ indica que neste ponto irá conter uma informação que deverá ser mapeada e disponibilizada para o nosso tradutor. No nosso exemplo, temos uma informação que chamamos de “@status” e que será usada no nosso template de saída.

Através do desenvolvimento desta biblioteca, nosso processo de integração passou a ser muito mais rápido no tempo de desenvolvimento e muito mais simples de aplicar regras específicas para cada sistema diferente. Nossa ideia num futuro breve é pensar em evoluir a ferramenta para que pessoas não técnicas – mas com conhecimento do negócio – sejam capazes de integrar sistemas de forma rápida e sem necessitar saber escrever uma aplicação. Dessa forma, vamos conseguir entregar mais valor em nossas soluções em menos tempo.

Philippe Moneda

Philippe Moneda

Desenvolvedor backend na Mundipagg trabalha com desenvolvimento de software atualmente nas linguagens C# e Go, gosta de contribuir com projetos no GitHub e não dispensa uma jogatina no PS4.
Philippe Moneda

Últimos posts por Philippe Moneda (exibir todos)

Quer receber as novidades de e-commerce em primeira mão?

x