No desenvolvimento temos diversos desafios, um deles é como aliar experimentações e customizações em aplicações já publicadas. Mas para apoiar esses e outros usos surgiu o conceito de deploy em círculos.
Descubra neste artigo o que é deploy em círculos e como o Charles CD e o Beagle, projetos open source mantidos pela Zup, podem te ajudar com isso!
Experimentação, desenvolvimento e deploy
Ao criar uma aplicação mobile é de extrema importância propor uma interface de usuário dinâmica, coerente, amigável, enfim, que incentive e facilite o uso da aplicação.
Nesse sentido, promover uma experiência de usuário que busque otimizar a experimentação é um elemento chave no desenvolvimento de qualquer aplicação.
Mas pera lá… a experimentação individual e como cada usuário entende e se relaciona com uma interface é algo tão específico e amplo ao mesmo tempo conforme existem perfis de usuários diferentes, certo?
Caramba, então como devemos fazer? Como podemos otimizar essa qualidade de experimentação a ambientes em produção? Entendendo que aplicações devem ser amplas o bastante para agradar uma maioria, mas também específicas o bastante para conquistar determinados perfis de usuários? Para isso lhes apresento o Deploy em círculos!
Ok…mas o que esse cara faz?
Mas, o que é deploy em círculos?
O Deploy em círculos é uma estratégia de implementação de versões que permite que devs segmentem a base de usuários, considerando características, para que eles sejam redirecionados para variantes diferentes da aplicação.
No contexto de deploy em círculos, é possível definir qual versão estará presente em cada círculo e qual será o conjunto de características que determinam as pessoas que acessarão.
Com essa estratégia podemos ter em produção várias versões da mesma aplicação, por exemplo: uma versão padrão, outra que testa um fluxo novo etc…
Para isso, temos a ferramenta Charles C.D., projeto open source mantido pela Zup, que implementa essa técnica.
Como o Charles CD funciona
Ufa… é muita coisa né? Vamos recapitular rapidamente alguns conceitos e funcionalidades para entender como isso tudo é possível.
Primeiro, temos que entender o que o Charles CD faz. Inclusive, ele faz muito mais do que vamos falar aqui, se você quiser saber mais sobre o Charles da uma olhada na documentação deles que tá show, mas por hora…
O Charles é um projeto open source que realiza deploys, podendo atuar tanto no front quanto no backend, ou seja, com ele devs podem realizar os deploys do backend de uma aplicação. E é aqui que a coisa fica muito louca.
Ao desenvolver uma aplicação podemos utilizar o conceito de Server Driven UI e dessa forma fazer com que a interface do usuário (telas, componentes de tela, fluxo de telas etc) seja definida a partir do backend da aplicação, algo que chamamos carinhosamente de BFF (Backend For Frontend).
Dessa forma, é possível ter uma aplicação com vários BFFs, cada um com um comportamento de tela definido para um perfil de usuário (ou círculo de usuários!).
E é a partir daí que o Charles faz sua mágica utilizando o Deploy em círculos e assim definindo qual círculo de usuários navega em qual BFF!
Bora ver isso em um exemplo?
Vamos supor que uma aplicação de delivery de comida queira oferecer um fluxo de tela diferente para usuários de um bairro específico. Esse novo fluxo é iniciado em um card que só aparece para usuários desse bairro.
Em nosso exemplo temos a Alice, que mora no Centro da cidade e o Caio, que mora no bairro “EstomagoSemFim” (Bairro hipotético, porém estranhamente familiar).
Ambos acessam a aplicação normalmente e navegam de acordo com as opções, mas a tela que o Caio enxerga é diferente!
Como isso acontece e por quê?
Nesse exemplo temos dois backends que definem telas e fluxos de tela na aplicação. Um é o Default, conhecido carinhosamente pelos devs do Charles como “Mar Aberto”, esse é aquele BFF que será acessado por todos os usuários que não estejam em um círculo (calma que já fica mais claro). O outro é o BFF que tem o fluxo alternativo para a turma do bairro “EstomagoSemFim”, com um card diferente na tela.
O Charles CD (aquele cara que faz deploys) faz a orquestração do círculo em que cada usuário vai navegar utilizando o Circle matcher (já te conto melhor o que é).
Em outras palavras, a Alice, que não está em nenhum círculo, vai navegar na estrutura Default. Já o Caio será direcionado para o outro fluxo, com o card diferente e um novo fluxo.
Tá, mas o que é o Circle matcher?
O Circle matcher é um módulo do Charles que permite selecionar qual BFF será utilizado, ou seja, o matcher receberá uma informação de segmentação (como, por exemplo, o nome de um bairro) e a partir daí ele verifica a qual círculo essa informação seleciona e retorna o círculo que deu “match” na aplicação.
A partir desse momento, toda requisição de telas novas será feita informando o novo círculo, e o Charles retornará as telas de acordo com o círculo definido.
Isso é o que acontece a nível de aplicação:
Bora ver código?
Como configuro a minha aplicação?
Bom, para utilizar o circle matcher, precisamos perguntar para o Charles se existe um círculo para o Caio. Para isso devemos fazer uma requisição do tipo POST informando um CircleRequest como o Body da requisição, assim como no exemplo abaixo:
- Ah sim, vale ressaltar que em nosso caso de uso utilizamos o Retrofit como padrão para transmissão de dados entre aplicação e servidor.
- Outro ponto importante: nossas classes e códigos foram implementados na linguagem Kotlin! Mas é claro, nenhum uso das ferramentas se limita a uma linguagem…
interface CharlesService {
@POST("my-charlescd-circle-matcher/identify")
suspend fun getCircle(@Body request: CircleRequest): CirclesResponse
}
Ok, mas quem são esses caras novos? CircleRequest? CircleResponse?
O CircleRequest é uma classe de dados simples que vai mapear as informações enviadas ao Charles. Já a CircleResponse é a classe que receberá a lista de círculos que será a resposta do Charles à nossa aplicação.
É no CircleResquest que enviaremos as informações sobre o usuário que irão definir a qual círculo ele pertence e aí o céu é o limite. Você pode criar uma classe com as informações que desejar, por exemplo, em nossa classe informaremos apenas o nome do usuário e o nome do bairro em que ele está.
O workspaceId, que está indo escondidinho, é uma informação da sua conta do Charles que identifica quais BFFs fazem parte da aplicação que você está utilizando. Mas essa ID nem vem ao caso agora, é só para que você saiba mesmo o que é.
data class CircleRequest(val workspaceId: String, val requestData: RequestData)
data class RequestData(val nome: String? = null,val bairro: String? = null)
Uma vez que esses pontos estão definidos, seu ambiente está quase pronto!
Agora, você deve decidir quando fará essa requisição e guardar a resposta recebida em sua aplicação. Em nosso exemplo, o usuário é cadastrado e faz um login, e a informação de nome e bairro vem daí. Após a requisição temos uma resposta do servidor, que é um JSON no formato abaixo:
{
"circles":[
{
"id":"4691c647-4d93-41cc-9526-597cf2a37747",
"name":"bairro-esf"
}
]
}
O que aconteceu para termos essa resposta?
Ao requisitarmos a identificação do círculo, o Charles utiliza o Circle Matcher e retorna uma lista de círculos (BFFs) identificados a partir da informação do nome do bairro, ou seja, o nome do bairro indica ao Charles que o usuário do “bairro-esf” pertence a esse círculo.
Agora que entendemos o que aconteceu, bora lá!
Para que uso essa informação?
Nós manipulamos esse JSON usando a classe de resposta CircleResponse, que citamos anteriormente:
data class CirclesResponse(
val circles: List<Circle>
)
data class Circle(
val id: String
)
Essa informação sobre o círculo é muito importante, pois ela será utilizada nas próximas requisições que sua aplicação fizer ao backend!
Aí acontece o seguinte… Toda nova requisição de tela deve levar consigo uma informação no header com a ID do círculo que você recebeu, ou seja, identificando o círculo no qual a navegação deve ocorrer!
Para isso, temos que configurar a nossa camada de rede para dar esse “golpe jedi” e modificar a HEADER das requisições da sua aplicação!
Configurando o HEADER e o golpe do Interceptor
Aqui, o nosso mestre Jedi é o Retrofit. Com ele podemos utilizar a função addInterceptor, e modificar as requisições da aplicação. Aí ele fica mais ou menos assim:
httpClient.addInterceptor(object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val newRequest = chain.request().newBuilder()
.header("x-circle-id", "4691c647-4d93-41cc-9526-597cf2a37747")
.build()
return chain.proceed(newRequest)
}
})
Com esse cara configurado na sua camada de rede, toda nova requisição de telas levará a informação do círculo (id) que deseja no HEADER. Essa informação será então interpretada pelo Charles, que responderá a partir do círculo (BFF) informado!
Perceba que nesse exemplo colocamos a ID do círculo “4691c647-4d93-41cc-9526-597cf2a37747” diretamente no campo, mas claro, aqui cabe uma sugestão de colocar ali uma função que recupere o valor a partir de onde você o guardou em sua aplicação.
Conclusão
Falta muito Papai Smurf?
Ufa!! Falta não! Chegamos… Foi um pouquinho de chão para explicar direitinho, mas com isso a sua aplicação consegue utilizar o Deploy em círculos. Com esse conceito você vai conseguir dinamizar o acesso a fluxos diferentes ou mesmo a regras de negócio, como exemplificamos acima!
Esse é o Deploy em círculos! É a funcionalidade que te permite acessar diferentes deploys de um backend de uma aplicação de acordo com informações sobre os usuários, segmentando uso e navegação da aplicação como quiser.
Com esse recurso um enorme escopo de testes de funcionalidade se abre, dinamizando a experimentação dos usuários de uma aplicação e possibilitando um rápido feedback.
Caso tenha alguma dúvida não deixe de nos mandar um oi com suas dúvidas nos comentários!
Para saber mais sobre o Charles CD:
Dê uma olhadinha no canal do youtube e na documentação.
Para saber mais sobre o Beagle:
Dê uma espiada no nosso canal do youtube que tá show e também na nossa documentação também!
É win-win com certeza!