gevent – Sam & Max http://sametmax.com Du code, du cul Thu, 05 Sep 2019 08:22:03 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 32490438 Le piège d’écrire du code couplé à une implémentation http://sametmax.com/le-piege-decrire-du-code-couple-a-une-implementation/ http://sametmax.com/le-piege-decrire-du-code-couple-a-une-implementation/#comments Wed, 03 Feb 2016 09:17:15 +0000 http://sametmax.com/?p=18044 On a reproché à la communauté de Twisted que c’était un silo fermé. Une lib écrite pour Twisted ne marchait que pour Twisted.

Puis on a reproché à la communauté de gevent la même chose.

Et maintenant la communauté d’asyncio recommence à faire la même erreur.

Regardez, pleins de libs compatibles asyncio, c’est génial non ?

Je ne vais pas dire non. Ça boost l’utilisabilité, l’adoption, etc.

Mais c’est aussi un énorme travail qui passe à côté de toute l’expérience (bugs, cas extrêmes, best practices, perfs…) des communautés précédentes. Et qui a une date de péremption, qui sera foutu à la poubelle à la prochaine vague.

Pourquoi ?

Parce que toutes ces libs se concentrent sur l’implémentation.

Vous ne pouvez pas réutiliser le code d’une lib SMTP Twisted, car elle est liée au reactor. Pourtant cette lib contient des milliers d’infos utiles, la gestion de ce serveur bizarre, la correction de cette erreur de calcul de date, qui n’ont rien à voir avec Twisted.

C’est la même chose avec ces libs pour asyncio.

Que faire alors ?

Et bien d’abord écrire une lib neutre. Qui contient des choses comme :

  • Le parsing des packets.
  • Le workflow.
  • Les constantes.
  • Les convertisseurs de données.
  • Les vérificateurs de données.
  • Les bases de connaissances sur le monde extérieur.

Il faut écrire cette lib de manière à ce qu’elle puisse être réutilisée dans tout contexte. À base de callbacks simples, de hooks, de points d’entrées.

Puis, vous rajoutez dans un sous-module, le support pour votre plateforme favorite. Un adaptateur qui utilise ces hooks pour Twisted, ou asyncio, ou gevent.

Cela a de multiples bénéfices:

  • Quand vous changez de plateforme ou que le nouveau joujou à la mode sort, une grande partie du travail peut être réutilisé.
  • Toute la partie neutre de la lib peut être réutilisée par toute la communauté Python, pas juste celle qui utilise la même plateforme.
  • Cela encourage les contributions à votre lib, puisque n’importe qui peut rajouter un module pour une plateforme et l’enrichir, et corriger des bugs sur la partie neutre.
  • Votre lib est beaucoup plus facile à tester.
  • Votre lib va cumuler du savoir sur la problématique qu’elle résout pendant bien plus de temps, puisqu’elle traverse les modes des implémentations. Au long terme, ce sera la lib la plus stable et complète.

Toutes les plateformes ont une manière ou un autre pour attaquer ce problème. Twisted par exemple a une classe protocole qui est indépendante du reactor. Oui, mais elle est dépendante de la manière de penser en Twisted. Personne ne documente ces protocoles de manière neutre. Personne n’utilise ces protocoles de manière neutre.

gevent utilise carrément le monkey patching pour essayer de se rendre transparent. Évidemment ça veut dire que c’est très dépendant de l’implémentation. Si CPython change, ça casse. Si on utilise une implémentation différente de Python, ça ne marche pas. Si on fait des expérimentations comme actuellement sur le JIT, les résultats sont imprévisibles.

async/await a l’énorme bénéfice de proposer une interface commune à tout travail asynchrone. Fut-ce de l’IO, du thread, du multi-processing, du sous-processing, du multi-interpretteur ou des callbacks ordinaires… Cela va donc énormément gommer ces problèmes de compatibilité, même si la séparation des responsabilités que je recommande n’est pas suivie. Mais pour le moment tout le monde n’implémente pas __await__. Et si __await__ lance le code sur l’autre plateforme, ça fait un truc en plus à gérer. Ce n’est pas tout à faire neutre.

Attention, je comprends très bien que cette séparation que je recommande ne soit pas suivie.

C’est très difficile de faire une API agnostique par rapport à la plateforme. Ça demande beaucoup plus de taf, de connaissance, etc. Je suis le premier à ne pas le faire pas fainéantise ou ignorance.

Mais il faut bien comprendre qu’à chaque fois, on réinvente la roue, une roue jetable par ailleurs.

Bien entendu, je dis ça pour l’async, mais c’est vrai pour tout.

Par exemple, des centaines de code ont leur propre moyen de définir un schéma et valider les données en entrée. Les ORM sont particulièrement coupable de cela, les libs de form aussi, mais on a tous codé ce genre de truc. C’est idiot, c’est un code qui n’a pas à être lié à une plateforme.

Des centaines de libs ont leur code de persistance lié à une plateforme. Même celles qui utilisent un ORM, au final, se lient à certaines bases de données (raison pour laquelle je suis GraphQL de très près).

La généricité a ses limites, et c’est toujours un compromis entre le coût immédiat, et le bénéfice futur. Si on fait tout générique, on se retrouve avec un truc qui évolue à 2 à l’heure et qui a 15 surcouches pour faire un print. On se retrouve avec Zope. Dont personne, et c’est ironique, ne réutilise les composants parce que c’est devenu trop compliqué de les comprendre.

Car évidemment, qui dit découplage, dit doc bien faite, qui explique clairement comment bénéficier de ce découplage. Mais dit aussi que le code utilisant les adapteurs doit être aussi simple que si on avait un fort couplage, ce qui est dur à faire.

Et on tombe ici sur un autre problème : la compétence pour faire ce genre de code. Si il faut 10 ans d’expérience pour faire une lib propre, alors on va réduire considérablement le nombre de personnes qui vont oser coder des libs.

Aussi cet article n’est en aucun cas un savon que je souhaite passer aux auteurs. Merci de coder ces libs. Merci de donner de votre temps.

Non, cet article est juste là pour dire : dans la mesure du possible, il est très bénéfique sur le long terme de se découpler de la plateforme.

]]>
http://sametmax.com/le-piege-decrire-du-code-couple-a-une-implementation/feed/ 10 18044