Diagramas de reatividade no shiny (reactlog)

O meu maior desafio durante o desenvolvimento de um Shiny app complexo é a construção do fluxo de reatividade. Não foram raras as vezes que gastei horas pensando em uma lógica de programação que gerasse o comportamento que eu gostaria ou que simplesmente fizesse o app funcionar.

Além de a reatividade ser um conceito abstrato e invisível no código, precisamos não apenas garantir que o app funcione, mas também que funcione adequadamente. Se ao mudar o valor de um slider, por exemplo, a gente espera que um gráfico seja atualizado, dois problemas podem surgir: (1) o gráfico não ser recalculado e (2) o gráfico ser recalculado mais de uma vez.

Os dois problemas indicam um fluxo de reatividade mal construído. A diferença é que no primeiro caso o app não funciona e no segundo ele funciona de maneira inadequada.

Para evitar esses problemas, podemos imaginar ou desenhar o fluxo de reatividade para investigar onde está a falha. Essa é uma tarefa simples em apps com poucos inputs e outputs, mas extremamente difícil ou inviável em apps complexos.

Nesses casos, ou mesmo nos casos simples, podemos utilizar o pacote reactlog. Com ele, além de criarmos facilmente o diagrama do fluxo de reatividade de qualquer Shiny app, podemos olhar o que acontece por trás das curtinas da reatividade quando executamos o aplicativo.

Antes de mais nada, instale o pacote reactlog.

install.packages("reactlog")

Em seguida, no Console, rode o código abaixo. Isso vai habilitar o reactlog para qualquer app que você rodar na sessão de R atual.

options(shiny.reactlog = TRUE) 

Por fim, rode o seu app e utilize o comando CTRL + F3 (no Mac, command + F3). O seu navegador abrirá uma nova aba com o diagrama de reatividade. Veja o exemplo a seguir. Primeiro temos a UI de um aplicativo que gera o histograma de uma amostra com distribuição normal. O tamanho da amostra é determinado pelo sliderInput. Sempre que o tamanho da amostra muda, o gráfico é recalculado.

Shiny app que mostra o histograma de uma amostra com distribuição normal. O tamanho da amostra é determinado por um sliderInput.

Figura 1: Shiny app que mostra o histograma de uma amostra com distribuição normal. O tamanho da amostra é determinado por um sliderInput.

Veja agora o diagrama de reatividade associado a esse app. A forma dos 4 elementos mais a esquerda representa inputs ou valores reativos, a forma do elemento plotObj representa expressões reativas e a forma do elemento output$hist representa os outputs (ou observadores).

Diagrama de reatividade do app anterior criado pelo pacote reactlog.

Figura 2: Diagrama de reatividade do app anterior.

Parece muito mais complicado do que deveria, né? Acontece que além do input e output, o diagrama também apresenta elementos referentes ao tamanho da janela da pessoa que está utilizando o app. Esses elementos influenciam na imagem produzida para o gráfico dentro do HTML, que é redimensionada a depender do tamanho da tela. Por isso a existência do elemento intermediário plotObj, que guarda as instruções para gerar o gráfico criadas pelo código R. Assim, o código R no servidor não precisa ser rodado novamente para que a imagem do gráfico seja redimensionada.

Podemos filtrar o diagrama para mostrar apenas o fluxo relacionado aos inputs do aplicativo escrevendo input no campo de busca. Repare também que os comandos no canto superior esquerdo permitem visualizar o fluxo de reatividade das ações realizadas entre a inicialização do app e o momento em que criamos o diagrama (quando pressionamos CTRL + F3).

Diagrama de reatividade do app anterior criado pelo pacote reactlog.

Figura 3: Diagrama de reatividade do app anterior.

Em resumo, com um diagrama de reatividade em mãos, podemos:

  • ver os inputs dos quais cada output depende e não depende;

  • investigar porque o código de um output não é rodado ou roda duas vezes quando acionamos um input do qual ele deveria depender;

  • ter uma visão menos abstrada do fluxo de reatividade e entender melhor o que acontece quando executamos cada parte do nosso app.

Um ponto importante: por razões de segurança e performance, nunca habilite o reaclog em ambientes de produção. Quando ele está habilitado, qualquer pessoal utilizando o seu app pode ver pelo menos parte do seu código fonte (que eventualmente pode conter informações sensíveis).

Você pode aprender mais sobre o funcionamento do reaclog clicando aqui.

É isso! Dúvidas, sugestões e críticas, mande aqui nos comentários. Até a próxima!

comments powered by Disqus