Stratégie pour suivre les changements de langage (Python)

16

Écriture de code qui durera encore des années

Les langages de programmation changent. Les bibliothèques changent. Certains codes datant de 5, 10 ou même 20 ans peuvent toujours s'exécuter et produire les résultats attendus, tandis que certains codes datant de 2 ans peuvent échouer avec une erreur de syntaxe. Cela est en partie inévitable, car les langues évoluent (du moins, la plupart le font). Les développeurs ont la responsabilité de maintenir leur code. Mais parfois, la stabilité est une exigence importante dans le code de production, et le code devrait simplement fonctionner pendant 10 ans sans que quelqu'un ait besoin de le parcourir chaque année pour l'adapter aux changements de langue. Ou je pourrais avoir de petits scripts, par exemple pour l'analyse de données scientifiques, que je dois revoir après ne pas les avoir touchés pendant des années. Par exemple, dans les bureaux météorologiques, il y a beaucoup de code Fortran opérationnel même pour les pièces non essentielles à la vitesse, et la stabilité du code est l'une des raisons. JE' J'ai entendu dire que la peur de l'instabilité est l'un des objets qu'ils ont contre le passage à Python (en dehors de l'inertie du langage bien sûr; cela n'est possible que pour le nouveau code ne dépendant pas de l'ancien code). Bien sûr, une stratégie pour un code stable consiste à geler l'ensemble du système d'exploitation. Mais ce n'est pas toujours faisable.

J'utilise Python comme sur l'exemple, mais le problème n'est pas limité à Python en particulier.

Documents sur les problèmes de compatibilité avec Python

Dans le cas de Python, il existe plusieurs documents décrivant la politique pour les modifications incompatibles en amont.

PEP-5

Selon PEP 5 :

Il doit y avoir au moins une période de transition d'un an entre la sortie de la version transitionnelle de Python et la sortie de la version incompatible en amont. Les utilisateurs auront au moins un an pour tester leurs programmes et les migrer de l'utilisation de la construction obsolète à l'alternative.

Personnellement, je considère qu'un an est plutôt court. Cela signifie que je pourrais écrire du code, et dans un an et demi, il ne fonctionnera plus.

PEP 291

Le PEP 291 contient une liste incomplète de directives sur les choses à éviter afin de maintenir la compatibilité descendante. Cependant, il ne concerne que Python 2.x. Comme Python 2.7 est la version finale de la série 2.x et Python 2.7 est uniquement corrigé, ce PEP n'a plus qu'un intérêt historique.

PEP 387

Il existe également PEP 387 sur les modifications incompatibles en amont. Le PEP 387 est un projet et non une politique officielle. En juin 2009, cela a été discuté sur la liste de diffusion Python-ideas . Une partie de la discussion a porté sur la façon dont les développeurs peuvent écrire du code robuste contre les changements de langage. Un article a donné quelques conseils sur ce qu'il ne faut pas faire :

Parallèlement à cela, vous pouvez déduire plusieurs règles qui sont probablement vraies la plupart du temps: n'appelez pas les choses en commençant par "_", ne modifiez rien par des singes, n'utilisez pas le remplacement de classe dynamique sur des objets de classes autres que la vôtre , ne dépendent pas de la profondeur des hiérarchies d'héritage (par exemple, non ".__bases__[0].__bases__[0]"), assurez-vous que vos tests s'exécutent sans produire de DeprecationWarnings, tenez compte des conflits potentiels d'espace de noms lors de l'ajout d'attributs à des classes héritant d'autres bibliothèques. Je ne pense pas que toutes ces choses soient écrites au même endroit.

En outre, il y avait quelques points concernant les "champs de mines" (nouvelles fonctionnalités susceptibles de changer) et les "zones gelées" (API très vendues pratiquement garanties de ne pas changer). Citant Antoine Pitrou :

Je pense que la "zone gelée" devrait être définie positivement (API publiques explicites et comportement explicitement garanti) plutôt que négativement (un "champ de mines" explicite). Sinon, nous oublierons de mettre des choses importantes dans le champ de mines et de nous mordre plus tard lorsque nous aurons besoin de changer ces choses d'une manière incompatible à l'envers.

Il ne semble pas y avoir de conclusion à partir de ce fil, mais il se rapproche assez du cœur de ce que je recherche. Le fil a presque quatre ans, alors peut-être que la situation a changé ou s'est améliorée. Quel type de code est susceptible de survivre et quel type de code est plus fragile?

Consignes de portage

En plus des documents décrits ci-dessus, chaque version de Python est livrée avec une directive de portage : portage vers Python 3.2 , portage vers Python 3.3 , etc.

Compatibilité utile

Le PEP 3151 m'a présenté le concept de compatibilité utile . Selon mes propres mots, cela se résume à l'idée que ce n'est que si le code est soigneusement écrit que les développeurs de langage doivent veiller à maintenir la compatibilité. Il ne définit pas vraiment la compatibilité utile , mais je pense que c'est similaire aux idées que j'ai citées de la discussion PEP 387 ci-dessus.

Du point de vue des programmeurs

En tant que programmeur, je sais que Python va changer à l'avenir et que les gens - surtout moi-même - essaieront d'exécuter mon code dans plusieurs années à partir de maintenant dans une version Python qui est une, deux ou peut-être trois versions mineures. Tout ne sera pas compatible, et en fait, il est facile de trouver du code qui échouera (j'ai déjà rencontré du code indiquant if sys.version[:3] != '2.3': print 'Wrong version, exiting'). Ce que je recherche, c'est un ensemble de directives sur ce qu'il faut faire et ce qu'il ne faut pas faire pour augmenter les chances que mon code continue de fonctionner sans modification à l'avenir.

Existe-t-il de telles directives? Comment écrire du code Python qui fonctionnera toujours à l'avenir?

Ma question concerne à la fois au cœur de Python, à sa bibliothèque standard, mais aussi couramment utilisé add-on des bibliothèques, en particulier numpy, scipy, matplotlib.


EDIT : Jusqu'à présent, deux des réponses se rapportent à python2 vs python3. Ce n'est pas ce que je veux dire. Je connais les outils pour migrer de Python2 vers Python3. Ma question concerne les changements de langue à venir . Nous pouvons faire mieux qu'une boule de cristal pour trouver des directives de codage plus stables. Par exemple:

  • import moduleest plus à l'épreuve du temps que from module import *, car ce dernier peut casser le code s'il se moduledéveloppe une ou plusieurs nouvelles fonctions / classes.

  • L'utilisation de méthodes non documentées peut être moins pérenne que l'utilisation de méthodes documentées, car quelque chose qui n'est pas documenté peut être le signe que quelque chose n'est pas encore stable.

C'est ce genre de conseils pratiques de codage que je recherche. Puisqu'il s'agit du présent → du futur, nous pouvons nous limiter à Python3, car Python2 ne va plus changer.

gerrit
la source

Réponses:

13

Il s'agit d'un problème non résolu dans notre domaine. Il n'y a aucun moyen d'être sûr que votre code fonctionnera indéfiniment. Même si votre code était vraiment parfait dans le sens de la compatibilité ascendante (et si c'est le cas, venez travailler pour mon entreprise!;)), S'il fonctionne, utilise ou est utilisé par tout autre logiciel qui obtient un bogue ou des modifications en aucune façon, votre code peut ne pas fonctionner.

Je ne peux donc pas vous donner une liste de choses à faire qui, si vous les suivez, garantiront le succès. Mais ce que vous pouvez faire, c'est minimiser le risque de futures ruptures et minimiser leurs impacts. Un Pythoniste plus compétent serait en mesure de vous donner des conseils plus spécifiques à Python, donc je devrai être plus général:

  • écrire des tests unitaires. Même pour les choses que vous savez n'en avez pas besoin.

  • en utilisant des bibliothèques et des technologies populaires / bien conçues / stables, en évitant celles impopulaires (et donc susceptibles de ne plus être prises en charge)

  • évitez d'écrire du code qui exploite les détails de l'implémentation. Code aux interfaces, pas aux implémentations. Code contre plusieurs implémentations de la même interface. Par exemple, exécutez votre code dans CPython, Jython et IronPython et voyez ce qui se passe. Cela vous donnera d'excellents commentaires sur votre code. Cela pourrait ne pas être utile pour Python3 - la dernière fois que j'en ai entendu parler, certaines implémentations étaient toujours en Python2.

  • écrire un code simple et clair expliquant ses hypothèses

  • écrire du code modulaire et composable. Si un code doit faire quelque chose de dangereux (dans le sens évolutif), séparez-le afin que même s'il doit changer, le reste du code ne le fasse pas.

  • avoir une spécification d'une certaine forme. Ceci est similaire aux points sur les tests unitaires, si vous utilisez des tests en tant que spécification, et des interfaces, qui peuvent également être utilisées comme spécifications. (Je veux dire l'interface dans le sens général, pas le sens du mot clé Java).

Faire l'une de ces choses peut / augmentera la quantité de travail que vous avez à faire. Je pense que cela a du sens - beaucoup de ces points peuvent également être expliqués sur la façon d'écrire du bon code, ce qui est assez difficile (à mon avis). Parfois, vous devrez peut-être violer certaines de ces suggestions. C'est parfaitement acceptable, mais soyez conscient des coûts.

C'est formidable que l'équipe Python y pense, et c'est sûr qu'ils sont beaucoup plus talentueux et qualifiés que je ne le serai jamais. Pourtant, j'estime qu'il y a 100% que le code de quelqu'un quelque part cessera de fonctionner comme il le souhaite lorsque Python est mis à niveau.


la source
4

C'est ce qu'on appelle la gestion de la configuration. Si le système n'est jamais changé, il ne devrait pas se casser. Alors ne changez pas le système. Vous vous inquiétez des nouvelles versions de Python? Ne pas mettre à niveau. Vous vous inquiétez des nouveaux pilotes de périphérique? Ne pas mettre à niveau. Vous vous inquiétez des correctifs Windows? ...

Ross Patterson
la source
0

Pour Python 2 -> Python 3, une bibliothèque Python 2to3 est déjà installée (elle est livrée avec le package Python d'origine).

Sur la base de cela, peu de temps après la sortie de nouvelles versions, des bibliothèques similaires devraient être fournies avec chaque nouvelle version. Cependant, comme Martijn l'a déclaré, des bibliothèques comme celles-ci ne seront publiées que pour les versions majeures (comme la version 3.0) mais pas pour les versions mineures (telles que 3.2). Cependant, entre 3.0 et 3.2 (ou toute autre version mineure), il ne devrait pas y avoir de problème de compatibilité, donc la conversion vers la version 3.0 devrait être correcte.

Aussi, je vous suggère de regarder cette question .

Rushy Panchal
la source
1
Non, 2to3 vous aide uniquement à mettre à niveau le code à travers l'écart de version majeur; il n'y a pas de bibliothèques (nécessaires) pour mettre à niveau le code dans les versions mineures.
Martijn Pieters
@MartijnPieters Les versions mineures ne devraient pas avoir de problèmes de compatibilité, car il ne devrait pas y avoir de changements trop importants. En cas de problèmes de compatibilité et de modifications importantes, une toute nouvelle version devrait être publiée.
0

Je n'ai pas grand-chose à ajouter, le "programme pour 2, et utiliser 2to3" semble être un complément courant sur Internet ces derniers temps. Cependant, il y a quelque chose que vous devriez regarder:

Cela s'appelle six (page pypi) . C'est une bibliothèque python consacrée à aider à écrire du code qui s'exécute à la fois sur python 2 et python 3. Je l'ai vu utilisé dans un certain nombre de projets tout en parcourant le net, mais les noms m'échappent pour le moment.

Aren
la source
Pas vraiment ce que je recherche. J'ai édité la question, j'espère que c'est plus clair ce que je cherche maintenant.
gerrit