Skip to content

Instantly share code, notes, and snippets.

@Tiagoperes
Last active May 27, 2022 20:08
Show Gist options
  • Save Tiagoperes/673d23581194e48c147fd71d5714767a to your computer and use it in GitHub Desktop.
Save Tiagoperes/673d23581194e48c147fd71d5714767a to your computer and use it in GitHub Desktop.

Problema

Considere uma aplicação com dois módulos:

  • Client: código local
  • Vendor: lib terceira

Precisamos implementar a ideia de fluxo server driven. Os seguintes cenários devem ser contemplados (considere que os fluxos no lado direito devem retornar uma resposta para o fluxo do lado esquerdo):

  1. Fluxo Server Driven no módulo Client -> Outro fluxo Server Driven no módulo Client
  2. Fluxo nativo no módulo Cliente -> Fluxo Server Driven no módulo Client
  3. Fluxo Server Driven no módulo Client -> Fluxo nativo no módulo Client
  4. Fluxo Server Driven no módulo Client -> Fluxo Server Driven no módulo Vendor (com outra instância do Nimbus)
  5. Fluxo Server Driven no módulo Client -> Fluxo nativo no módulo Vendor
  6. Fluxo Server Driven no módulo Vendor -> Outro fluxo Server Driven no módulo Vendor
  7. luxo Server Driven no módulo Client -> Outro fluxo Server Driven no módulo Client -> Fluxo Server Driven no módulo Vendor

Independente de como o fluxo foi iniciado, ele deve ser completado exatamente da mesma maneira. O fluxo deve ser agnóstico de quem o chamou.

Exemplo

Considere:

  • um cliente com dois fluxos:
    • server driven qualquer;
    • nativo qualquer.
  • um vendor com três fluxos:
    • PIX (Server Driven);
    • Endereço (Server Driven);
    • Qualquer (nativo).

Fatos:

  • o fluxo de endereço pode ser chamado pelo fluxo de pix (server-driven apenas);
  • o fluxo de endereço pode ser chamado pelo fluxo server driven do cliente (server-driven inter-módulo);
  • o fluxo de endereço pode ser chamado pelo fluxo nativo qualquer do cliente (nativo para server-driven).

O desenho abaixo mostra algumas interações possíveis para esses fluxos:

Fluxos SD

Discussão

Análise inicial

Temos dois problemas para resolver:

  1. Executar um callback de resposta quando o fluxo for concluído.
  2. Navegar de volta para a página que chamou o fluxo quando ele for concluido.

Uma possível abordagem seria tratar esses problemas de forma separada. Mas ao modelar essa estratégia, percebemos que existe um espaço muito grande para erro e confusão: um fluxo poderia ser iniciado sem navegar para frente ou terminado sem navegar para trás, o que causaria uma inconsistência de dados. Dado que um fluxo terminou, quando exatamente navegar? Isso é bem confuso.

Precisamos seguir com uma abordagem que resolve ambos os problemas simultaneamente.

Múltiplos fluxos

Um fluxo SD do cliente pode precisar da resposta de um fluxo SD do vendor que pode precisar da resposta de outro fluxo SD do vendor.

Isso significa que precisamos de uma pilha de callbacks de completamento de fluxo. Completar um fluxo significa completar o fluxo no topo da pilha. Dessa forma podemos ter quantos fluxos quisermos.

O problema é cada um desses fluxos pode ter sido iniciado de uma forma diferente. Como vamos saber voltar para a view que iniciou o fluxo?

Uma estratégia seria:

  1. Empilhar um Fluxo(caller: id da view que iniciou o fluxo, onComplete: callback)
  2. Quando o fluxo completar, desempilha, executa onComplete e navega de volta para "caller"

Isso não é difícil de se fazer considerando que aconteceram apenas navegações server driven (push e present). Mas o que fazer com navegações nativas? Hoje não temos um conceito do tipo "goBackToNativeRoute(viewId)". É possível criar tal conceito? Se sim, bastaria adicionar ao fluxo um "isServerDrivenNavigation".

A pilha de fluxos seria uma propriedade do navegador e um navegador poderia iniciar a pilha com o callback passado no NimbusNavigator: NimbusNavigator(onComplete = { result -> print(result) }).

Como podemos inicializar a pilha de fluxos a partir do componente nativo (NimbusNavigator) e também podemos passar parâmetros no openNativeRoute (inclusive callbacks), conseguimos atingir todos os objetivos citados em "Problema".

Dificuldades:

  1. goBackToNativeRoute(viewId), essencial para essa abordagem, pode não ser possível.
  2. Para que isso funcionasse em navegações Server Driven, o popTo deveria olhar para toda pilha de navegação e não apenas para o present atual.
  3. Em uma navegação Server Driven o viewId é a URL. Se duas views com a mesma URL existir na pilha de navegação, mas a primeira for aquela que iniciou o fluxo, a operação popTo voltaria para a tela errada.

Fluxo único

As vezes a solução para um problema complexo é impedir que ele aconteça. Para isso, deveríamos limitar a ideia de fluxo:

Fluxo, nesta abordagem, é equivalente a Navegador. Para iniciar um fluxo, deve-se obrigatoriamente, criar um novo navegador na aplicação de frontend. Assim, não seria possível, a partir de um fluxo server driven, iniciar outro fluxo server driven sem passar por uma tela nativa.

Completar um fluxo significa chamar o callback "onComplete" do navegador com a resposta e fechar a tela que contém esse navegador.

Assim, se o usuário desejar acessar o fluxo de endereço (server driven) a partir do fluxo de PIX (server driven), dever-se-ia chamar openNativeRoute ao invés de push ou present.

Vantagens:

  • Parece ser bem mais simples de se implementar, apesar de eu não ter certeza de como fechar a tela do navegador;

Problemas:

  • Limitação sobre como iniciar os fluxos. Muitas vezes o usuário gostaria de fazer um present, por exemplo.
  • Necessidade de uma tratativa local, impedindo que seja 100% server driven.
  • Necessidade de implementar o NavigationContext, do Beagle. Pessoalmente, acho bem estranho passar variáveis para a página em uma navegação de volta. Além disso, esse tipo de passagem de dados é impossível de tipar no backend (pop).

Conclusão

Ainda não temos uma solução definida para este problema, estamos abertos a sugestões e discutiremos mais assim que concluirmos o primeiro Beta.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment