Brevet FR2929727A1 — publié le 20091009

AJOUT DE CODE UTILISATEUR DANS UN CODE SOURCE GENERE La présente invention concerne un procédé de modification d'un code source généré par ajout de code utilisateur. Dans ce qui suit, les termes suivants sont utilisés avec le sens indiqué : • � application logicielle � : désigne tout programme ou ensemble de programmes fonctionnant conjointement, dans le but de rendre des services à leurs utilisateurs. • � code source � : texte écrit dans un langage de programmation ou de description, qui est ensuite compilé en langage machine afin d'être exécuté par une plate-forme informatique matérielle, ou interprété par un environnement matériel ou logiciel d'interprétation. • � compilation � : action de traduction d'une description exprimée dans un langage de programmation vers le langage natif d'une plate-forme informatique matérielle avant son exécution par cette plate-forme informatique matérielle. • � génération de code � : désigne ici la production automatique ou semi-automatique de code source pour une application informatique, au moyen d'un générateur de code. Le générateur de code opère à partir d'une description abstraite (modèle). Le générateur, après analyse de la description, construit le code attendu en sortie. Cette description est généralement exprimée dans un langage de plus haut niveau que celui dans lequel le code sera produit et est indépendant de ce dernier. • � Classe � : désigne la notion de classe communément manipulée dans les langages de programmation orientés objet et notamment l'agrégation de données et de traitements (ou attributs et méthodes respectivement) destinés à fonctionner ensemble dans une application informatique. Dans les langages orientés objet, chaque type d'objet est défini par sa classe. Une classe représente l'ensemble des objets partageant les mêmes attributs, opérations, méthodes, relations et sémantique. • � package � : désigne une unité regroupant des classes. • � héritage � : relation attachant deux classes, dans laquelle une classe hérite des propriétés (attributs et méthodes) d'une classe parente et permettant à la première d'enrichir sa propre définition avec celle de la seconde, tout en conservant ses caractéristiques d'origine. • � objet � : désigne en programmation orienté objet, une instance de classe, constitué d'un ensemble de données et des procédures utiles à leur manipulation. • � programmation orientée objet � : type particulier de programmation dans lequel on utilise un langage de programmation orienté objet (par exemple Java, C++, C#), manipulant des classes et des objets. • � langage de programmation orienté objet � : langage permettant de décrire des actions destinées à être exécutées par un ordinateur après compilation, dont les composants de base sont des classes, dont les instances (les objets) vivent dynamiquement dans le programme informatique qui les utilise. • � modélisation � : désigne la représentation abstraite d'un problème ou d'un système, réalisée dans un but de résolution du problème ou d'implémentation concrète du système. • � modélisation orientée objet � : désigne un type particulier de modélisation, dans laquelle les éléments de modélisation sont des classes, objets, attributs, méthodes, etc. On connaît un domaine de l'informatique dit � génie logiciel �, qui désigne l'ensemble des méthodes, techniques et outils concourant à la conception et au développement d'applications logicielles, dans le but d'en optimiser la production, jusqu'à parvenir à une industrialisation de leur développement. Cette branche de l'informatique s'intéresse plus particulièrement à la manière dont le code source d'une application logicielle est spécifié, puis produit. Parmi les fonctionnalités mises en oeuvre par le génie logiciel, on retrouve donc souvent la génération de code source à partir d'un modèle, dit modèle métier, reposant par exemple sur une modélisation orientée objet. Une fois le code source généré, le développeur s'emploie souvent à ajouter des modifications dans des fichiers du code source généré, afin de tenir compte par exemple de besoins spécifiques d'utilisateurs dans l'application développée au final. La figure 1 montre un diagramme représentant schématiquement les principales étapes réalisées par un développeur dans le cadre du développement d'une application logicielle. Le développement de l'application comprend une première étape 100 de création d'un modèle 50, à partir d'éléments de modélisation orientée objet par exemple. Une étape 110 de génération de code dans un langage orienté objet quelconque, par exemple en langage Java, est alors mise en oeuvre. Pour ce faire, le développeur exécute le générateur de code, qui récupère le modèle et génère le code source 60 dans le langage de programmation Java par exemple, sous forme de fichiers .java. Une fois générés, les fichiers .java peuvent être compilés à l'aide d'un compilateur Java sous forme de fichiers dont l'extension est de type .class. Le ou les développeurs de l'application sont alors souvent amenés à gérer des besoins de modification du code source ainsi généré, consistant en l'ajout de fonctions utilisateurs dans le code source généré et en leur prise en compte par le générateur de code lors de la regénération du code source. Une étape 120 de développement de code utilisateur 70, correspondant à une fonction utilisateur à ajouter dans le code source généré est mise en oeuvre. Une méthode classique d'implémentation de cette étape consiste à éditer le fichier de code source généré de type .java existant devant être modifié et à ajouter les modifications (le code utilisateur écrit manuellement) dans ce fichier entre des marqueurs 10 15 2035 spécifiques, que le générateur de code saura reconnaître. Plus précisément, soit l'exemple suivant dans lequel l'extrait 61 de code source généré que le développeur souhaite modifier correspond au fichier Person.java ci-dessous, permettant à l'utilisateur de récupérer le nom complet d'une personne sous la forme d'abord du prénom, puis du nom de famille : package com.jaxio.example; public class Person { private String firstname; public String getFirstName() { return firstname ; } private String lastname; public String getLastName() { return lastname ; } } Supposons que le développeur souhaite modifier ce fichier Person.java, de manière à ajouter une fonction 25 utilisateur à la classe Person générée, appelée getName, permettant à l'utilisateur de récupérer le nom complet d'une personne sous la forme prénom et nom de famille ensemble. Il doit donc pour ce faire d'abord éditer le fichier Person.java puis exécuter une étape 30 62 d'insertion manuelle entre deux marqueurs du code utilisateur correspondant à la fonction utilisateur getName à ajouter: package com.jaxio.example; public class Person { 5 10 15 35 private String firstname; public String getFirstName() { return firstname ; } private String lastname; public String getLastName() { return lastname ; } // MARQUEUR DEBUT CODE MANUEL public String getName() { return getFirstName() + � � + getLastName(); } // MARQUEUR FIN CODE MANUEL } Ainsi, grâce aux marqueurs, le générateur de code 20 pourra facilement repérer le code correspondant à la fonction getName lors d'une regénération. Typiquement, avant de générer le code, il détecte le fichier existant Person.Java, l'analyse et stocke le code applicatif à ajouter en mémoire. Il regénère alors le 25 fichier, avec potentiellement des modifications indépendantes des modifications apportées par le développeur (ci-dessous la fonction getEmail par exemple, qui provient simplement d'une évolution du modèle entre les deux générations), puis ajoute au 30 nouveau fichier généré le code utilisateur en conservant également les marqueurs. package com.jaxio.exemple; public class Person { private String firstname; public String getFirstName() { return firstname ; } 10 15 private String email; public String getEmail() { Return email ; } private String lastname; public String getLastName() { return lastname ; } // MARQUEUR DEBUT CODE MANUEL public String getName() { return getFirstName() + � � + getLastName(); } // MARQUEUR FIN CODE MANUEL } 20 Cette solution d'ajout de fonctions par le développeur dans le code source généré comporte cependant des contraintes importantes. Ainsi, dès lors qu'un fichier de code source généré comprend classiquement plusieurs centaines de 25 lignes, le code spécifique écrit par le développeur, i.e. le code utilisateur, se retrouve � noyé � dans le code généré. Il est par conséquent difficile d'une part, pour son auteur de l'identifier clairement et, d'autre part, pour ses collègues développeurs de se 30 l'approprier de manière naturelle. En outre, dans un processus de développement, toutes les équipes de développeurs utilisent classiquement un gestionnaire de source, référencé 80 à la figure 1. Il s'agit par exemple d'un serveur central 35 dans lequel sont publiés tous les fichiers écrits par les développeurs, qui permet ainsi de travailler à plusieurs sur une même base de code source et de conserver un historique des modifications, d'où l'on peut par exemple extraire des statistiques. Il est couramment admis que les librairies binaires ou le code source généré ne doivent pas être inclus dans les gestionnaires de source. Cependant, à partir du moment où du code est inséré par le développeur dans un fichier de code source généré, selon la méthode exposée plus haut, le fichier complet doit être envoyé au gestionnaire de source 80, comme symbolisé par la flèche 81 sur la figure 1. D'où il résulte que les modifications apportées par la regénération du code elle-même (par exemple la fonction getEmail décrite plus haut) seront également envoyées au gestionnaire de source, ce qui est contraire à l'usage. En effet, cela augmente les risques de conflits entre les différents développeurs et fausse les statistiques que le gestionnaire de source peut produire comme, par exemple, le nombre de lignes de code utilisateur écrites manuellement par l'équipe de développeur. La présente invention a donc pour but de remédier à ces inconvénients et vise à résoudre, pour les langages orientés objets, tels que Java, les problèmes liés à l'ajout de fonctions par le développeur dans le code source généré et à la prise en compte de ces modifications par le générateur de code lors de la regénération du code source. Cet objectif est atteint par la prévision d'un procédé de modification d'un code source généré en langage de programmation orienté objet par un générateur de code à partir d'un modèle, consistant à ajouter au moins une fonction utilisateur dans au moins un fichier généré déclarant une classe générique du code source, ledit procédé étant caractérisé en ce qu'il comprend les étapes suivantes de : -création d'un premier fichier, déclarant une classe spécifique sous le même nom que celui de la classe générique, avec uniquement le code correspondant à la fonction utilisateur à ajouter, ladite classe spécifique étendant en outre une classe non référencée du code source, -regénération du code source, comprenant l'exécution par le générateur de code d'étapes de: -suppression dudit fichier généré, suite à la détection du premier fichier créé, -création d'un second fichier du nom de la classe non référencée étendue, dont le contenu correspond à celui qui aurait été généré pour ladite classe générique. La classe non référencée est avantageusement associée à un identifiant spécifique, adapté à indiquer au générateur de code de générer le second fichier avec le contenu correspondant à celui qu'il aurait généré pour la classe générique. Selon un mode de réalisation, ledit premier fichier créé est enregistré séparément du code source généré, sous le même nom que ledit fichier généré. De préférence, le procédé comprend une étape d'envoi du seul premier fichier créé vers un gestionnaire de source, adapté à conserver un historique des modifications. Selon un mode de réalisation, le code source généré ayant été compilé avant modification, l'étape de suppression comprend en outre une étape de suppression dudit fichier généré compilé. De préférence, le contenu du second fichier créé comprend des objets générés provenant d'une évolution du modèle orienté objet entre deux générations de code source. De préférence, le procédé comprend une étape de compilation du code source modifié. Le langage de programmation orienté objet mis en oeuvre dans le procédé est de préférence le langage Java, C++, C# ou tout autre langage approprié pour l'application du procédé selon l'invention. L'invention concerne également un produit programme d'ordinateur comprenant des instructions de code de programme enregistré sur un support utilisable dans ou par un ordinateur, comprenant des moyens de génération de code adaptés à générer un code source en langage de programmation orienté objet à partir d'un modèle, et des moyens de modification adaptés à ajouter au moins une fonction utilisateur dans au moins un fichier généré déclarant une classe générique dudit code source, caractérisé en ce que les moyens de modifications comprennent : -des moyens de détection d'un premier fichier, déclarant une classe spécifique sous le même nom que celui de ladite classe générique, avec uniquement le code correspondant à la fonction utilisateur à ajouter, ladite classe spécifique étendant en outre une classe non référencée du code source, - des moyens de suppression dudit fichier généré, - des moyens de création d'un second fichier du nom de la classe non référencée étendue, dont le contenu correspond à celui qui aurait été généré pour ladite classe générique. D'autres caractéristiques et avantages de la présente invention apparaîtront plus clairement à la lecture de la description suivante donnée à titre d'exemple illustratif et non limitatif et faite en référence aux figures annexées dans lesquelles - la figure 1 est un schéma illustrant les principales étapes réalisées dans le cadre du développement d'une application logicielle et de la modification de son code source généré selon l'état de l'art, - la figure 2 est un schéma illustrant le principe de modification du code source généré selon la présente invention. Sur la figure 2, les références de la figure 1 sont reprises pour désigner des éléments semblables. Reprenons l'exemple précédent du fichier généré Person.java, que le développeur souhaite modifier pour y ajouter la fonction utilisateur getName, déjà décrite plus haut dans le cadre de cet exemple. Selon l'invention, plutôt que de modifier le fichier Person.java existant, c'est-à-dire celui précédemment généré, le développeur crée un nouveau fichier Person.java 71. Ce nouveau fichier créé est donc enregistré sous le même nom que le fichier 5 Person.java précédemment généré, dans un répertoire connu du générateur, avec le code suivant : package com.jaxio.example; public class Person extends PersonBase { public String getName() { return getFirstName() + � � + getLastName(); } } 10 Tout d'abord, ce nouveau fichier créé ne comprend que le code utilisateur 70 écrit manuellement, correspondant à la fonction utilisateur getName à ajouter. Il ne reprend donc pas le code généré correspondant au fichier Person.java précédemment 15 généré, en l'occurrence la déclaration des fonctions getFirstName, getLastName, etc. En outre, le nom de la classe correspondante et son package n'ont pas changé par rapport à la classe générée dans le fichier Person.java existant. Il s'agit 20 toujours de la classe Person. Ainsi, on peut analyser la classe Person du nouveau fichier créé comme une classe spécifique, en ce qu'elle recouvre des aspects spécifiques du code qui sont liés à la fonction utilisateur, tandis que la classe Person précédemment 25 généré s'analyse comme une classe générique, en ce qu'elle recouvre des aspects génériques du code, qui sont liés à la génération du code à partir du modèle. Enfin, la classe Person du nouveau fichier créé Person.java étend une classe nommée PersonBase, non 30 référencée dans le code source généré et qui n'existe donc pas à ce stade. Bien entendu, ce code ne peut pas compiler tel quel puisque d'une part, la classe PersonBase étendue n'existe pas et que, d'autre part, il existe 2 fichiers nommés Person.java, le nouveau fichier créé et le fichier précédemment généré, ce qui n'est pas permis par le compilateur Java pour un même package. L'invention prévoit alors à ce stade une étape de regénération du code source, de manière à prendre en compte l'ajout du code source utilisateur et remettre le code en état d'être compilé. Dans cette étape, le générateur est tout d'abord prévu pour détecter le nouveau fichier créé 71 Person.java. Le générateur identifie également le lien d'héritage entre la classe Person de ce fichier et la classe PersonBase. Suite à cette détection, le générateur est prévu pour supprimer l'ancien fichier Person.java précédemment généré. Dans le cas où le code source aurait déjà été compilé avant la mise en oeuvre de l'étape de modification du code source généré, le générateur de code supprime également le fichier correspondant compilé Person.class. A ce stade, il n'y a alors plus qu'un seul fichier Person.java, en l'occurrence le fichier créé 71 ne contenant que le code correspondant à la fonction utilisateur. Puis, le générateur de code est prévu pour générer automatiquement, à la place de l'ancien fichier Person.java précédemment généré et dorénavant supprimé, un fichier 64, nommé PersonBase.java, du nom de la classe étendue par la classe Person du nouveau fichier 71 Person.java créé, appartenant au même package, et 5 10 15 20 comprenant un contenu identique à celui qu'il aurait généré dans le cas nominal, c'est-à-dire le contenu correspondant à la génération de la classe Person à partir du modèle : package com.jaxio.example; public class PersonBase { private String firstname; public String getFirstName() { return firstname ; } private String email; public String getEmail() { Return email ; } private String lastname; public String getLastName() { return lastname ; } } Cette action du générateur de code peut être 25 déclenchée par la reconnaissance d'un identifiant spécifique associé à la classe étendue non référencée, adapté à indiquer au générateur de code de générer ce second fichier 64 avec le contenu correspondant à celui qu'il aurait normalement généré pour la classe Person. 30 Dans l'exemple, cet identifiant spécifique est constitué par le suffixe � Base �, ajouté à la fin du nom de la classe Person. De cette manière, le générateur de code sait qu'il doit regénérer le contenu de la classe Person, mais sous le nom de la classe 35 étendue PersonBase. En plus des fonctions getFirstName et getLastName générées automatiquement pour la classe Person, on retrouve également la fonction getEmail, qui provient simplement d'une évolution du modèle entre les deux générations. La classe étendue PersonBase précédemment manquante dans le code source générée PersonBase existe alors à présent. A ce stade, le code modifié peut donc être compilé sans erreur. Le procédé selon l'invention permet avantageusement au développeur d'insérer du code utilisateur dans le code source généré, sans qu'il lui soit nécessaire d'éditer manuellement le fichier de source généré devant être modifié. Grâce au lien d'héritage 72 défini entre la classe Person du fichier 71, ne contenant que le code utilisateur et la classe PersonBase du fichier 64, reprenant le code généré pour la classe Person dans le cas nominal, toute propriété ou méthode non privée de la classe PersonBase est accessible au travers de la classe Person, de sorte que les autres classes générées 63 du code source 60 qui utilisent la classe Person ne voient pas leur utilisation de la classe en question impactée par ce mode opératoire de modification du fichier Person.java précédemment généré. Par ailleurs, le code modifié est plus modulaire, dans la mesure où, à l'issue de la modification du fichier Person.java précédemment généré pour la classe Person, on a dorénavant deux classes au lieu d'une, en l'occurrence la classe Person et la classe PersonBase, dédiées, pour la première, aux seuls aspects spécifiques du code, i.e. liés à l'ajout du code utilisateur et, pour la seconde, aux aspects génériques du code, i.e. liés au modèle métier et à ses évolutions éventuelles. Cette façon de faire permet donc de mieux séparer ces différents aspects, spécifiques et génériques, du code modifié. Le code utilisateur écrit manuellement est en effet isolé dans un fichier séparé du code généré. Ainsi, il n'est pas nécessaire d'envoyer au gestionnaire de source 80 l'ensemble du code généré (i.e. contenu de PersonBase.java), mais il suffit juste de publier dans le gestionnaire de source le fichier Person.java, qui ne comprend que les quelques lignes de code utilisateur ajouté. L'étape d'envoi du fichier Person.java vers le gestionnaire de source 80 est symbolisée par la flèche référencée 82 sur la figure 2. Cette séparation entre les parties de code utilisateur ajoutées au code généré et le code généré lui-même permet d'optimiser le travail lorsque plusieurs développeurs sont amenés à mettre à jour le code généré. De plus, à partir du moment où du code utilisateur est inséré directement dans un fichier de code source généré, comme décrit en référence à la figure 1, le fichier complet doit être envoyé au gestionnaire de source, de sorte que les modifications apportées par l'évolution du modèle et la regénération elle-même en découlant (exemple la fonction getEmail plus haut) impliquent de publier à nouveau le fichier complet dans le gestionnaire de source. Avantageusement, le code utilisateur ajouté au code généré étant séparé du code généré, la seule évolution du modèle et la regénération du code en découlant n'impose aucune publication au niveau du gestionnaire de source. REVENDICATIONS1. Procédé de modification d'un code source (60) généré en langage de programmation orienté objet par un générateur de code à partir d'un modèle (50), consistant à ajouter au moins une fonction utilisateur dans au moins un fichier généré (61) déclarant une classe générique du code source, ledit procédé étant caractérisé en ce qu'il comprend les étapes suivantes de -création d'un premier fichier (71), déclarant une classe spécifique sous le même nom que celui de la classe générique, avec uniquement le code (70) correspondant à la fonction utilisateur à ajouter, ladite classe spécifique étendant en outre une classe non référencée du code source, -regénération du code source, comprenant l'exécution par le générateur de code d'étapes de: -suppression dudit fichier généré (61), suite à la détection du premier fichier créé, -création d'un second fichier (64) du nom de la classe non référencée étendue, dont le contenu correspond à celui qui aurait été généré pour ladite classe générique. 2. Procédé selon la revendication 1, caractérisé en ce que la classe non référencée est associée à un identifiant spécifique, adapté à indiquer au générateur de code de générer le second fichier avec le contenucorrespondant à celui qu'il aurait généré pour la classe générique. 3. Procédé selon la revendication 1 ou 2, caractérisé en ce que ledit premier fichier créé est enregistré séparément du code source généré, sous le même nom que ledit fichier généré. 4. Procédé selon l'une quelconque des revendications 1 à 3, caractérisé en ce qu'il comprend une étape d'envoi (82) du seul premier fichier créé vers un gestionnaire de source (80), adapté à conserver un historique des modifications. 5. Procédé selon l'une quelconque des revendications précédentes, caractérisé en ce que le code source généré ayant été compilé avant modification, l'étape de suppression comprend en outre une étape de suppression dudit fichier généré compilé. 6. Procédé selon l'une quelconque des revendications précédentes, caractérisé en ce que le contenu du second fichier créé comprend des objets générés provenant d'une évolution du modèle orienté objet entre deux générations de code source. 7. Procédé selon l'une quelconque des revendications précédentes, caractérisé en ce qu'il comprend une étape de compilation du code source modifié. 8. Procédé selon l'une quelconque des revendications précédentes, caractérisé en ce que le langage de programmation orienté objet est le langage Java ou C++ ou C#. 9. Programme d'ordinateur comprenant des instructions de code de programme pour l'exécution des étapes du procédé selon la revendication 1 lorsque ledit programme est exécuté sur un ordinateur.