Python permet facilement de passer d'un programme structuré en fonction à un programme utilisant des classes et des objets.
C'est à mon avis une des forces de Python. Pas besoin de tout réécrire le gros du travail est conservé.
Aussi , Python favorise la refactorisation de son code au fur et à mesure de la progression du développement.
(le notebook est disponible sur : https://github.com/germanlinux/notebooks
(https://github.com/germanlinux/notebooks/blob/main/init/refactorisation.ipynb)La refactorisation en objet et classe consiste à :
- Ajouter le paramètre 'self' dans les déclarations des fonctions
- Préfixer les variables locales par 'self'
- Créer un cadre pour la classe
- Améliorer le nommage des méthodes
Pour sécuriser ces opérations de refactorisation, j'utilise le dispositif du DOCTEST pour m'assurer de la non régression du programme.
Le DOCTEST permet d'inclure des tests dans la documentation des méthodes ou des fonctions.
Il utilise pour cela le motif '>>>' pour insérer des instructions Python dans la documentation. Le resultat de ces appels est comparé avec la ligne suivante sans préfixe.
Exemple:
Ces insertions n'auront aucun impact sur le fonctionnement des méthodes ou des fonctions.
Pour activer les tests il suffit d'ajouter l'appel au module de DOCTEST.
Dans cet exemple, la fonction à tester est indiquée. Il est possible de lancer tous les test présents dans un programme en remplaçant la methode run_docstring_examples(...) par testmod(..)
Lancement des testsCi dessous un exemple complet (projet pycobol)
class ZoneGroupe: ''' Cette classe prend en charge la creation d'une zone groupe. Par nature cette zone est de type ALN. Sa longueur est la somme des longueurs des composants qui la composent >>> obj = ZoneGroupe('zoneessai', 1, 0) >>> obj.nom 'zoneessai' >>> print(obj) >>> objfils = ZoneGroupe('zonefils', 2) >>> obj.ajout_fils_groupe(objfils) >>> len(obj.fils) 1 >>> objfils.pere # doctest: +ELLIPSIS ZoneGroupe(nom='zoneessai'... >>> objfils2 = ZoneGroupe('zonefils2', 1) >>> obj.ajout_fils_groupe(objfils2) # doctest: +ELLIPSIS Traceback (most recent call last): ... >>> objfilsimp = ZoneFilsSimple('essaifils', 5, picture = '999') >>> obj.ajout_fils_simple(objfilsimp) >>> obj.longueur_utile 3 '''
La directive #doctest: +ELLIPSIS permet de signaler au module DOCTEST d'arrêter la comparaison du résultat après les trois points (...) . C'est très utile pour tester une exception: la sortie complète de l'exception (trace de la pile d'exécution) sera ignorée. Il est aussi utilisé ici pour des contenus un peu longs comme les objets.
class ZoneGroupe(builtins.object) | ZoneGroupe(nom: str, rang: int, pere: int = 0, fils: list[int] = <factory>, son_type: str = 'GRP', usage: str = 'DISPLAY', longueur_utile: int = 0, valeur_interne: str = '', valeur_externe: str = '', section: str = 'NON RENSEIGNE') -> None | | Cette classe prend en charge la creation d'une zone groupe | par nature cette zone est de type ALN. | Sa longueur est la somme des longueurs des composants qui la composent | >>> obj = ZoneGroupe('zoneessai', 1, 0) | >>> obj.nom | 'zoneessai' | >>> print(obj) | >>> objfils = ZoneGroupe('zonefils', 2) | >>> obj.ajout_fils_groupe(objfils) | >>> len(obj.fils) | 1 | >>> objfils.pere # doctest: +ELLIPSIS | ZoneGroupe(nom='zoneessai'... | >>> objfils2 = ZoneGroupe('zonefils2', 1) | >>> obj.ajout_fils_groupe(objfils2) # doctest: +ELLIPSIS | Traceback (most recent call last): | ... | >>> objfilsimp = ZoneFilsSimple('essaifils', 5, picture = '999') | >>> obj.ajout_fils_simple(objfilsimp) | >>> obj.longueur_utile | 3
Résultat de l'instruction help
Ci-dessous un résultat partiel d'exécution des tests
Trying: objfils = ZoneGroupe('zonefils', 2) Expecting nothing ok Trying: obj.ajout_fils_groupe(objfils) Expecting nothing ok Trying: len(obj.fils) Expecting: 1 ok Trying: objfils.pere # doctest: +ELLIPSIS Expecting: ZoneGroupe(nom='zoneessai'... ok Trying: objfils2 = ZoneGroupe('zonefils2', 1) Expecting nothing ok
Résultats des tests.
En conclusion.
Python nous donne la possibilité de se tromper et d'améliorer notre ouvrage par petites touches.
Ces tests intégrés sont à compléter par des tests unitaires avec une couverture du code mesuré avec la commande coverage.
Aucun commentaire:
Enregistrer un commentaire