Refactoring avec Delphi 2007

Sébastien Doeraene

Présentation des outils de refactoring de Delphi 2007 ne nécessitant pas le support de Together dans le projet.

Vous êtes invité à réagir à cet article sur les blogs, et à y laisser un commentaire. ♪

- Titre : Refactoring avec Delphi 2007

- Auteur : Sébastien Doeraene

- Parution : 22 mai 2007

- Licence : Copyright ® 2007 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Introduction

- I. Renommer

- I-A. But de l'opération

- I-B. Applicable sur…

- I-C. Utilisation

- I-D. Remarques

- II. Extraire une méthode

- II-A. But de l'opération

- II-B. Applicable sur…

- II-C. Utilisation

- II-D. Remarques

- III. Extraire une chaîne de ressources

- III-A. But de l'opération

- III-B. Applicable sur…

- III-C. Utilisation

- III-D. Remarques

- IV. Déclarer une variable ou un champ

- IV-A. But de l'opération

- IV-B. Applicable sur…

- IV-C. Utilisation

- IV-D. Remarques

- V. Modifier les paramètres

- V-A. But de l'opération

- V-B. Applicable sur…

- V-C. Utilisation

- V-D. Remarques

- VI. Liens

Introduction

Nous savons tous qu'un code écrit n'est pas figé. Qu'une modélisation rédigée n'est pas permanente. Il arrive plus que fréquemment qu'il faille repasser sur le travail déjà accompli. Que celui-ci l'ait été dans les règles de l'art ou, comme il est coutume de dire, « à l'arraché ».

Des besoins récurrents sont le renommage d'objets ou l'insertion de données supplémentaires au sein de classes. Dans le cadre d'une traduction de logiciel, on peut aussi vouloir transformer les chaînes littérales en chaînes de ressources. On appelle ces opérations des opérations de refactoring (traduit parfois en français comme réusinage).

Le fait est que ces opérations sont souvent ennuyeuses, longues, et donc sujettes à beaucoup d'erreurs. Imaginez toutes les conséquences que peut avoir le fait de renommer une propriété d'une classe !

Aujourd'hui, on trouve de plus en plus d'outils de refactoring. Des traitements automatiques sur le code ou la structure UML d'un projet, qui effectuent ces tâches en prévenant les erreurs possibles.

Depuis Delphi 2005, l'EDI propose un certain nombre d'opérations de refactoring. Si deux ou trois sont très intuitives, la plupart méritent un mot d'explication. Ce tutoriel propose de montrer l'utilisation des outils de refactoring de Delphi 2007 ne nécessitant pas le support de Together. Ces dernières feront sans doute l'objet d'un futur tutoriel.

Chacune des opérations décrites ci-dessous peut être trouvée dans le menu Refactoring de l'EDI, après avoir positionné le curseur correctement. Soit par le menu contextuel de l'éditeur de code, sous-menu Refactoring.

Les différents outils que je vais vous présenter ici fonctionnent tous sur le même schéma global, excepté le premier (renommer) :

1. Vous sélectionnez les options du refactoring choisi ;

2. Vous validez les options : aucune modification n'a lieu à ce moment ;

3. Dans la fenêtre Refactorings, vous pouvez voir les modifications qui vont être apportées ;

4. Cliquez sur le bouton Refactoring de cette fenêtre pour exécuter effectivement les modifications ;

5. Vous pouvez éventuellement annuler les modifications au moyen du bouton prévu à cet effet.

Fenêtre Refactorings

La différence pour Renommer est que vous pouvez, au moyen d'une case à cocher, choisir si vous voulez immédiatement appliquer le refactoring ou pas.

I - Renommer

Si cette opération est en haut de la liste, ce n'est pas un hasard. La fonction renommer est non seulement la plus utilisée, mais également la plus simple à utiliser.

I-A - But de l'opération

Renommer un type, champ, variable, méthode, propriété, ou tout autre identificateur – excepté une unité, en mettant à jour automatiquement toutes les références à celui-ci.

I-B - Applicable sur…

L'opération de renommage est applicable sur tout identificateur qui n'est pas une unité. Pour les méthodes à liaison dynamique (virtuelles et dynamiques, et leurs surcharges), le renommage n'est permis que si la déclaration initiale (celle qui porte le mot clef virtual ou dynamic) se trouve dans un projet ouvert. Cela est bien sûr toujours vrai si vous renommez directement cette déclaration initiale.

I-C - Utilisation

Boîte de dialogue Renommer

Dans la boîte de dialogue qui apparaît, choisissez simplement un nouveau nom pour l'identificateur.

I-D - Remarques

- Lorsqu'elle est utilisée sur une méthode à liaison dynamique, les méthodes surchargées dans les classes enfants et parents sont également renommées automatiquement.

- Cette opération ne fonctionne pas bien avec les routines et méthodes déclarées overload.

II - Extraire une méthode

C'est bien connu, on commence à implémenter les méthodes de sa classe, et on remarque qu'on utilise plusieurs fois la même portion de code. Bah… Copier-coller, à la vieille méthode… Et bonjour les duplications de code.

Mais non ! L'extraction de méthode vous permet de rationaliser votre code, et de factoriser les morceaux de code récurrents en une nouvelle méthode.

II-A - But de l'opération

Le but de l'extraction de méthode est de construire automatiquement une nouvelle méthode, privée en général, dont le code est une partie d'un code existant dans une autre méthode. Et cela en substituant les données externes au morceau de code à des paramètres, et les résultats à des paramètres var.

Parallèlement, le code déjà écrit est remplacé par un appel à cette nouvelle méthode.

II-B - Applicable sur…

L'extraction de méthode est applicable sur un ensemble d'instructions au sein d'une méthode déjà écrite. Les instructions concernées doivent être sélectionnées avant de lancer l'opération.

Il y a plusieurs exceptions à l'application de cette opération. Extrait de l'aide de Delphi 2007.

- Seules les instructions peuvent être extraites, pas les expressions.

- Dans Delphi, les instructions qui contiennent un appel à inherited ne peuvent pas être extraites.

- Les instructions contenues dans une instruction with ne peuvent pas être extraites.

- Les instructions qui appellent une procédure ou fonction locale ne peuvent pas être extraites.

J'ajouterais encore :

- du code contenant un appel à exit, break, continue ou goto devant faire sortir l'exécution du morceau sélectionné ne peut pas être extrait :

- des instructions assembleur ne peuvent être extraites, que ce soit dans leur entièreté (tout le bloc asm…end) ou pas.

II-C - Utilisation

Boîte de dialogue Extraire une méthode

Sélectionnez tout d'abord l'ensemble des instructions devant être factorisées dans la nouvelle méthode. Sachez que cette sélection sera automatiquement étendue pour couvrir les instructions dans leur entièreté. Cela signifie par exemple que, si vous sélectionnez une instruction if, le bloc dépendant de celui-ci, ainsi que du else correspondant éventuel, seront ajoutés à votre sélection.

La boîte de dialogue de l'opération de refactoring vous montre un aperçu de la méthode qui sera créée. Vous pouvez alors lui donner le nom que vous souhaitez. Validez, et l'opération s'exécute.

II-D - Remarques

- Cette opération gère aussi bien les routines que les méthodes, ou encore les méthodes de classe. Les nouvelles méthodes créées sont toujours du même type.

- L'extraction de méthode ne génère que des procédures, jamais de fonction. Les résultats sont renvoyés au moyen de paramètres var.

- Les méthodes générées sont toujours déclarées comme privées, et les routines n'ont pas de déclaration dans l'interface. À vous de déplacer/ajouter la déclaration si vous le désirez.

- Le contenu de la méthode extraite est réindenté à la « norme » CodeGear, et non tel que vous l'aviez écrit. Repassez donc dessus pour le remettre en forme selon vos goûts et habitudes.

III - Extraire une chaîne de ressources

Vous reprenez un ancien code que vous devez internationaliser ? Ou vous n'avez tout simplement pas encore la bonne habitude de déclarer les chaînes à traduire en chaînes de ressources ? Grâce à cette opération, vous pouvez facilement transformer une constante littérale chaîne en une chaîne de ressources.

III-A - But de l'opération

À partir d'une constante littérale chaîne – en d'autres mots, une chaîne dans votre code –, déclarer une chaîne de ressources (resourcestring) et remplacer l'ancienne référence par cette chaîne de ressources.

III-B - Applicable sur…

Cette opération est applicable sur toute chaîne de caractères littérale, à l'exception des cas suivants :

- les valeurs de constantes chaînes ;

- les valeurs par défaut de paramètres de routine ;

- les chaînes qui sont déjà des chaînes de ressource (c'est bête à dire, mais c'est le cas).

III-C - Utilisation

Boîte de dialogue Extraire une chaîne de ressource

Le curseur placé sur la chaîne à extraire, lancez l'opération de refactoring. Spécifiez simplement le nom que vous souhaitez donner à la chaîne de ressources, et validez.

III-D - Remarques

- Les chaînes extraites sont placées dans la section implémentation de l'unité courante. Si vous les voulez ailleurs, vous devrez les déplacer à la main ensuite.

- Seule la chaîne sélectionnée est remplacée par le nom de la chaîne de ressources. Si cette chaîne est utilisée plusieurs fois dans votre code, vous devrez remplacer les autres occurrentes à la main.

IV - Déclarer une variable ou un champ

Il arrive très fréquemment que, lors du codage, on ait besoin d'une variable supplémentaire, ou d'un champ de classe non prévu. Cette opération permet de déclarer automatiquement de nouvelles variables locales, et de nouveaux champs.

IV-A - But de l'opération

À partir d'un identificateur non déclaré – souligné en rouge par l'éditeur –, déclarer une variable locale ou un champ de classe.

IV-B - Applicable sur…

Ces deux opérations sont applicables sur un identificateur non déclaré au sein d'une routine ou d'une méthode. Dans le cas de l'extraction d'un champ, ce n'est valable que dans une méthode.

Bien que l'opération soit légitime pour l'identificateur MaVar dans MonObjet.MaVar, le résultat de l'opération sera erroné.

De même, l'extraction de champ dans une méthode de classe est valide, mais crée un champ d'objet (les champs de classe n'existent pas en Delphi), ce qui sera plus que probablement faux également.

IV-C - Utilisation

Boîte de dialogue Déclarer une variable

La boîte de dialogue de ce refactoring permet de choisir les choses suivantes :

- le type de la variable/du champ ;

- s'il s'agit d'un tableau et, le cas échéant, son nombre de dimensions (nombre de array of) – c'est toujours un tableau dynamique qui est généré ;

- dans le cas d'une variable, une éventuelle valeur initiale ;

- dans le cas d'un champ, sa visibilité.

IV-D - Remarques

- Le refactoring vous empêche de choisir un nom qui entrerait, d'une manière ou d'une autre, en conflit avec un autre élément.

V - Modifier les paramètres

Vous avez codé une fonction, vous l'avez beaucoup utilisée, et vous devez la modifier. Mais vous avez alors besoin d'un paramètre supplémentaire ! Aïe, tant de références à vérifier ! Ce refactoring permet de modifier les paramètres sans effort, et sans danger.

V-A - But de l'opération

Modifier les paramètres d'une routine ou d'une méthode, et mettre à jour les appels à celles-ci.

V-B - Applicable sur…

Cette opération est applicable sur n'importe quelle routine ou méthode.

Attention toutefois : même si son utilisation est légitime sur une méthode servant d'accesseur à une propriété, la propriété correspondante ne sera pas du tout modifiée. Il est donc impossible en pratique de s'en servir dans ces cas.

V-C - Utilisation

Boîte de dialogue Modifier les paramètres

La boîte de dialogue de ce refactoring est plus remplie que les autres. Elle contient une liste des paramètres, et des boutons permettant de les modifier.

Les boutons Vers le haut et Vers le bas permettent de changer l'ordre des paramètres.

Le bouton Ajouter vous proposera une boîte de dialogue permettant de donner le nom du champ, son type, une éventuelle valeur par défaut et le statut d'entrée/sortie du paramètre (var, out et const).

La valeur par défaut n'est pas ce que vous croyez ! Cela n'a aucun lien avec la valeur par défaut que vous pouvez spécifier avec le = dans la déclaration. Celle-ci indique la valeur à placer dans les appels à la méthode, une fois le refactoring effectué.

Le bouton Modifier permet de modifier un paramètre ajouté durant ce refactoring, au moyen de la même boîte de dialogue. Pas d'en modifier un qui était déjà présent avant.

Enfin, le bouton Enlever supprime un paramètre.

Une fois le refactoring effectué, les déclarations sont parfaitement modifiées. En revanche, vous devrez repasser à la main sur chaque appel. En effet, le refactoring ne fait que placer de nouvelles parenthèses, avec des virgules et les valeurs par défaut, devant les anciennes parenthèses. Il faut donc tout remodifier.

Néanmoins, puisque le refactoring vous indique dans sa fenêtre d'exécution toutes les références à la routine/méthode, ces modifications sont vite faites. Ce refactoring est donc tout de même très pratique.

V-D - Remarques

- Lorsque vous supprimez tous les paramètres d'une routine/méthode au moyen de ce refactoring, les déclarations reçoivent des parenthèses vides (), et les appels sont tout à fait inchangés.

VI - Liens

- Information about Refactoring