OVH Cloud OVH Cloud

nettoyage de code

9 réponses
Avatar
paul POULAIN
Bonjour,

je travaille sur un projet assez gros en Perl (www.koha-fr.org pour ceusses
que ca intéresse)
Dans la prochaine version majeure, nous voudrions nettoyer le code, parce
qu'il est clair que certaines fonctions dans les packages .pm ne sont pas
utilisées.
Existe t'il un outil qui fasse une espèce de "cartographie" de
l'application, avec, pour chaque script[*], qui l'appelle, pour chaque sub
qui l'appelle...

[*] ca ca me paraît impossible, vu qu'on utilise massivement les templates
html::template, il faudrait savoir quel script utilise quel template ;-)
--
Paul

9 réponses

Avatar
Emmanuel Florac
Le Thu, 22 Sep 2005 16:08:01 +0200, paul POULAIN a écrit :

Existe t'il un outil qui fasse une espèce de "cartographie" de
l'application, avec, pour chaque script[*], qui l'appelle, pour chaque sub
qui l'appelle...


Il y a Devel::DProf qui sert à ça.

--
Toutes les organisations ont leur règles, et les Femmes Algériennes
doivent avoir aussi leurs règles.
Aït Ahmed.

Avatar
paul POULAIN
Emmanuel Florac wrote:

Le Thu, 22 Sep 2005 16:08:01 +0200, paul POULAIN a écrit :

Existe t'il un outil qui fasse une espèce de "cartographie" de
l'application, avec, pour chaque script[*], qui l'appelle, pour chaque
sub qui l'appelle...


Il y a Devel::DProf qui sert à ça.

Si je ne m'abuse, ce n'est pas tout à fait ce que je cherche, parce que ca

porte sur 1 script unique, et c'est surtout utile pour évaluer les appels
(trop) nombreux à une fonction. Alors que moi je voudrais exactement le
contrire et qqc qui porte sur toute une application.

Dans l'idéal, ca me sortirait un truc du genre :
=== Xxxx.pm == sub toto
=> used by script1.pl
=> used by script15.pl

sub tata
***** unused

sub titi
=> used by script247.pl

=== script27.pl == => called by script script39.pl

=== script31.pl == => called by nobody ?
...

--
Paul


Avatar
Emmanuel Florac
Le Fri, 23 Sep 2005 09:16:50 +0200, paul POULAIN a écrit :

Alors que moi je voudrais
exactement le contrire et qqc qui porte sur toute une application.


Alors Devel::TraceCalls ? Par contre il est plutôt pour le code OO. IL y
a aussi Devel::TraceMethods. Le mieux c'est que tu cherches sur CPAN et
que tu essaies les différents modules.

--
Il y a toujours un bug de plus.
Loi de Lubarsky.

Avatar
Paul Gaborit
À (at) Fri, 23 Sep 2005 09:16:50 +0200,
paul POULAIN écrivait (wrote):
Emmanuel Florac wrote:

Le Thu, 22 Sep 2005 16:08:01 +0200, paul POULAIN a écrit :

Existe t'il un outil qui fasse une espèce de "cartographie" de
l'application, avec, pour chaque script[*], qui l'appelle, pour chaque
sub qui l'appelle...


Il y a Devel::DProf qui sert à ça.

Si je ne m'abuse, ce n'est pas tout à fait ce que je cherche, parce que ca

porte sur 1 script unique, et c'est surtout utile pour évaluer les appels
(trop) nombreux à une fonction. Alors que moi je voudrais exactement le
contrire et qqc qui porte sur toute une application.


Devel::DProf stocke l'information pour tout (script et modules
utilisés). Seuls les appels aux fonctions internes de Perl ne sont pas
tracés.

Le script 'dprofpp' permet a posteriori (après exécution et donc
hors-ligne) d'analyser comme on veut le fichier de trace
(tmon.out). Ça ne sert pas qu'à voir les routines les plus
utilisées. On peut consulter l'arbre exact de tous les appels.

Par contre, c'est de l'analyse dynamique. C'est donc la trace d'une
exécution donnée. Si cette exécution ne passe pas par une fonction,
rien ne dit qu'une autre exécution avec d'autres paramètres n'y
passera pas.

Malheureusement, l'analyse statique de code ne peut pas être fiable
avec un langage dynamique comme Perl... sauf à placer beaucoup de
restrictions sur la nature du code utilisé (pas d'objet, pas
d'AUTOLOAD, pas d'introspection, pas de sérialisation, etc.).

Dans le cas d'une grosse application, un nettoyage comme celui que
vous envisagez passe par une programmation la plus modulaire possible
(pour diviser le problème en petits problèmes plus simples et quasi
indépendants) et par l'utilisation de jeux de tests complets
(unitaires, fonctionnels, de non regression, etc.) avec une couverture
maximale. Si ces jeux de tests existent et sont à jour, leur
utilisation avec Devel::DProf doit donner de bons résultats.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>



Avatar
Patrick Mevzek
Malheureusement, l'analyse statique de code ne peut pas être fiable
avec un langage dynamique comme Perl... sauf à placer beaucoup de
restrictions sur la nature du code utilisé (pas d'objet, pas
d'AUTOLOAD, pas d'introspection, pas de sérialisation, etc.).


Personnellement j'ai fait une telle analyse statique en parsant le
résultat de perl -MO=Xref
mais effectivement ca ne couvre pas tout, comme vous le décrivez.

C'est déjà mieux que rien je trouve, car cela ne nécessite pas
d'exécuter le code, ce qui peut ne pas être trivial (ex: modperl)

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>

Avatar
Paul Gaborit
À (at) Fri, 23 Sep 2005 14:24:54 +0200,
Patrick Mevzek écrivait (wrote):
Malheureusement, l'analyse statique de code ne peut pas être fiable
avec un langage dynamique comme Perl... sauf à placer beaucoup de
restrictions sur la nature du code utilisé (pas d'objet, pas
d'AUTOLOAD, pas d'introspection, pas de sérialisation, etc.).


Personnellement j'ai fait une telle analyse statique en parsant le
résultat de perl -MO=Xref
mais effectivement ca ne couvre pas tout, comme vous le décrivez.


Ce que je décrivais implique des faux négatifs (des appels qui ne sont
pas détectés).

Mais il y a aussi des faux positifs. Ex :

$x = $y * $y;
if ($x < 0) {
f();
}

L'analyse statique vous dit que f() est utilisée alors que si $y est
bien un nombre, f() n'est jamais appelée... Évidemment si $y est un
objet avec un overload de '*', ce n'est plus la même chose ;-)

C'est déjà mieux que rien je trouve, car cela ne nécessite pas
d'exécuter le code, ce qui peut ne pas être trivial (ex: modperl)


Il est toujours possible de faire des jeux de tests sur une plateforme
complète (apache + mod_perl)... C'est pas évident mais, pour de gros
développements, ça vaut le coup.

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>


Avatar
paul POULAIN
Paul Gaborit wrote:

Par contre, c'est de l'analyse dynamique. C'est donc la trace d'une
exécution donnée. Si cette exécution ne passe pas par une fonction,
rien ne dit qu'une autre exécution avec d'autres paramètres n'y
passera pas.


ben oui...

Malheureusement, l'analyse statique de code ne peut pas être fiable
avec un langage dynamique comme Perl... sauf à placer beaucoup de
restrictions sur la nature du code utilisé (pas d'objet, pas
d'AUTOLOAD, pas d'introspection, pas de sérialisation, etc.).


C'est bien ce qu'il me semblait. Mais comme on fait des trucs "magiques" en
Perl, j'espérais...

Dans le cas d'une grosse application, un nettoyage comme celui que
vous envisagez passe par une programmation la plus modulaire possible
(pour diviser le problème en petits problèmes plus simples et quasi
indépendants)


C'est clairement ce que l'on souhaite faire, of course. Mais un projet sous
licence GPL avec une cinquantaine de développeur depuis son début (5 ans),
évidemment, tout le monde n'a pas codé avec ses mains (je veux dire que ca
a été parfois codé avec les pieds ;-) )

et par l'utilisation de jeux de tests complets
(unitaires, fonctionnels, de non regression, etc.) avec une couverture
maximale. Si ces jeux de tests existent et sont à jour, leur
utilisation avec Devel::DProf doit donner de bons résultats.


mmm... joker sur ce point là, quelqu'un a commencé un jour, mais personne ne
l'a suivi (et je n'étais pas le quelqu'un...)
--
Paul

Avatar
Paul Gaborit
À (at) Fri, 23 Sep 2005 16:24:41 +0200,
paul POULAIN écrivait (wrote):
Paul Gaborit wrote:

Par contre, c'est de l'analyse dynamique. C'est donc la trace d'une
exécution donnée. Si cette exécution ne passe pas par une fonction,
rien ne dit qu'une autre exécution avec d'autres paramètres n'y
passera pas.


ben oui...


Mais c'est tout de même un bon point de départ : après analyse de
quelques exécutions typiques on connait déjà une partie de ce qu'il ne
faut pas supprimer ;-)

Il y a aussi le 'grep' (l'analyseur statique du pauvre) qui permet de
chercher le nom d'une fonction dans tous le code. Ensuite le "pauvre"
programmeur analyse lui-même chaque bout de code pour déduire si oui
ou non la fonction est réellement appelée.

Ou encore la bonne vieille méthode du "deprecated" : on ne supprime
pas mais on trace avec un GROS message d'erreur (avec appel à
Carp::cluck pour savoir d'où ça vient) tous les appels aux fonctions
qu'on souhaite supprimer. Les beta-testeurs ayant, entre autres, pour
mission de remonter tous ces messages.


--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>


Avatar
Patrick Mevzek
Ce que je décrivais implique des faux négatifs (des appels qui ne sont
pas détectés).


Oui, et surtout les méthodes des objets, c'est ce qui m'embête le plus.

Mais il y a aussi des faux positifs. Ex :

$x = $y * $y;
if ($x < 0) {
f();
}

L'analyse statique vous dit que f() est utilisée alors que si $y est
bien un nombre, f() n'est jamais appelée... Évidemment si $y est un
objet avec un overload de '*', ce n'est plus la même chose ;-)


Ce faux positif ne me dérange pas. Quand l'API de f change, mieux vaut
être sûr de bien changer partout. C'est ma principale utilisation de mon
analyseur statique, changer les API, les noms ou les packages de certaines
fonctions.

C'est déjà mieux que rien je trouve, car cela ne nécessite pas
d'exécuter le code, ce qui peut ne pas être trivial (ex: modperl)


Il est toujours possible de faire des jeux de tests sur une plateforme
complète (apache + mod_perl)... C'est pas évident mais, pour de gros
développements, ça vaut le coup.


Tout est toujours possible, mais il faut voir le travail engendré. Un
simple analyseur statique, c'est beaucoup moins de travail, et déjà 95%
de fait.
Cela n'exclut pas une plateforme de tests dynamiques, mais cela abat
déjà une certaine quantité de travail triviale.

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>
Dépêches sur le nommage <news://news.dotandco.net/dotandco.info.news>