Joe Armstrong à propos d'Elixir, Erlang, FP et OOP

Au cours des derniers jours, un certain nombre d'articles ont été publiés sur Habré, dont le leitmotiv général (en particulier dans les commentaires) était la confrontation entre des personnes franches et pointues - des partisans du FP contre l'OLP, bien qu'ils aient été invités à ne pas discuter. Erlang a parfois été discuté, à propos duquel j'ai rappelé un court post sur un sujet de Joe Armstrong, l'un des créateurs de cette langue, écrit par lui fin 2018 sur le forum Elixir en réponse à une question sur le paradigme linguistique. Je pense que son commentaire sera intéressant.


Joe Armstrong 12 septembre 2018


Toutes les bonnes choses à propos d'Elixir (et d'Erlang) sont liées à la concurrence - il suffit de créer des processus et des messages indépendants. Et c'est exactement l'essence de la programmation orientée objet, comme Alan Kay l'a souligné à plusieurs reprises.


OOP est entièrement dédié aux objets. Les objets répondent (ou devraient répondre) aux messages, et lorsque vous voulez faire quelque chose, vous envoyez un message à l'objet, et la façon dont il le traite est complètement hors de propos. Considérez les objets comme des "boîtes noires", et lorsque vous en voulez quelque chose - envoyez simplement des messages, et ils vous enverront des messages en réponse.


La façon dont tout est organisé à l'intérieur n'a pas d'importance si le code à l'intérieur de la boîte noire est fonctionnel ou impératif - seul ce qu'il doit faire exactement est important.


Malheureusement, bien que le premier langage orienté objet réussi basé sur ce modèle (Smalltalk) ait fonctionné sur les concepts d '"objet" et de "message", ces derniers dans Smalltalk n'étaient pas de vrais messages, mais seulement des appels de fonction synchrones masqués. La même erreur a été répétée en C ++, puis en Java, et l'idée principale de la POO a dégénéré en un paradigme étrange pour organiser le code en classes et méthodes.


Erlang et Elixir facilitent la création de millions de processus isolés où tout fonctionne en envoyant des messages entre eux. L'architecture du système est déterminée par le niveau de parallélisme que vous souhaitez, avec sa mise en correspondance ultérieure avec les processus directement.


Le serveur Web Elixir pour 10 000 utilisateurs n'est pas «un serveur Web avec 10 000 utilisateurs» (comme c'est le cas avec Apache ou Jigsaw et similaires), mais c'est «10 000 serveurs Web par utilisateur» - d'accord, radical départ du modèle traditionnel.


Le fait qu'un langage fonctionnel simple ait été utilisé pour décrire le modèle de processus Erlang / Elixir est presque un accident. Tout a commencé avec un système de programmation logique (Prolog), et des choses comme C-node, par exemple, peuvent être écrites dans n'importe quel langage. La chose vraiment importante pour Elixir (et tout autre langage BEAM) est la capacité de leur machine virtuelle à fonctionner avec un très grand nombre de processus parallèles.


Pendant longtemps, j'ai dit que "Erlang est le seul véritable langage orienté objet". Je suppose que maintenant je peux y ajouter Elixir.


Pour OOP, les choses de base sont:


  • l'isolement entre les objets (nous l'avons)
  • liaison tardive (nous décidons quoi faire uniquement lorsque le processus reçoit un message)
  • polymorphisme (tous les objets peuvent répondre à un message du même type, par exemple, "imprimer soi-même" et tout objet peut savoir comment le faire)

Beaucoup moins important:


  • division en classes et méthodes
  • syntaxe
  • modèle de logiciel (fonctionnel ou impératif)

Après avoir divisé le système en un grand nombre de petits processus communiquant entre eux, tout le reste devient (relativement) facile - chaque processus devrait être assez simple et pouvoir faire beaucoup, ce qui simplifie considérablement la programmation.


Ce qu'Erlang (et Elixir) ont apporté à la programmation, c'est l'idée de la communication (lien - environ Traducteur). Initialement proposé par Mike Williams, il consiste à élargir les possibilités de gestion des erreurs, permettant de le faire en dehors des frontières des processus. Ayant cela, nous avons obtenu tous les outils nécessaires pour construire des arbres de superviseur, etc.


Les superviseurs, gen_server et tout ce jazz ne sont que des bibliothèques qui cachent certains détails à l'utilisateur. Intérieur simple, écrit en utilisant les mêmes outils - processus parallèles et relations entre eux.


Erlang n'a pas été développé comme un langage de programmation fonctionnel, mais comme un outil pour créer des systèmes tolérants aux pannes de longue durée.


Un élément central de la tolérance aux pannes est le concept de gestion à distance des erreurs. Si l'ensemble du système tombe en panne, le dysfonctionnement doit être corrigé (compensé) sur une autre machine, car il est déjà impossible de le faire localement - l'ordinateur local ne fonctionne pas.


Cela signifie que pour programmer des systèmes tolérants aux pannes, nous avons besoin que la distribution des (processus) et de la messagerie soient des outils faciles à utiliser, et c'est pourquoi, en principe, toute architecture tolérante aux pannes finira par ressembler à Erlang.


L'intérêt de la création d'Erlang était de simplifier la programmation des systèmes tolérants aux pannes, dont l'un des effets secondaires était la facilité de programmation des systèmes évolutifs.


La différence entre Erlang et Elixir et "tout le monde" réside dans les mécanismes garantissant la concurrence et la tolérance aux pannes, et il ne s'agit pas de monades, de syntaxe ou de "pureté" du FP.


Maintenant, la question est - voulez-vous traiter 10 000 utilisateurs dans un thread, en utilisant des rappels pour émuler la concurrence, ou voulez-vous toujours créer 10 000 processus parallèles, chacun étant simple et ne nécessitant aucun rappel?


Chaque processus attend le message qui l'intéresse, puis effectue des calculs et s'endort en prévision du suivant.


Je pense que le gros problème de la popularisation d'Erlang / Elixir est que vous devez expliquer comment de nombreux processus parallèles aident à résoudre votre problème spécifique. Puisqu'aucun autre langage commun n'était initialement destiné à la programmation parallèle et ne l'a facilité de manière significative, le besoin de celui-ci pour les gens n'est pas entièrement compris et compris.


«Mais je peux tout faire sur les rappels dans un seul fil», diront-ils. Et ils le font, et c'est douloureusement difficile. Et vous demandez: «Que se passe-t-il si le rappel entre dans la boucle ou lève une exception?», Et s’ils ne comprennent pas la question, vous devez travailler dur et expliquer le problème. Mais si la question est claire, dites-leur qu'il y a un pays éloigné dans lequel les rappels ne sont pas nécessaires pour programmer la concurrence.


Il semble que tout ce qui précède peut être réduit comme suit: veuillez ne pas annoncer Elixir comme langage de programmation fonctionnel - ce n'est pas le cas. Il s'agit d'un langage de programmation parallèle (CPL, Concurrent Programming Language).


Ne répondez pas à des arguments comme «mon langage fonctionnel est plus fonctionnel que le vôtre». Et ne vous embêtez même pas à parler de monades, changez immédiatement de sujet.


"- Qu'est-ce qu'un CPL?"
"- Vous savez, c'est sur cela que WhatsApp est fait ..."


Du traducteur


Tout d'abord, je voudrais exprimer mes regrets pour la mort soudaine de Joe Armstrong - il est décédé le 20 avril 2019. Il est difficile de sous-estimer sa contribution au développement de l'industrie, ainsi que son talent de vulgarisateur - livres, discours et travail actif dans les communautés d'Erlang et d'Elixir.


Liens utiles:


Source: https://habr.com/ru/post/fr450508/


All Articles