5 Coisas a Saber Sobre Programação Reativa

By Clement Escoffier 30 de junho de 2017Agosto 6 de 2020

Reativo, que palavra sobrecarregada. Muitas coisas acabam por se tornar magicamente Reativas hoje em dia. Neste post, vamos falar sobre Programação Reativa, ou seja, um modelo de desenvolvimento estruturado em torno de fluxos de dados assíncronos.

Eu sei que você está impaciente para escrever sua primeira aplicação reativa, mas antes de fazê-lo, há um par de coisas a saber. Usar programação reativa muda como você projeta e escreve seu código. Antes de pular no trem, é bom saber para onde você está indo.

Neste post, vamos explicar 5 coisas sobre programação reativa para ver o que ela muda para você.

Ao usar programação reativa, os fluxos de dados vão ser a coluna vertebral da sua aplicação. Eventos, mensagens, chamadas e até mesmo falhas serão transmitidas por um fluxo de dados. Com programação reativa, você observa esses fluxos e reage quando um valor é emitido.

Então, em seu código, você vai criar fluxos de dados de qualquer coisa e de qualquer coisa: eventos de clique, solicitações HTTP, mensagens ingeridas, notificações de disponibilidade, alterações em uma variável, eventos de cache, medidas de um sensor, literalmente qualquer coisa que possa mudar ou acontecer. Isso tem um efeito colateral interessante em sua aplicação: ela está se tornando inerentemente assíncrona.

Reativa eXtension (http://reactivex.io, a.ka. RX) é uma implementação dos princípios de programação reativa para “compor programas assíncronos e baseados em eventos usando seqüência observável”. Com o RX, o seu código cria e subscreve fluxos de dados chamados Observables. Enquanto Programação Rativa é sobre os conceitos, RX fornece a você uma caixa de ferramentas surpreendente. Combinando os padrões do observador e do iterador e idiomas funcionais, o RX dá-lhe superpoderes. Você tem um arsenal de funções para combinar, fundir, filtrar, transformar e criar os fluxos de dados. A próxima figura ilustra o uso do RX em Java (usando https://github.com/ReactiveX/RxJava).

Embora RX não seja a única implementação dos princípios de programação reativa (por exemplo podemos citar BaconJS – http://baconjs.github.io), ele é o mais comumente usado hoje em dia. No resto deste post, vamos usar Rx Java.

2. Os observáveis podem ser frios ou quentes – e isso importa.

Neste ponto, você está tentando ver quais são os diferentes streams (ou observáveis) com os quais você vai lidar no seu programa. Mas há duas classes de fluxos: quente e frio. Entender a diferença é a chave para usar com sucesso a programação reativa.

Os observáveis frios são preguiçosos. Eles não fazem nada até que alguém os comece a observar (subscreva em RX). Eles só começam a funcionar quando são consumidos. Os fluxos frios são usados para representar ações assíncronas, por exemplo, que não serão executadas até que alguém esteja interessado no resultado. Outro exemplo seria um download de arquivo. Ele não vai começar a puxar os bytes se ninguém vai fazer algo com os dados. Os dados produzidos por um fluxo frio não são compartilhados entre os assinantes e quando você assina você recebe todos os itens.

Os fluxos quentes são ativos antes da assinatura como um ticker de ações, ou dados enviados por um sensor ou um usuário. Os dados são independentes de um assinante individual. Quando um observador subscreve um hot observable, ele obterá todos os valores no fluxo que são emitidos depois de subscrever. Os valores são partilhados entre todos os subscritores. Por exemplo, mesmo que ninguém tenha subscrito um termômetro, ele mede e publica a temperatura atual. Quando um assinante se inscreve no fluxo, ele recebe automaticamente a próxima medida.

Por que é tão importante entender se seus fluxos são quentes ou frios? Porque muda a forma como o seu código consome os itens transportados. Se você não estiver inscrito em um hot observable, você não receberá os dados, e estes dados serão perdidos.

Desenvolver usando os produtos mais valiosos da Red Hat

A sua inscrição desbloqueia os produtos e o treinamento técnico da Red Hat sobre o desenvolvimento de aplicativos na nuvem corporativa.

Desenvolvimento de Chapéu Vermelho Juntado

Mordidas assíncronas mal utilizadas

Existe uma palavra importante na definição de programação reativa: assíncrona. Você é notificado quando os dados são emitidos no fluxo assíncrono – significando independentemente do fluxo do programa principal. Ao estruturar seu programa em torno de fluxos de dados, você está escrevendo código assíncrono: você escreve código invocado quando o fluxo de dados emite um novo item. Threads, código de bloqueio e efeitos colaterais são assuntos muito importantes neste contexto. Vamos começar com efeitos colaterais.

Funções sem efeitos colaterais interagem com o resto do programa exclusivamente através de seus argumentos e valores de retorno. Efeitos colaterais podem ser muito úteis e são inevitáveis em muitos casos. Mas eles também têm armadilhas. Ao usar programação reativa, você deve evitar efeitos colaterais desnecessários, e ter uma intenção clara quando eles os usam. Portanto, abrace a imutabilidade e as funções livres de efeitos colaterais. Enquanto alguns casos são justificados, o abuso de efeitos colaterais leva a trovoadas: thread safety.

Esse é o segundo ponto importante: threads. É bom observar os fluxos e ser notificado quando algo interessante acontece, mas você nunca deve esquecer quem está lhe chamando, ou mais precisamente em que thread suas funções são executadas. É altamente recomendado evitar usar demasiados threads no seu programa. Programas assíncronos que dependem de múltiplos threads se tornam um difícil quebra-cabeças de sincronização, muitas vezes terminando como uma caçada de deadlock.

Esse é o terceiro ponto: nunca bloqueie. Como você não é dono do thread que o chama, você deve ter certeza de nunca bloqueá-lo. Se você fizer isso você pode evitar os outros itens a serem emitidos, eles serão protegidos até … que o buffer esteja cheio (neste caso, a contrapressão pode fazer efeito, mas este não é o tópico deste post). Combinando RX e IO assíncrono você tem tudo o que precisa para escrever código sem bloqueio, e se quiser mais, veja Eclipse Vert.x, um toolkit reativo promovendo reatividade e assíncronia. Por exemplo, o seguinte código mostra o Cliente Web Vert.x e é RX API para recuperar um documento JSON do servidor e exibir a entrada de nome:

client.get("/api/people/4").rxSend().map(HttpResponse::bodyAsJsonObject).map(json -> json.getString("name")).subscribe(System.out::println, Throwable::printStackTrace);

Note o método de assinatura neste último trecho. É necessário um segundo método chamado quando uma das etapas de processamento lança uma exceção. Pegue sempre as exceções. Se você não o fizer, você passará horas tentando entender o que está errado.

4. Mantenha as coisas simples

Como você sabe, “Com grande poder vem grande responsabilidade”. RX fornece muitas funções muito fixes, e é fácil inclinar-se para o lado escuro. Encadear flapmap, tentar novamente, debounce, e zip faz você se sentir como um ninja… MAS, nunca esqueça que um bom código precisa ser legível por outra pessoa.

Deixe pegar algum código…

manager.getCampaignById(id) .flatMap(campaign -> manager.getCartsForCampaign(campaign) .flatMap(list -> { Single<List<Product>> products = manager.getProducts(campaign); Single<List<UserCommand>> carts = manager.getCarts(campaign); return products.zipWith(carts, (p, c) -> new CampaignModel(campaign, p, c)); }) .flatMap(model -> template .rxRender(rc, "templates/fruits/campaign.thl.html") .map(Buffer::toString)) ) .subscribe( content -> rc.response().end(content), err -> { log.error("Unable to render campaign view", err); getAllCampaigns(rc); });

Dar um exemplo como este pode ser difícil de entender não? Ele encadeia várias operações assíncronas (flatmap), junte outro conjunto de operações (zip). O código de programação reativa primeiro requer um deslocamento de mente. Você é notificado de eventos assíncronos. Depois, a API pode ser difícil de compreender (basta olhar para a lista de operadores). Não abuse, escreva comentários, explique ou desenhe diagramas (tenho certeza que você é um artista asciartista). RX é poderoso, abusar ou não explicá-lo fará seus colegas de trabalho rabugentos.

5. Programação reativa != Sistema reativo

Provavelmente a parte mais confusa. Usar programação reativa não constrói um sistema reativo. Sistemas reativos, como definido no manifesto reativo, são um estilo arquitetônico para construir sistemas distribuídos responsivos. Sistemas reativos podem ser vistos como sistemas distribuídos feitos corretamente. Um sistema reativo é caracterizado por quatro propriedades:

  • Responsive: um sistema reativo precisa lidar com as solicitações em um tempo razoável (eu deixo você definir razoável).
  • Resiliente: um sistema reativo precisa permanecer responsivo diante de falhas (crash, timeout, 500 erros… ), então ele precisa ser projetado para falhas e lidar com elas apropriadamente.
  • Elástico: um sistema reativo precisa permanecer responsivo sob várias cargas. Consequentemente, ele deve escalar para cima e para baixo, e ser capaz de lidar com a carga com recursos mínimos.
  • Message driven: componentes de um sistema reativo interagem usando a passagem assíncrona de mensagens.

Apesar da simplicidade destes princípios fundamentais dos sistemas reativos, construir um deles é complicado. Tipicamente, cada nó precisa abraçar um modelo de desenvolvimento assíncrono não obstrutivo, um modelo de simultaneidade baseado em tarefas e usa E/S não obstrutivas. Se você não pensar nesses pontos primeiro, será rapidamente uma placa de spaghetti.

Reactive Programming and Reactive eXtension fornece um modelo de desenvolvimento para domar a besta assíncrona. Ao usá-lo sabiamente, o seu código vai permanecer legível e compreensível. No entanto, o uso de programação reativa não transforma seu sistema em um Sistema Reativo. Sistemas Reativos são o próximo nível.

Conclusão

Finalmente chegamos ao fim deste post. Se você quiser ir mais longe e estiver interessado em sistemas reativos, recomendo dar uma olhada no Eclipse Vert.x – um conjunto de ferramentas para construir sistemas reativos e distribuídos (http://vertx.io), e nos Microservices Reativos em Java minibook disponíveis a partir de https://developers.redhat.com/books/building-reactive-microservices-java. A combinação de Vert.x e Reactive eXtension liberta a sua superpotência reactiva. Você pode não só usar programação reativa, mas também construir sistemas reativos e ter acesso a um ecossistema emocionante e em crescimento.

Codificação Feliz!

Download do Eclipse Vert.x cheat sheet, este cheat sheet fornece detalhes passo a passo para permitir que você crie seus aplicativos da maneira que você quiser.

Deixe uma resposta

O seu endereço de email não será publicado.