Nos últimos dias, vários artigos foram publicados no Habré, cujo leitmotivo geral (especialmente nos comentários) foi o confronto entre pessoas francas e pontudas - adeptos do PF contra a OLP, apesar de serem instados a não discutir. Erlang foi discutido algumas vezes, em relação ao qual lembrei de um pequeno post sobre Joe Armstrong, um dos criadores dessa linguagem, escrito por ele no final de 2018 no fórum Elixir em resposta a uma pergunta sobre o paradigma da linguagem. Eu acho que o comentário dele será interessante.
Joe Armstrong 12 setembro 2018
Todas as coisas boas do Elixir (e Erlang) estão relacionadas à concorrência - apenas criando processos e mensagens independentes. E essa é exatamente a essência da programação orientada a objetos, como Alan Kay repetidamente apontou.
OOP é totalmente dedicado a objetos. Os objetos respondem (ou devem responder) às mensagens e, quando você deseja fazer algo, envia uma mensagem ao objeto, e como ele processa é completamente irrelevante. Pense nos objetos como "caixas pretas" e, quando quiser algo deles - basta enviar mensagens, e eles enviarão mensagens em resposta.
Como tudo é organizado dentro, não importa se o código dentro da caixa preta é funcional ou imperativo - apenas o que exatamente ele deve fazer é importante.
Infelizmente, embora a primeira linguagem orientada a objetos de sucesso com base nesse modelo (Smalltalk) operasse nos conceitos de "objeto" e "mensagem", a última no Smalltalk não eram mensagens reais, mas apenas chamadas de funções síncronas mascaradas. O mesmo erro foi repetido em C ++, depois em Java, e a idéia principal de OOP degenerou em um paradigma estranho para organizar o código em classes e métodos.
Erlang e Elixir facilitam a criação de milhões de processos isolados, onde tudo funciona enviando mensagens entre eles. A arquitetura do sistema é determinada pelo nível de paralelismo que você deseja, com seu mapeamento subsequente para os processos diretamente.
O servidor web Elixir para 10.000 usuários não é "um servidor web com 10.000 usuários" (como é o caso do Apache ou Jigsaw e similares), mas é "10.000 servidores web por usuário" - concorda afastamento do modelo tradicional.
O fato de uma linguagem funcional simples ter sido usada para descrever o modelo de processo Erlang / Elixir é quase um acidente. Tudo começou com um sistema de programação lógica (Prolog), e coisas como o nó C, por exemplo, podem ser escritas em qualquer idioma. O que é realmente importante para o Elixir (e qualquer outra linguagem BEAM) é a capacidade da máquina virtual de operar com um número extremamente grande de processos paralelos.
Durante muito tempo, disse que "Erlang é a única linguagem real orientada a objetos". Acho que agora posso adicionar a ele e Elixir.
Para OOP, as coisas básicas são:
- isolamento entre objetos (nós o temos)
- ligação tardia (decidimos o que fazer somente quando o processo recebe uma mensagem)
- polimorfismo (todos os objetos podem responder a uma mensagem do mesmo tipo, por exemplo, "imprimir você mesmo" e qualquer objeto pode saber como fazer isso)
Muito menos importante:
- divisão em classes e métodos
- sintaxe
- modelo de software (funcional ou imperativo)
Depois de dividirmos o sistema em um grande número de pequenos processos de comunicação, tudo se torna (relativamente) fácil - cada processo deve ser bastante simples e capaz de fazer um pouco, o que simplifica bastante a programação.
O que Erlang (e Elixir) trouxe para a programação foi a idéia de comunicação (link - aproximadamente tradutor). Inicialmente proposto por Mike Williams, consiste em expandir a possibilidade de tratamento de erros, permitindo que isso seja feito fora dos limites dos processos. Com isso, obtivemos todas as ferramentas necessárias para construir árvores de supervisor, etc.
Supervisores, gen_server e todo esse jazz são apenas bibliotecas que escondem alguns detalhes do usuário. Simples por dentro, escrito usando as mesmas ferramentas - processos paralelos e os relacionamentos entre eles.
Erlang não foi desenvolvido como uma linguagem de programação funcional, mas como uma ferramenta para criar sistemas tolerantes a falhas de longa duração.
Um elemento central da tolerância a falhas é o conceito de tratamento remoto de erros. Se todo o sistema falhar, o mau funcionamento deve ser corrigido (compensado) em outra máquina, pois já é impossível fazê-lo localmente - o computador local não está funcionando.
Isso significa que, para programar sistemas tolerantes a falhas, precisamos que a distribuição de (processos) e as mensagens sejam ferramentas fáceis de usar, e é por isso que, em princípio, qualquer arquitetura tolerante a falhas acabará parecendo Erlang.
O objetivo principal da criação do Erlang era simplificar a programação de sistemas tolerantes a falhas, cujo efeito colateral era a facilidade de programar sistemas escaláveis.
A diferença entre Erlang e Elixir e "todo mundo" está nos mecanismos para garantir a simultaneidade e a tolerância a falhas, e não estamos falando de mônadas, sintaxe ou "pureza" dos FPs.
Agora, a pergunta é: você deseja processar 10.000 usuários em um encadeamento, usando retornos de chamada para simular simultaneidade, ou ainda deseja criar 10.000 processos paralelos, cada um dos quais é simples e não precisa de retornos de chamada?
Cada processo aguarda a mensagem em que está interessado, depois realiza cálculos e adormece em antecipação ao próximo.
Acho que o grande problema com a popularização do Erlang / Elixir é que você precisa explicar como muitos processos paralelos ajudam a resolver seu problema específico. Como nenhuma outra linguagem comum foi inicialmente destinada à programação paralela e não a facilitou de maneira significativa, a necessidade dela para as pessoas não é totalmente compreendida e compreendida.
"Mas eu posso fazer tudo em retornos de chamada em um único segmento", eles dirão. E eles fazem isso, e é dolorosamente difícil. E você pergunta: "o que acontece se o retorno de chamada entra em loop ou gera uma exceção?". E se eles não entenderem a pergunta, será necessário trabalhar duro e explicar o problema. Mas se a pergunta for clara, diga a eles que há um país distante em que não são necessários retornos de chamada para programar a simultaneidade.
Parece que tudo isso pode ser reduzido ao seguinte: não anuncie o Elixir como uma linguagem de programação funcional - não é. É uma linguagem de programação paralela (CPL, Concurrent Programming Language).
Não responda a argumentos como "minha linguagem funcional é mais funcional que a sua". E nem se preocupe em falar sobre mônadas, mude de assunto imediatamente.
"- O que é uma CPL?"
"- Você sabe, é disso que o WhatsApp é feito ..."
Do tradutor
Antes de tudo, gostaria de expressar meu arrependimento pela morte repentina de Joe Armstrong - ele morreu em 20 de abril de 2019. É difícil subestimar sua contribuição para o desenvolvimento da indústria, bem como seu talento como popularizador - livros, discursos, trabalho ativo nas comunidades Erlang e Elixir.
Links úteis: