Desenvolvimento

23 jun, 2016

Além da programação funcional com Elixir e Erlang

Publicidade

Eu gostaria de adicionar uma perspectiva levemente diferente para programação funcional no Erlang VM: programação funcional não é o objetivo do Erlang VM. Esse é um meio para um fim.

Com o Erlang VM e a linguagem Erlang tomando forma, Joe, Mike e Robert não objetivam implementar uma linguagem de programação funcional, eles procuraram um runtime no qual tivessem builds distribuídas, tolerância a falhas de aplicação. Aconteceu que o fundamento para escrever tais sistemas compartilha muitos dos princípios de programação funcional. E reflete tanto em Erlang e Elixir.

Portanto, a discussão se torna muito mais interessante quando você pergunta sobre as suas metas finais e como a programação funcional ajudou a alcançá-los. Quanto mais exploramos essas metas, percebemos como elas empatam com a imutabilidade e o controle do estado compartilhado, por exemplo:

  • Tolerância a falhas: se você tiver duas entidades em seu software que trabalham na mesma área de dados e uma delas falhar (ou seja, gerar uma exceção), como você garante que a entidade falhou e não deixou um estado corrupto? Em Elixir, você isola as entidades em trheads leves de processos de execução de chamada e garante que o seu estado não é compartilhado (a coordenação acontece ao longo da comunicação);
  • Concorrência: muitas das questões em escrever software concorrente em OO e linguagens imperativas vêm de gerenciamento de estado mutável compartilhado. Uma vez que tanto a partilha (através de um namespace global) quanto a mutabilidade são o modo padrão das operações nessas linguagens, é mais difícil de identificar as partes de dados que você pode obter em apuros. Com a imutabilidade como um padrão, as partes mutáveis em que você efetivamente precisa se concentrar ao escrever software concorrente vão se destacar e darão aos desenvolvedores mais precisão ao abordar condições de corrida;
  • Manutenção: o fundamento para escrever um código mais sustentável tanto em Erlang e Elixir vem da programação funcional. Dados imutáveis garantem aos dados nenhuma alteração mais longa sob os nossos pés! Pattern-matching traz concisão, protocolos introduzem polimorfismo dinâmico apoiado por contratos explícitos etc.

Os exemplos acima são o motivo de eu preferir, na maioria das vezes, introduzir Elixir como uma linguagem para a construção de sistemas sustentáveis e robustos. E enquanto algumas das semânticas funcionais podem variar entre Erlang e Elixir (religação, pipelines etc.), elas ainda são meios para um fim. Passado isso, a base para a construção de aplicações de tolerância a falhas e distribuição em ambas as linguagens é precisamente a mesma, já que ambas são construídas em cima da mesma VM e da plataforma OTP.

Isso não é dizer que o aspecto funcional não é importante. Ele definitivamente é! Costumo resumir programação funcional como um paradigma que nos obriga a adaptar os componentes complexos de nosso sistema explícito e que é uma diretriz importante quando se escreve software. Felizmente, muitas das lições de programação funcional podem ser aplicadas a outras linguagens e plataformas não-PF.

No entanto, os outros objetivos finais são menos portáteis. Simultaneidade deve vir a partir do ground-up: o runtime deve fornecer abstrações eficazes, e os desenvolvedores devem ter um bom conjunto de ferramentas para debater sobre elas. Tolerância a falhas é ainda mais complicado, uma vez que não pode ser local e não pode ser aplicada a uma parte da sua aplicação. Todo o ecossistema deve ser construído em cima dos mesmos princípios; caso contrário, o “elo mais fraco da cadeia” será sempre quebrado.

Se você está construindo serviços que se destinam a executar 24/7 e servir a múltiplos clientes (e a maioria dos serviços de rede e aplicações web deve fazer precisamente isso), você deve escolher uma plataforma que forneça simultaneidade, robustez e capacidade de resposta a partir do ground-up. Você quer dar a melhor experiência de usuário para tantos usuários quanto possível.

Mais importante ainda, essas preocupações vão muito além do ponto de vista da infraestrutura. Os desenvolvedores geralmente associam desempenho e simultaneidade com o rendimento do seu aplicativo (quantas solicitações  podem entregar por segundo), mas tais capacidades também afetam diretamente a produtividade do programador. Se a compilação de código é lenta, ou a sua aplicação leva tempo para iniciar, ou a sua suíte de teste se estende ao longo de minutos, eles se tornam obstáculos que o programador deve superar diariamente para escrever o código. Obstáculos que poderiam ser vencidos por um tempo de execução mais eficiente e concorrente. Afinal, em 2016, quase tudo que você faz no seu ambiente de programação deve estar usando todos os núcleos disponíveis.

Aqui está um exercício rápido: imagine que você tem um conjunto de testes intensivos de CPU que levam 2 minutos para serem executados através de um single-core. Se a sua máquina tem 4 núcleos, seu tempo de execução poderia ser reduzido idealmente para 30 segundos. No entanto, dado que é pouco provável para a totalidade da suíte ser intensiva de CPU e executar plenamente em paralelo, se assumirmos a paralelização de 80%, a nossa suíte ainda vai levar aproximadamente apenas 48 segundos, o que é 2,5 vezes mais rápido.

Uma base forte não só garante que seus usuários terão uma experiência mais fluida e robusta, mas também que os desenvolvedores terão iterações mais produtivas e proveitosas. É por isso que ferramentas como o Elixir´s Mix põem um grande esforço para não só executar seus testes de forma assíncrona, mas também para compilar todo o seu código em paralelo e tão rápido quanto possível. As abstrações que fornecem tolerância a falhas também darão aos desenvolvedores uma grande quantidade de introspecção em ambos os ambientes de produção e desenvolvimento. O fato de Erlang e Elixir terem sido construídos com essas preocupações em mente é o que os torna uma das melhores opções para escrever tal software lá fora.

Eu gostaria de agradecer a Robert Virding pela revisão do artigo. Ainda assim, todas as opiniões e imprecisões são minhas.

***

José Valim faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://blog.plataformatec.com.br/2016/05/beyond-functional-programming-with-elixir-and-erlang/