Dificilmente um software conseguirá atender sozinho todas as demandas de seu contexto de operação. Por essa razão, para cumprir, de fato, os objetivos do negócio, a arquitetura de um software deverá contemplar, além dele próprio, a relação com os demais “integrantes sistêmicos”, delimitando responsabilidades e relacionamentos.
Sabendo que, por exemplo, um software digitaliza ou suporta a execução de atividades de um processo, será mais bem sucedido aquele que, necessário para uma atividade, “conseguir passar o bastão” para os demais, necessários para as demais atividades.
Segregando responsabilidades, um software gerencial será bem sucedido se conseguir “consolidar dados” de diversas fontes transacionais.
Data is a precious thing and will last longer than the systems themselves. Tim Berners-Lee |
Finalmente, um software especialista, para ser “bem sucedido”, precisará estar “disponível” para acionamento fácil.
Archimate (R) 3.1 Specification A linguagem ArchiMate permite que arquitetos corporativos descrevam, analisem e visualizem os relacionamentos entre os domínios de negócios de maneira efetiva.Este livro é a especificação oficial da linguagem de modelagem ArchiMate 3.1 do The Open Group. |
Habitue-se a utilizar, consistentemente e corretamente, linguagens visuais de modelagem, como ArchiMate e C4, para comunicar aspectos relevantes de arquitetura. |
A relação de um software com artefatos externos é, ao mesmo tempo, a expressão de sua utilidade e a principal fonte de problemas em ambiente produtivo. Sejam as integrações explícitas, com esforço de desenvolvimento do time para fazer com que ela aconteça, ou implícitas, acontecendo a revelia e gerando apenas dificuldade para evolução, as integrações são aspecto crítico da arquitetura de qualquer software.
Quando as integrações não são devidamente projetadas, acontecem “organicamente”, muitas vezes como iniciativas shadow IT. Obviamente, esse é um bad smell para o futuro da solução como um todo.
Quanto mais relacionamentos um software possuir, maior será seu impacto e relevância no contexto onde funciona. Em termos simples, software com poucos relacionamentos costuma ser inútil ou ser importante apenas em períodos curtos e eventuais. Não é exagero dizer que qualidade “interna” de um software pouco importará se suas “integrações” não forem bem-sucedidas no médio/longo prazo.Aplicativos interessantes raramente operam isolados. Hohpe e Woolf |
O acoplamento forte permite que as “rachaduras” em uma parte do sistema se propaguem – ou se multipliquem – através das camadas ou limites do subsistema. Nygard |
Aspectos arquiteturais relevantes em integrações
Ao analisar a integração entre dois ou mais sistemas de software é importante analisar três aspectos: forma de comunicação, necessidade de consistência e coordenação.
Começando pela forma de comunicação, chegamos a duas possibilidades genéricas: síncrona e assíncrona. Dois sistemas de software tem comunicação síncrona quando a requisição de uma das partes implica em um tempo espera até que uma resposta seja devolvida (atualização de status ou indicativo de erro). Por outro lado, a comunicação é assíncrona quando a parte requisitante prossegue trabalho após confirmação mínima de que sua solicitação foi aceta.
As decisões arquiteturais que dizem respeito ao formato de comunicação entre sistemas tem impacto direto em atributos de qualidade como segurança, resiliência, escalabilidade e desempenho.
Tratando de consistência há, também, duas possibilidades genéricas: atomicidade ou eventualidade, sendo que, dois sistemas de software tem consistência atômica quando, em hipótese alguma, seus estados refletem momentos diferentes (tudo está atualizado ou nada está atualizado). Por outro lado, dois sistemas tem consistência eventual quando defasagens sejam suportadas sem prejuízo de operação.
Em sistemas distribuídos, dificilmente se atinge indicadores adequados de escalabilidade e resiliência quando atomicidade é indispensável.
Finalmente, tratando de coordenação há, também, duas possibilidades genéricas: coreografia ou orquestração, sendo que, dois sistemas de software serão “coreografados” quando não dependerem de um agente externo (um terceiro software) para garantir que a integração aconteça. Entretanto, há cenários com workflows complexos – envolvendo diversas etapas – onde algum tipo de orquestração torna-se indispensável.
Cabe ao arquiteto decidir, para cada integração, se a comunicação será síncrona ou assíncrona, a consistência deverá ser atômica ou eventual e, finalmente, a coordenação ocorrerá por coreografia.
Integração simples ou colaboração
Eventualmente, integrações tem regras e formatos que extrapolam as “responsabilidades” de cada um dos sistemas, individualmente, expressando funcionalidades inéditas resultantes de uma “colaboração”.
Considere, por exemplo, uma organização pode desejar implementar suporte especial para o atendimento a revendedores, combinando funcionalidades de seus sistema de CRM e ERP – nenhum deles planejado, originalmente, para essa finalidade.
A integração desses sistemas será uma colaboração que, provavelmente, envolverá a escrita de código novo.
Modelando 'colaborações' entre aplicações Manual do Arquiteto Corporativo A modelagem de colaborações entre aplicações é atividade essencial na prática da arquitetura corporativa. Neste capítulo, apresento ideias e conceitos que colaboram nessa atividade. |
Explicitando as relações de um software com outros usando C4
Nos últimos anos, uma notação tem ganhado destaque para documentação de relacionamentos. Trata-se do modelo C4, idealizado por Simon Brown.
O modelo C4 é uma técnica de notação gráfica enxuta para modelar a arquitetura de sistemas de software. É baseado em uma decomposição estrutural de um sistema em contêineres e componentes e depende de técnicas de modelagem existentes, como a Unified Modeling Language (UML) ou Entity Relation Diagrams (ERD) para a decomposição mais detalhada dos blocos de construção arquitetônicos. Wikipedia |
O propósito dessa análise é revelar quem são as “pessoas” (usuários, agentes, papéis ou personas) e outros artefatos (dependências externas) que estão diretamente conectadas com o software que estamos analisando. Geralmente, estes outros sistemas estão fora do escopo primário.
Agentes externos podem operar como gatilhos para operações no software ou como fontes de dados. Outras vezes, serão “acionados” pelo sistemas que estamos analisando ou irão ser atualizados por este. Finalmente, podem ser utilitários realizando operações de alta especificidade ou complexidade tecnológica (como o envio massivo de e-mails).De todas as práticas associadas a arquitetura de software, a mais fundamental é a explicitação das integrações que precisam ser suportadas por um sistema de software. |
Embora esta seja uma análise muito simples, na prática, sua execução tem se relevando útil e desafiadora. Por incrível que pareça, é difícil para as organizações relacionar quais são os principais “acionadores” e “acionados” para os diversos sistemas. Também costuma ser bem difícil criar uma descrição sucinta sobre o que um sistema faz ou deveria fazer.
Visualising software architecture with the C4 model Na palestra de Simon Brown na AOTB 2019, ele explora a comunicação visual da arquitetura de software com base em uma década de experiências trabalhando com equipes de desenvolvimento de software grandes e pequenas em todo o mundo. |
Representando relacionamentos usando C4
O nível mais alto de abstração proposto pelo modelo C4 propõe a elaboração de diagramas de contexto, muito semelhantes ao que indicamos aqui. Já no segundo nível, o diagrama de contêineres, “explode” o sistema que sendo analisado para revelar sua estrutura.
O diagrama do contêineres mostra a forma de alto nível da arquitetura do software e como as responsabilidades são distribuídas por ela. Também mostra as principais opções de tecnologia e como os contêineres se comunicam. É um diagrama simples e focado em tecnologia de alto nível, útil para desenvolvedores de software e equipes de suporte/operações. Simon Brown |
A elaboração do diagrama de contêineres não é tarefa trivial.
Em sistemas muito grandes, ou legados, é comum que não seja evidente a responsabilidade de cada contêiner (indicando claro acoplamento). Em sistemas novos ou em desenvolvimento, há uma tendência de simplificar em demasia os contêineres.
O diagrama do contêineres mostra a forma de alto nível da arquitetura do software e como as responsabilidades são distribuídas por ela. Também mostra as principais opções de tecnologia e como os contêineres se comunicam. É um diagrama simples e focado em tecnologia de alto nível, útil para desenvolvedores de software e equipes de suporte/operações.
[/sc]
O maior ganho que tenho percebido na elaboração desse diagrama está na explicitação da complexidade dos sistemas, geralmente causada por um projeto descuidado ou pela evolução descontrolada. Para sistemas novos, esse diagrama antecipa discussões que ficariam relegadas a momentos posteriores e que, se feitas no momento certo, poderiam evitar dores de cabeça.
Software Architecture for Developers - Volume 2 Simon Brown explica nos dois volumes de “Software Architecture for Developers” ideias essenciais relacionadas a arquitetura de software e a utilização do modelo C4. |
Modelando dependências de microsserviços com C4
Estratégias arquiteturais baseadas em microsserviços representam desafios para mapeamento de dependências. O problema é que, embora a relação entre dois microsserviços se assemelhe a relação de qualquer outro nível de sistema, a granularidade dificulta visualização e entendimento.
Simon Brown, criador do modelo C4 ensina que há duas abordagens comuns para modelagem de microsserviços com o modelo C4:
- Se o sistema de software depende de uma série de microsserviços que estão fora do controle do time, devemos modelar esses microsserviços como sistemas de software externos, representando o time.
- Se uma única equipe possui vários “microsserviços”, devemos modelar cada coisa implantável como um contêiner.
O mesmo é verdadeiro para funções sem servidor/lambdas/etc. Devemos tratá-los como sistemas de software ou contêineres com base na propriedade.
É curioso que a forma como modelamos integrações tem relação direta com a forma como times estão estruturados, exatamente em conformidade com a lei de Conway.Se aceitamos que as implicações da lei de Conway são reais, então, também precisamos aceitar que qualquer um que tome decisões sobre o design dos times de engenharia influencia fortemente a arquitetura do software (…) Se temos gerentes decidindo que serviços serão desenvolvidos, por quais times, implicitamente, temos gerentes decidindo a arquitetura dos sistemas. Skelton |
Principais abordagens para integração entre aplicações
Ao longo dos anos, a integração entre sistemas é implementada utilizando uma das seguintes cinco abordagens:- Troca de arquivos – Onde uma ou mais aplicações escrevem arquivos em um determinado formato que serão, posteriormente, processados por outra. Além do formato, é necessário estabelecer regras para como nomear os arquivos e onde estes devem ser salvos.
- Banco de dados compartilhado – com múltiplas aplicações compartilhando um mesmo esquema, localizado em um único banco (que pode ser relacional ou não). Não há, de fato, duplicação de dados e tampouco transferências.
- Replicação eventual, onde “motores de ETL” fazem cargas rotineiras de dados de determinadas fontes de dados, sem critério objetivo de seleção.
- Acionamento remoto, onde uma aplicação expõe algumas de suas funcionalidades, geralmente através de serviços e protocolos abertos, de forma que estas possam ser acessadas por outra aplicação. A comunicação é geralmente síncrona.
- Mensageria, onde uma aplicação publica mensagens para um canal comum para serem processadas por outras aplicações que “escutam” ativamente o canal.
Também há as integrações manuais, ou seja, pelo “estagiário digitador” que, partindo de um relatório, gera entradas em sistemas.
Muito embora todas as cinco abordagens resolvam essencialmente os mesmos problemas, cada uma delas tem vantagens e desvantagens. Não raro, aliás, mais de uma abordagem é empregada em um software.Enterprise Integration Patterns Enterprise Integration Patterns é um verdadeiro clássico entre livros de arquitetura de software. Ele contém um catálogo com 65 padrões de integração usando mensageria.Sendo uma obra com mais de 10 anos, o livro demonstra algum cansaço em seus exemplos de código. Mesmo assim, trata-se da melhor referência disponível sobre o tema. |
Desafios comuns em integrações
Todas as integrações tendem a enfrentar os seguintes desafios comuns:- Rede não confiável e lenta – Como bem descrito pelas “oito falácias da computação distribuída”, a rede não pode ser assumida como confiável, tampouco livre de penalidades. Não é raro que aplicações que precisam ser integradas estão operando geograficamente distantes.
- Toda aplicação é diferente (e única) – Soluções de integração precisam transmitir informações entre sistemas escritos em linguagens de programação, plataformas operacionais e formatos diferentes. Nem sempre, essa passagem é fácil.
- Mudança é inevitável – Aplicações sempre mudam ao longo do tempo (aliás, esse é o grande desafio das disciplinas de engenharia). Qualquer solução de integração precisa permanecer alinhada com essas mudanças.
As falhas da rede implicam em adotar diversas estratégias, incluindo chamadas idempotentes, handshakes, políticas de retentativa e circuit-breakers.
Para integrações com serviços externos, surgem questões relacionadas a versionamento de APIs e continuidades.
Exemplo de discussão arquitetural para integração de dados
Como fazer com que duas ou mais aplicações (potencialmente serviços ou microsserviços) que utilizam os dados de um determinado tipo de entidade, operem de forma eventualmente consistente, com o mínimo de acoplamento, sem sobrecarregar a rede e sem introduzir pontos críticos de falha?
Geralmente, fazer com que todas as aplicações utilizem o mesmo banco de dados não é a melhor escolha. Afinal, essa decisão faria com que todos os sistemas operassem de maneira extremamente acoplada tornando a evolução mais lenta. Além disso, o banco em si se converteria em um ponto crítico de falha. Por outro lado, trata-se da solução com o menor custo de desenvolvimento e parece “OK” em cenários onde o schema está estável e o time de desenvolvimento das aplicações seja o mesmo.
Desenvolver um serviço que opere como “fonte da verdade” para um determinado tipo de entidade, sendo consumido por todos os demais serviços, também não parece ser uma estratégia muito inteligente. Afinal, o acoplamento não seria em função do schema do banco de dados, mas em função do contrato do serviço. Além disso, o serviço também seria um ponto crítico de falhas (sofrendo instabilidades, comprometeria potencialmente o sistema como um todo). De qualquer forma, seria “OK” caso o volume de consumo fosse pequeno.
A melhor estratégia parece ser fazer com que cada serviço mantenha uma cópia dos dados que precisa para funcionar, pelo menos para as operações on-line. Dessa forma, seria necessário mais espaço para armazenamento (o que custa pouco), mas não haveria implicações com instabilidades externas (sem pontos de falha) e não haveria sobrecarga desnecessária na estrutura, principalmente se a frequência de modificação dos dados é pequena. De qualquer forma, trata-se da abordagem com maior complexidade associada e complexidade é custo.
Lembre-se sempre de ponderar a respeito de risco e custo na seleção de soluções arquiteturais. A “melhor” solução é sempre contextual. |
Integrando com sistemas legados
Sistemas legados eventualmente não fornecem interfaces adequadas para integração. A saída, frequentemente, passa pela adoção de “interfaces adaptadoras”.
Eventualmente, a solução poderá ser uma API preparada para atender demandas de sistemas modernos, de maneira “reativa”.
A interface adaptadora também poderá ser “ativa”, “escutando” mudanças de estado no legado e “encaminhando” para sistemas modernos, de maneira pró-ativa.
Raramente valerá a pena modificar “o fonte” de um sistema legado com base de código antiga e desenvolvida em tecnologia ultrapassada.
Ao realizar integrações com sistemas legados, considere desenvolver “interfaces adaptadoras”. |
A lei de Hyrum
Interessante observar que, na prática, nem todas as integrações de um software nascem com a anuência do time que o desenvolve. Não raro, relacionamentos são estabelecidos com base em características não documentadas de aplicações ocasionando em dificuldades para a evolução. Essa realidade é retratada por Hyrum Wright, engenheiro da Google, em uma “lei” de engenharia de software que leva seu nome.Com um número suficiente de usuários, não importa o que estiver acertado em contrato: todos os comportamentos observáveis de um sistema serão premissas para funcionamento de outros artefatos. Hyrum Wright |
Tal realidade é tão frequente que foi “piada” no xkcd.
Detalhes técnicos de implementação como tempos de resposta, ordenação em resultados, esquemas de bancos de dados, mecanismos de persistência e, até mesmo, detalhes de infraestrutura de uma aplicação servem, invariavelmente, como fundamento para desenvolvimento de processos e outros sistemas.
Esquemas de banco de dados, por exemplo, mesmo que oficialmente privados e restritos aos times técnicos da organização desenvolvedora, são frequentemente utilizados para desenvolvimento de mecanismos de integração.
Quanto maior o número de usuários de um software, maiores são as possibilidades de clientes precisarem permanecer em versões antigas. Afinal, estes clientes poderão ter construído processos e ferramentas usando como base comportamentos do sistema que não foram preservados em versões mais novas. A consequência direta disso é o aumento dos custos da empresa desenvolvedora pela necessidade de manter suporte a versões legadas, mesmo sem gerar valor novo.Toda grande jornada tem um primeiro passo…
As decisões de design que se relacionam com a arquitetura garantem o atendimento dos objetivos do negócio, respeitando restrições e atingindo atributos de qualidade. Não raro, todos estes elementos tem relação direta com os relacionamentos do software que está sendo arquitetado no ambiente que irá operar.
Quanto antes os responsáveis pela elaboração da arquitetura desenvolverem familiaridade com as integrações que irão ser suportadas, maiores as chances de sucesso! Por isso, a recomendação é explicitar essas integrações no início do esforço de desenvolvimento. Além disso, garantir que os artefatos de documentação gerados se mantenham atualizados.
Explicitar as integrações do software são uma boa forma de integrar novos desenvolvedores ao time de trabalho.
// TODO
Antes de avançar para o próximo capítulo recomendo as seguintes atividades:
- Utilizando o modelo C4, desenvolva representações do software que está desenvolvendo nos níveis de contexto e contêiner.
- Pondere sobre quais abordagens de integração estão sendo utilizadas atualmente. Quais as “dores” percebidas nas escolhas feitas?
- Reflita sobre os impactos da organização dos times em sua organização na forma como as integrações são feitas
- Reflita sobre a lei de Hyrum e o software que está desenvolvendo. Há indícios de integrações desenvolvidas “apesar” das especificações?
Em um service bus, quais as formas mais interessantes para lidar com cargas históricas de dados?
No item [Exemplo de discussão arquitetural para integração de dados] não seria interessante explicar o teorema CAP? No modelo A, existe alta coesão abrindo mão de disponibilidade e resistência a partição. No modelo B escalando a API dá para melhorar a disponibilidade abrindo mão de coesão (concorrência entre vários PODs no cluster) mas o banco ainda continua sendo ponto central de falha. No modelo C tem alta resistência a partição e alta disponibilidade e quase nenhuma garantia de coesão. Também colabora com a ideia de que nenhum modelo é absolutamente melhor.