Compréhension d’un programme à travers la segmentation et l’analyse des traces

Pour faire les tâches de maintenance d’un grand système logiciel, les ingénieurs logiciels doivent comprendre comment ce système est construit. La compréhension de ce système permet aux ingénieurs logiciels d’effectuer des activités comme le débogage, l’évolution ou l’amélioration des performances du système. La difficulté qui fait face aux mainteneurs lorsqu’ils essaient de comprendre le comportement d’un système est que souvent la documentation ne reflète pas l’implémentation du système. Ceci peut être dû au cout élevé de la modification de la documentation, à une documentation initiale de mauvaise qualité (ou même inexistante), ou au fait que le concepteur original du système a passé à une autre projets ou d’autre entreprise, etc. Plusieurs approches sont proposées pour aider les ingénieurs logiciels à comprendre le comportement des systèmes. L’objectif de ces approches est de réduire le temps consacré aux tâches de maintenance.

Les ingénieurs logiciels ont généralement recours à l’analyse du code source pour comprendre le comportement des logiciels. Une solution potentielle consiste à utiliser les techniques de fouille de texte mises au point à l’origine pour faciliter l’analyse de grands corpus de textes écrits en langues naturelles telles que l’anglais. Ces techniques peuvent être adaptées et appliquées à des problèmes d’ingénierie logicielle tels que l’analyse de traces.

Quelle que soit la méthode utilisée pour analyser le code source, il existe deux catégories de techniques d’analyse du code source, soit l’analyse statique et l’analyse dynamique. On utilise ces deux techniques selon que l’analyse nécessite l’exécution du système ou non (Corbi, 1989).

L’analyse statique est basée sur l’analyse de tout le code source du programme sans l’exécuter. Elle donne une vue complète du système; cependant, lorsque les ingénieurs logiciels ont besoin de comprendre une partie du système, elle devient un inconvénient, de plus, les concepts de programmation avancés tels que la ligature dynamique, le polymorphisme et le parallélisme rendent difficile l’application de l’analyse statique (Shafiee, 2013). L’analyse dynamique se concentre sur une partie du système par l’exécution d’un scénario choisi par le mainteneur. L’exécution d’un scénario permet aux mainteneurs de se concentrer sur les parties du système qui les intéressent. L’analyse dynamique est souhaitable aussi lorsque le mainteneur veut comprendre le comportement d’un système cible en lui donnant des entrées variées. Dans ce mémoire, on va plutôt se concentrer sur l’analyse dynamique.

Les donnes collectées au cours de l’exécution du scénario sont généralement stockées dans un fichier appelé trace d’exécution (Pirzadeh, 2012). Nous pouvons tracer n’importe quel aspect d’un système et le type de la trace dépend de ce que nous voulons savoir sur lui. Une trace peut être une trace d’appels de méthodes, une trace d’instructions, ou une trace de communication entre processus, etc. Les traces générées par l’exécution d’un scénario ont une taille importante, ils peuvent atteindre plusieurs milliers de lignes par exécution, ce qui rend difficile leur analyse manuelle. Il est donc nécessaire de trouver des solutions pour abstraire les traces de grande taille afin de faciliter leur compréhension. Plusieurs approches ont été proposées pour abstraire les traces de grande taille (voir Cornelissen et al. (2009) pour une étude sur ces approches). Récemment, la plupart de ces approches reposent sur le concept de la segmentation des traces. Le but est de segmenter une trace de grande taille en un ensemble de phases qui reflètent les phases d’exécution d’un programme (voir Pirzadeh et Hamou-Lhadj (2011a), Medini et al. (2012), Medini et al. (2014), Benomar et al. (2014), Pirzadeh et Hamou-Lhadj (2011b), Pirzadeh et al. (2011)).

Dans ce mémoire nous proposons une approche de segmentation des traces basées sur les lois de Gestalt (similarité et continuité). Ces lois sont introduites en psychologie et indiquent que nos perceptions obéissent à un certain nombre de lois qui nous aident à reconnaître les formes. Ils expliquent comment notre système de perception se fonctionne afin de regrouper visuellement les objets perçus en fonction de leur contexte pour construire des formes qu’on peut les reconnaître. (Koffka, 1935). Nous étendons une approche existante (Pirzadeh et al., 2011) en incorporant aussi un rapproche des éléments de la trace selon la similarité dans les paramètres et valeurs de retours des méthodes : si deux méthodes ont un paramètre ou valeur de retour similaire on va rapprocher ces deux méthodes l’une vers l’autre. Cette approche résume ensuite chaque phase résultant de la segmentation pour faciliter la compréhension de ces phases par les mainteneurs.

LA MAINTENANCE LOGICIELLE ET LA COMPRÉHENSION DES PROGRAMMES

La maintenance logicielle est définie dans la norme IEEE 1219 comme : «la modification d’un logiciel après son entrée en production, afin de corriger ses erreurs, d’améliorer ses performances ou autres attributs, ou pour adapter le produit à un environnement modifié.» (IEEE-1219, 1998).

La compréhension des systèmes accélère considérablement les tâches de maintenance (Khoury et al., 2016). Cette compréhension nous permet de faire des taches de maintenance comme le débogage (Jerding et Stasko, 1998), l’amélioration des fonctionnalités (Systa, 2000), ou l’analyse de performance (Becker et al., 2007).

La compréhension des systèmes est définie comme l’activité consistant à comprendre comment fonctionne un système logiciel ou une partie de celui-ci (Maalej et al., 2014). Les ingénieurs dans cette discipline passent entre 50 % et 60% de leur temps à comprendre un système (Basili, 1996). Il existe plusieurs modèles pour comprendre le fonctionnement des programmes (Storey, 2006; Hamou-Lhadj, 2005). Nous les décrivons brièvement ci-dessous.

LE MODÈLE DESCENDANT

Ce modèle est utilisé généralement lorsque le mainteneur est familiarisé avec le système. Celui-ci débute son travail par des suppositions sur le dit système. Par la suite, il vérifie ses suppositions initiales en les projetant sur un code source (Brooks, 1977). On peut appliquer un tel modèle à l’analyse des traces en effectuant une comparaison entre les hypothèses de départ sur la trace et le code source du système. Ainsi, un premier travail d’investigation est alors complété (Hamou-Lhadj, 2006).

LE MODÈLE ASCENDANT

Dans ce modèle, l’ingénieur logiciel commence par la lecture du code source plusieurs fois pour construire une idée sur le code (Letovsky, 1986). Ce modèle peut être appliqué à l’analyse des traces par l’exploration des lignes de la trace, et en essayant d’attribuer des résumés aux différents patrons de lignes.

LE MODÈLE INTÉGRÉ

Le troisième modèle, appelé le modèle intégré, est fréquemment employé par les ingénieurs logiciels. En théorie, il consiste à combiner l’utilisation des deux modèles expliqués ci-haut, soit descendant et ascendant. En pratique, les mainteneurs s’accordent à n’utiliser que l’un ou l’autre modèle selon leurs besoins (Pirzadeh, 2012).

LE CONCEPT DE TRACE D’EXÉCUTIONS

Une trace d’exécution est l’ensemble des évènements collectés au cours de l’exécution d’un scénario sur un programme donné. On retrouve différents types d’événement collectés. À ce sujet, le mainteneur peut tracer les appels des méthodes (nom, valeurs de retour, paramètres, niveau d’imbrication des méthodes), ou encore la communication entre les processus ou autres aspects jugés utiles pour la bonne comprehension du système (Shafiee, 2013). Dans ce mémoire, nous nous intéressons aux traces d’appels de méthodes. Lorsque nous évoquons ce dernier concept, nous faisons référence aux fonctions, routines et procédures.

Une trace peut être générée par instrumentation du code source. Celle-ci consiste à ajouter des instructions au code source original. On peut citer ici comme exemple l’ajout des instructions d’impression. On peut également instrumenter le bytecode du programme ou encore l’environnement d’exécution (système d’exploitation ou machine virtuelle) (Hamou Lhadj, 2005).

Une autre façon de générer une trace d’exécution d’un programme consiste à utiliser la programmation orientée aspect (POA). Cette méthode permet en effet aux ingénieurs d’insérer des bouts de code dans le programme sans altérer le code source. On peut aussi utiliser le débogueur pour générer une trace; dans ce cas l’ingénieur place des points d’arrêt dans le programme (Shafiee, 2013). Dans notre travail, nous allons utiliser la programmation orientée aspect pour générer les traces. Ce type de programmation permet de recueillir toutes les informations des méthodes sans pour autant modifier le code source. Ces informations renferment des paramètres de méthodes, des valeurs de retour, les noms des méthodes et autres informations pertinentes sur les méthodes.

Table des matières

1 Introduction 
1.1 Problème et motivations
1.2 Méthodologie
1.3 Contributions
1.4 Organisation
2 État de l’art 
2.1 La maintenance logicielle et la compréhension des programmes
2.2 Le concept de trace d’exécutions
2.3 Le concept de phase d’exécution
2.4 L’analyse des traces et la fouille de texte
2.5 La psychologie de la forme et la segmentation des données
2.6 Le résumé des traces
2.7 Segmentation des traces
3 Présentation de l’approche  
3.1 Segmentation à trois facteurs
3.2 Extraction d’éléments clés
3.3 Élimination d’utilitaires et minimisation de résumé
3.4 Implémentation de l’approche
4 Expérimentation 
4.1 Systèmes cibles
4.2 Générer les traces
4.3 Étude quantitative
4.4 Étude qualitative
Conclusion

Cours gratuitTélécharger le document complet

Télécharger aussi :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *