Conteúdo


Desenvolvendo aplicativos rapidamente (parte 4): utilizando padrões de desenvolvimento

Comments

[Roland Barcia (IBM Distinguished Engineer/CTO) e Kyle Brown (IBM Distinguished Engineer/CTO) colaboraram com o Rick nesta publicação. - Ed.]

Nesta série em sete partes sobre desenvolvimento de aplicativos de microsserviços, fornecemos um contexto para definir um projeto piloto baseado em nuvem que melhor se ajusta às atuais necessidades e prepara para uma decisão de adoção da nuvem em mais longo prazo.

Aqui, na parte 4: consideramos os padrões para desenvolver aplicativos de microsserviços.

Esta é uma orientação para a série em geral:

Padrões de desenvolvimento

Martin Fowler criou o princípio de projeto segundo o qual uma equipe deve organizar os microsserviços de um aplicativo em torno dos recursos comerciais essenciais. Há padrões estabelecidos para o desenvolvimento de microsserviços de aplicativos monolíticos que sua equipe está transformando e para o desenvolvimento de microsserviços em um contexto novo e nativo da nuvem.

Independentemente do caminho que você esteja seguindo para a adoção da nuvem, esses padrões fornecem uma estrutura básica para a evolução de um aplicativo baseado em microsserviços.

Padrão de Single Page Application (SPA)

Com a convergência de navegadores mais poderosos, redes mais rápidas e idiomas no lado do cliente, muitas interfaces da Web começaram a incorporar todas as funcionalidades em aplicativos de uma só página. O usuário entra por meio de uma interface que nunca recarrega a página inicial nem navega para fora dessa experiência inicial. Construídos com uma combinação de HTML, CSS e JavaScript, esses aplicativos respondem às entradas dos usuários por meio de chamadas de serviço dinâmicas a serviços de apoio baseados em REST que atualizam partes da tela em vez de fazer o redirecionamento para uma página totalmente nova. Muitas vezes, essa arquitetura de aplicativo simplifica a experiência de front-end e, em compensação, os serviços de apoio têm mais responsabilidade.

Padrão de Back-end para Front-end (BFF)

Embora um aplicativo de uma só página funcione bem para experiências de usuário de canal único, esse padrão entrega resultados ruins entre as experiências de usuário por meio de diferentes canais, às vezes sobrecarregando um navegador com interações de gerenciamento com muitos serviços de apoio assíncronos baseados em REST.

Um padrão de Back-end para Front-end evoluiu, no qual um serviço agregador de back-end reduz o número geral de chamadas do navegador e gerencia a maior parte da comunicação dentro dos serviços de apoio externos, por fim retornando ao navegador uma única solicitação mais facilmente gerenciada. O padrão permite que as equipes de front-end desenvolvam e implementem seu próprio serviço agregador de back-end (o BFF) para gerenciar todas as chamadas de serviço externo necessárias para sua experiência do usuário específica, frequentemente construída para um navegador, uma plataforma móvel ou um dispositivo de IOT específico. A mesma equipe constrói tanto a experiência do usuário quanto o BFF, muitas vezes no mesmo idioma, resultando em um aumento no desempenho geral do aplicativo e na entrega do aplicativo.

Nesta arquitetura, por exemplo, você vê uma camada de microsserviços alcançada por meio do gateway da API de front-end. Esses BFFs (Serviços móveis, Web, Compartilhado) acionam outra camada de microsserviços Java reutilizáveis. Em um projeto no mundo real, geralmente uma equipe diferente escreverá esses microsserviços. Os BFFs e os microsserviços Java se comunicam entre si usando uma malha de microsserviços (como o Istio).

Padrões de entidades e agregados

Uma entidade é um objeto que é diferenciado principalmente por sua identidade. As entidades são os objetos do processo de modelagem que têm identificadores exclusivos.

Em seu livro Domain-Driven Design, Eric Evans explica que os objetos de entidade precisam de ciclos de vida de objetos bem definidos e de uma boa definição do que é a relação de identidade raiz, o que significa que eles devem ser iguais a outra coisa.

A partir da modelagem de relação de entidades, sabemos que, às vezes, as entidades são bem definidas e têm um identificador específico conhecido, mas podem nem sempre viver de forma independente. Uma combinação de entidades é um agregado. Nos casos em que temos um cluster de entidades que precisam ser mantidas consistentes em uníssono, podemos nos referir a ela entidades como entidades dependentes e precisamos nos certificar de que sabemos qual é a raiz do agregado, pois a raiz define o ciclo de vida das entidades dependentes.

Para equipes de desenvolvimento que não estão acostumadas a projetar em termos de interfaces comerciais, os padrões de entidades e agregados são úteis para identificar conceitos de negócios específicos que são mapeados diretamente aos microsserviços, executando funções comerciais abrangentes.

Obviamente, optar por implementar cada entidade comercial como um microsserviço não é o fim de seus problemas de projeto. É necessário pensar também em como implementar o microsserviço e como esse microsserviço está relacionado aos outros serviços em seu aplicativo comercial geral.

Os microsserviços comerciais tendem a ser stateful e a ter seus próprios dados em um banco de dados gerenciado.

Padrões de serviços

Os padrões de serviços oferecem uma maneira de mapear operações que não pertencem conceitualmente a nenhum objeto/entidade específico nem se agregam a uma abordagem baseada em entidade.

Evans sugere que esses objetos sejam modelados como interfaces independentes chamadas de serviços e que seguem estas regras:

  • Devem ser stateless
  • A interface do serviço é definida em termos de outros elementos de seu modelo de domínio (objetos de valores e entidades)
  • O serviço refere-se a um conceito de domínio que não corresponde naturalmente a qualquer objeto específico de valor ou entidade.

Padrão de microsserviços adaptadores

O padrão de microsserviços adaptadores faz a adaptação, conforme necessário, entre uma API orientada aos negócios construída usando técnicas RESTful ou de sistema de mensagem leve (com as mesmas técnicas orientadas por domínio de um microsserviço tradicional) e uma API existente ou um serviço SOAP tradicional baseado em WS-*.

A adaptação é necessária, por exemplo, quando uma equipe de desenvolvimento não tem controle descentralizado sobre a origem de dados de um aplicativo.

Um microsserviço adaptador agrupa e converte serviços existentes (geralmente baseados em função) em uma interface REST baseada em entidade. Esse tipo de microsserviço trata cada nova interface de entidade como um microsserviço e a constrói, gerencia e dimensiona de forma independente.

Em muitos casos, a conversão de uma interface baseada em função (por exemplo, uma construída usando SOAP) em uma interface baseada em conceito de negócios é direta. Pense nisso como mudar de uma abordagem baseada em verbo (funcional) para uma abordagem baseada em substantivo (entidade).

Frequentemente, as funções expostas em um terminal SOAP correspondem individualmente a operações CRUD (criar, ler, atualizar, excluir) em um único tipo de objeto comercial e, portanto, são facilmente mapeadas a uma interface REST.

Essas operações simplesmente enviariam as mensagens SOAP correspondentes ao terminal SOAP existente e, em seguida, converteriam os tipos de dados XML das operações SOAP correspondentes em tipos de dados JSON para a nova interface REST.

Padrões de aplicativo Strangler

Esse padrão aborda o fato de que os negócios e aplicativos nunca realmente vivem em um novo mundo. O padrão Strangler ajuda a gerenciar a refatoração de um aplicativo monolítico em estágios.

Como esse padrão é tão central para a transformação de aplicativos existentes em microsserviços, o que é um foco recorrente nesta série, vale a pena concentrar-se nele mais detalhadamente. O padrão obtém seu nome metafórico do fenômeno dos jardins em que um cipó estrangula a árvore na qual está enrolado.

A ideia é que você use a estrutura de um aplicativo da Web (o fato de serem construídos a partir de URIs individuais que mapeiam funcionalidades a diferentes aspectos de um domínio comercial) para dividir um aplicativo entre diferentes domínios funcionais e substituir esses domínios por uma nova implementação baseada em microsserviços, um domínio por vez. Esses dois aspectos formam aplicativos separados que vivem lado a lado no mesmo espaço de URI. Ao longo do tempo, o novo aplicativo refatorado substitui o aplicativo original até que seja possível encerrar completamente o aplicativo monolítico.

O padrão Strangler inclui estas etapas:

  • Transformar – crie um novo site paralelo (em uma plataforma de nuvem, como o Bluemix, por exemplo, ou em seu ambiente existente) que seja baseado na abordagem discutida na publicação anterior.
  • Coexistir – deixe o site existente onde está por um tempo. Faça o redirecionamento de forma incremental do site existente para o novo site para obter a nova funcionalidade implementada.
  • Eliminar – remova a antiga funcionalidade do site existente (ou simplesmente pare de fazer sua manutenção) à medida que o tráfego for redirecionado para fora dessa parte do site antigo.

O que é realmente excelente na aplicação desse padrão é que ele cria valor incremental em um período muito mais rápido do que se você tentasse fazer tudo em uma grande migração. Ele também fornece uma abordagem incremental para a adoção de microsserviços: se você observar que essa abordagem não funciona em seu ambiente por alguma razão, poderá mudar de direção facilmente, se necessário.

Qual é a melhor maneira de aplicar o padrão Strangler?

Se uma só página for muito pequena e um aplicativo inteiro for muito grande, qual será o nível certo de granularidade para aplicar o aplicativo Strangler? Para ter sucesso, você terá que entrelaçar dois aspectos diferentes da refatoração de aplicativo:

  • Refatoração de seu back-end para o projeto de microsserviços (a parte interna, digamos)
  • Refatoração de seu front-end para acomodar microsserviços e também para fazer quaisquer novas mudanças funcionais que estejam direcionando a refatoração (vamos chamar isso de parte externa)

Vamos começar com a parte interna:

  1. Inicie identificando os contextos limitados no projeto do seu aplicativo. Um contexto limitado é uma estrutura conceitual compartilhada que restringe o significado de diversas entidades em um conjunto maior de modelos de negócios. Em um aplicativo de empresa aérea, reserva de voos seria um contexto limitado, enquanto que o programa de fidelidade da empresa aérea seria um contexto limitado diferente. Embora possam compartilhar termos (como “voo”), a maneira como esses termos são usados e definidos é bem diferente.
  2. Escolha o contexto limitado que seja o menor e o menos dispendioso para xxx. Classifique seus outros contextos limitados de menos para mais complexo. Você deve iniciar com os contextos limitados menos complexos para comprovar o valor de sua refatoração (e resolver quaisquer problemas na adoção do processo) antes de assumir as tarefas de refatoração mais complexas (e potencialmente dispendiosas).
  3. Planeje os microsserviços conceitualmente dentro do contexto (aplicando os padrões de entidades, agregados e serviços). Nesse momento, não estamos tentando fazer um projeto detalhado de todos esses microsserviços. Estamos apenas tentando obter um entendimento de quais microsserviços provavelmente existem para que possamos usar essa aproximação no próximo conjunto de etapas.

Após concluir essa etapa, siga para a parte externa:

  1. Analise as relações entre as telas em sua UI existente. Especificamente, procure lentidões de grande escala que liguem diversas telas juntas. Se estiver construindo um website de empresa aérea, uma lentidão poderá ocorrer na reserva de uma passagem e será formada por diversas telas relacionadas que fornecem as informações necessárias para concluir o processo de reserva. Uma lentidão diferente pode estar centralizada na inscrição para o programa de fidelidade da companhia aérea. De qualquer forma, entender o conjunto de lentidões ajudará você a seguir para a próxima etapa de sua refatoração.
  2. À medida que você examina sua UI existente ou sua nova UI, deve procurar aspectos dela que correspondem aos microsserviços identificados na parte interna. É necessário identificar quais fluxos correspondem a quais microsserviços. O resultado dessa etapa é uma lista de lentidões de um lado da página, com uma lista dos microsserviços que podem possivelmente implementar cada lentidão do outro lado.
  3. Dimensione seu fragmento com base na suposição de que as mudanças na UI devem ser autoconsistentes. Sendo assim, suponha que uma ou mais lentidões tenham o tamanho mínimo de mudança que pode ser liberada a um cliente, mas o fragmento em si pode ser maior que uma lentidão. Por exemplo, você pode considerar que todo o programa de fidelidade do cliente seja um único fragmento, embora ele possa ser formado por dois ou três fluxos separados.
  4. Escolha se deseja liberar todo o fragmento de uma vez ou um fragmento como uma série de pequenas fatias.

O que fazer a partir daqui:

Rick Osowski


Recursos para download


Comentários

Acesse ou registre-se para adicionar e acompanhar os comentários.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Big data e análise de dados
ArticleID=1051511
ArticleTitle=Desenvolvendo aplicativos rapidamente (parte 4): utilizando padrões de desenvolvimento
publish-date=10252017