Thématiques principales

vendredi 29 décembre 2017

Construire un paquet Debian


Dans l’article précédent, nous avions vu comment préparer un dépôt debian viable de façon a faire des installation et des déploiements sur une plateforme debian [3].

Nous allons nous intéresser dans ce présent article sur comment alimenter notre dépôt et donc comment nous allons procéder pour construire un paquet debian.

Structure du paquet debian

Un paquet debian [4] n’est initialement qu’un tar.gz dont l'extension est .deb, construit à l’aide de la commande dpkg-deb (il existe d’autre approche comme jdeb [5]) qui sera déployé à la racine /. Cela signifie qu’il sera nécessaire lors de la conception du paquet de reproduire l’arborescence cible si l’on souhaite déployer des fichiers dans des répertoires précis du système.

Ainsi par exemple si l’on souhaite construire un paquet permettant de déployer un binaire dans le système, on créera un répertoire du nom du paquet dans lequel on trouvera le chemin /usr/bin/monBinaire:
/home/moi/monPaquet/usr/bin/monBinaire
Ainsi quand l’on construira le paquet, celui ci déposera monBinaire dans /usr/bin.

Cette démarche est valable pour tout fichier déposé statiquement dans le système. A noter que lors de cette étape, dpkg, le composant procédant à l’installation, fait le listing des fichiers déposés et défini le paquet (et ses éventuelles versions futur) comme responsable du cycle de vie du fichier dans le système. Ceci a pour intérêt de détecter lors de l’installation d'éventuels conflit entre paquet qui seront à traiter par des primitives particulières quand cela est possible [2] (ce ne sera pas le cas dans cet article). Pour que dpkg puisse clairement identifier le paquet, celui ci doit obligatoirement contenir un fichier de control contenant toutes les informations sur l’identité, la version, l’utilisation du paquet. Vous verrons plus loin dans l’article ou le déposer et comment le construire

Par contre si nous avons ici un moyen simple et efficace pour déployer des fichiers, nous n’avons rien pour dynamiquement configurer l’installation en fonction du système courant.
En effet, souvent, lors de l’installation, il est nécessaire de prendre en considération au mieux des besoins et de l’environnement en initialisant des fichiers de conf selon les autres applications présentes, le contexte réseau éventuel ou même des préférences utilisateurs.

La première approche est alors d’apporter statiquement des configurations par défaut et de les modifier après l’installation. Cette approche fonctionne si et seulement si l'application ne nécessite pas une synchronisation particulière avec d’autres applications du système qui nécessite un redémarrage (par exemple la prise en compte d’un plugin par une application amené par deux paquets différents qu’il faut nécessairement redémarrer)

Les fichiers du responsable


Pour répondre à ce problème spécifique, en plus du fichier de control (obligatoire) et il est possible de définir des fichiers du responsable (postinst, preinst, postrm et prerm). Ces fichiers sont à placer dans un répertoire DEBIAN de notre paquet. Notre paquet devient alors:
(/home/moi) ./monPaquet/usr/bin/monBinaire(/home/moi) ./monPaquet/DEBIAN/control (obligatoire)(/home/moi) ./monPaquet/DEBIAN/postinst (optionnel)(/home/moi) ./monPaquet/DEBIAN/preinst (optionnel)(/home/moi) ./monPaquet/DEBIAN/postrm (optionnel)(/home/moi) ./monPaquet/DEBIAN/prerm (optionnel)
Ces fichiers sont alors exécuter automatiquement par l’outil dpkg [6] pendant l’installation ou la suppression.

Par exemple la phase d’installation exécute les phases suivantes:



De la même façon la suppression d’un paquet exécute les fichiers du responsables comme suit:



Enfin leur combinaison permet d’obtenir le comportement que l’on aura lors d’une mise à jour:



A noter que les scripts peuvent être des simples fichiers qui s'exécutent indifféremment du contexte (pas de la phase) mais qu’il est possible de leur attribuer des spécificités selon que l’on fait justement par exemple une installation ou une mise a jour. Pour cela il est conseillé de s’appuyer sur un squelette de script par défaut ou skeleton [7] (que je ne détaillerai pas ici).

Le fichier de control

Voila maintenant que l’on a construit la structure du deb, il reste finaliser le debian en définissant dans le détail le fichier de control.

Le fichier de control est comme dit sommairement au début de cet article, la pièce d’identitée du paquet debian a construire.

Il se constitue des champs suivant [8] (directement extrait de la documentation):
Package: hello
Version: 2.9-2+deb8u1
Architecture: amd64
Maintainer: Santiago Vila <sanvila@debian.org>
Depends: libc6 (>= 2.14)
Conflicts: hello-traditional
Breaks: hello-debhelper (<< 2.9)
Replaces: hello-debhelper (<< 2.9), hello-traditional
Section: devel
Priority: optional
Homepage: http://www.gnu.org/software/hello/
Description: example package based on GNU hello
      The GNU hello program produces a familiar, friendly greeting.  It
      allows non-programmers to use a classic computer science tool which
      would otherwise be unavailable to them.
      .
      Seriously, though: this is an example of how to do a Debian package.
      It is the Debian version of the GNU Project's `hello world' program
      (which is itself an example for the GNU Project).
  • Le champ « Package » contient le nom du paquet. C'est le nom par lequel les outils de gestion de paquets peuvent le manipuler. Il est habituellement similaire mais pas nécessairement le même que la première chaîne composant le nom de l'archive Debian.
  • Le champ de « Version » donne le numéro de version du composant.
  • Le champ « Architecture » indique pour quel processeur ce binaire particulier a été compilé.
  • Le champ « Depends » donne une liste des paquets qui doivent être installés afin d'installer ce paquet avec succès.
  • La ligne « Section » indique la section où le paquet Debian est conservé sur les sites FTP de Debian.
  • Le champ « Maintainer » contient l'adresse électronique de la personne actuellement responsable de la maintenance du paquet.
  • Le champ « Description » fournit un bref résumé des fonctionnalités du paquet.

Bien sur tous ces champs suivant une nomenclature et de standards pour permettre de normaliser l’utilisation des paquets. Entre autre par exemple il est important de respecter certaines règles d'écriture du numéro de version afin de permettre des mises à jours conforme a l’attendu (voir les schémas du chapitre des fichiers du responsable sur les phases du cycle de vie d’installation, désinstallation et de mise à jour des paquets).

Chaque champs peut avoir son importance même s’ils ne sont pas obligatoire. Il convient donc de bien les étudier afin de prévenir ou de gérer les conflits entre paquets.

Construction du paquet debian

Pour finir cet article, il fait maintenant finaliser le packaging en construisant le .deb. Pour cela il suffit d’appeler la commande dpkg-deb:
dpkg-deb --build $REPERTOIRE_DEBIAN $REPO_DEBIAN/
avec REPERTOIRE_DEBIAN contenant le chemin du debian a packager et REPO_DEBIAN le répertoire de destination ou mettre le deb final (on privilégiera directement le dépôt debian)

Voila le paquet est construit et déposé dans un dépôt, il ne reste qu'à l’installer après une mise a jour du dépôt et un apt-get coté client.

Références

[1] http://blog.valouille.fr/2013/10/creer-un-paquet-debian-vide/
[2] https://www.debian.org/doc/manuals/debian-handbook/sect.package-meta-information.fr.html
[3] https://www.debian.org/doc/manuals/debian-faq/index.fr.html#contents
[4] https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.fr.html
[5] http://tcurdt.github.io/jdeb/
[6] https://www.debian.org/doc/debian-policy/#maintainer-script-flowcharts
[7] https://lists.debian.org/debian-mentors/1998/04/msg00004.html
[8] https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.fr.html#s-controlfile

mercredi 27 décembre 2017

QQOQCCP

Cet article sera court car il traite d’une approche simple mais efficace pour la préparation de projet mais aussi pour la rédaction d’article. Je m'étais intéressé à la question quand j’ai eu a faire ma thèse mais depuis j’avais un peu perdu le besoin, du coup me voici avec un article méthodologique de base mais qui pourra toujours servir.

Ainsi la question est comment rédiger un article ou identifier les éléments clefs d’un projet? Et bien en appliquant la règle des 7 questions: QQOQCCP [1] ou en 9 selon le cas [2] :
  • Qui : Identification des acteurs
  • Quoi : Solution apporté pour répondre au problème, il s’agit de la solution fonctionnelle
  • Ou : Ou sera produit la solution et ou est le problème
  • Quand : Quels sont les dates butoir du projet...
  • Comment : définition de la mise en oeuvre, il s’agit de la solution technique non fonctionnelle
  • Combien : en or ou en euro… bien sur c’est évident mais pour un projet… on peut aussi compter en jour
  • Pourquoi : Identification du facteur déclenchant, en termes plus simple, c’est quoi le problème, A quoi on va répondre?
  • Pour Qui : Définition des Use Case
  • Avec Quoi : Définition des moyens de mise en oeuvre de la solution
Ici cela recoupe l’analyse d’un projet mais dans le contexte de la rédaction d’article, il n’est probablement pas nécessaire d’aller aussi loin et tous ne serviront pas forcément ni seront les même selon les sujets. Il me semble pourtant que pour tout article il est systématiquement nécessaire de traiter les points suivant:
  • Pourquoi?
  • Pour Qui?
  • Quoi?
  • Comment?
  • Avec Quoi?
Bien sur comme il est dit dans l’article [2], le diable est dans les détails, et c’est effectivement lorsque l’on néglige quelques chose que cela nous explose à la figure. Donc même si dans le cadre d’article, ça ne parait pas forcément pertinent, se poser de bonnes questions, ne sera un luxe

Références

[1] https://www.piloter.org/qualite/qui-quoi-comment.htm
[2] http://www.rocketprojet.com/qqoqccp-recueil-besoins-9-questions/
[3] http://www.espacefrancais.com/les-types-de-plans-du-discours-argumentatif/

mardi 26 décembre 2017

Faire un dépôt debian

Un dépôt debian est un répertoire distant dans lequel se trouve des paquets debian [2] . Ces paquets sont accessible via les commandes apt [1] du système debian et la conjonction des deux mécanismes (apt+dépôts) permet l’installation et la maintenance des applications présent dans le système

Procédure d’installation debian

Lors de l’installation d’un paquet, on appellera la commande
apt-get install tee
La composant apt va télécharger depuis le dépôt via ftp ou http l’outil tee et le depackagera dans le système (pour les plus curieux sur la structure du paquet debian et son processus de déploiement : [4] mais je rédigerai un article à cet effet ).

L’installation n’est possible que si apt ne connait le contenu du dépôts. Pour cela, il est nécessaire de mettre à jour le référentiel connu de apt du dépôt distant en téléchargeant le package spécial : Packages.gz qui liste les paquets présent dans le dépôt. Il reste a appliquer la commande suivant:
apt-get update
Il manque encore une information importante: La localisation du dépôt qu’il est nécessaire de renseigner dans le fichier de configuration sources.list d'Apt (dans le répertoire /etc/apt)

Cependant pour renseigner ce fichier, il nous faut connaître la structure du dépôt et comment celui-ci se construit.

Structure d’un dépôt

Un dépôt debian n’est qu’un répertoire contenant des paquets debian. Ce répertoire va contraindre le nommage du dépôt. Pour que le dépôt soit viable, il doit contenir au moins un fichier Packages.gz cité plus haut dans un répertoire bien spécifique [6] . Ce répertoire est accessible via un chemin contenu dans le dépôt commençant par “dists” qui va spécifier divers informations facilitant le classement des paquets. Par exemple, il va être possible de distinguer les paquets propre à des architecture cibles différentes et des paquets pour les architectures  amd64, armhf, i386, etc.

Ce qui importe c’est d’avoir conscience que le chemin menant aux différents Packages.gz, va conditionner la façon dont on va référencer le dépôt coté client dans le sources.list.

Le fichier sources.list suit la syntaxe suivante [6] :
deb uri distribution [component1] [component2] [...]
  • la primitive deb spécifié qu’il s’agit d’un dépôt debian
  • uri est le chemin local ou réseau pour accéder au dépôt (généralement il est positionné derrière un serveur http apache)
  • distribution est le système cible mais celui ci est généralement le premier sous répertoire du chemin commençant par dists.
  • component* est un ensemble de sous répertoires au chemin suivant la distribution et avant le répertoire spécifiant l’architecture. Ils facilitent le classement des paquets selon leur utilisation (paquet de test, de sources, gratuit ou non, etc.)

Enfin le chemin se termine sur un répertoire spécifiant au moins une architecture.

Exemple si on considère un serveur apache exposant le chemin suivant:
(/var/www) ./debian/dists/maDistrib/all/binary-amd64/Packages.gz
Il faut spécifier dans le sources.list du client apt:
deb http://ipServer/debian maDistrib all 

Initialisation du dépôt

Maintenant que l’on a un dépôt debian, ou mettre nos paquets et comment procéder à son initialisation?

Dans la pratique les paquets debian produits sont déposés à la racine du paquet ou dans des sous répertoires de classement. Ces paquets sont ensuite indexés lors que la construction du Packages.gz a l’aide de la commande scanpackage [3].
cd $DEB_DIR; dpkg-scanpackages . /dev/null | gzip -9c > $DEB_DIR/dists/maDistrib/all/binary-amd64/Packages.gz
Voila les paquets sont accessibles il reste a mettre a jour le client (apt-get update) puis faire soit une installation ou une mise a jours (apt-get upgrade)

Nous intéresserons dans un autre article a la structure d'un paquet debian, a son cycle de vie et comment le produire.

References

[1] https://www.debian.org/doc/manuals/debian-faq/ch-pkgtools.fr.html#s-pkgprogs
[2] https://www.debian.org/doc/manuals/debian-faq/index.fr.html#contents
[3] https://wiki.debian.org/DebianRepository/Setup?action=show&redirect=HowToSetupADebianRepository
[4] Base sur le paquet bebian https://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.fr.html
[5] https://wiki.debian.org/DebianRepository/
[6] https://wiki.debian.org/DebianRepository/Format

samedi 23 décembre 2017

Les processus de développement ou cycles de vie du logiciel

Dans cet article faisons un état des lieux plus détaillé des cycles de vie les plus importants et les plus couramment utilisés. Après une présentation des cycles classiques comme ceux en Cascade ou en V, seront présentées des méthodes plus récentes basées sur l’agilité.

Les Classiques

Cycle en Cascade

Le cycle en cascade est typiquement un cycle de développement prédictif. Provenant du bâtiment, il part du principe que la construction nécessite, en général, un enchaînement logique ; la couverture d’une maison ne peut pas être effectuée sans avoir préalablement fait les fondations. Il définit une démarche de développement séquentiel (figure 2.9) où chaque phase conduit à la production d’un ou plusieurs livrable(s) qui doivent être validés avant d’être utilisés lors de la phase suivante.

Le modèle en cascade nécessite la définition d’un planning détaillé qui énonce toutes les étapes et réalisations attendues. Différentes activités d’analyse, de conception, d’implantation, de tests et d’intégration sont effectuées afin de converger vers l’obtention du système logiciel final.



Initialement, le modèle en cascade est un cycle de développement purement séquentiel, cependant, diverses possibilités d’itération ou de retour vers les phases amont ont ensuite été intégrées au modèle. Ces itérations permettent de vérifier les produits obtenus au fil du développement et ainsi fournir plus de souplesse à la conception.

Cycle en V

Le cycle en V est l’un des cycles les plus connus et utilisés (figure 2.10). C’est un cycle de type prédictif qui a été défini pour remédier aux lacunes du cycle en cascade qui manque de réactivité face aux erreurs découvertes lors de la conception, du développement ou encore de l’analyse. La structure en V du cycle a l’avantage de mettre en vis à vis les activités de développement et de tests permettant de mieux préciser les documents à
partager entre ces phases, notamment les rapports de tests et les modifications qu’il est nécessaire d’apporter pour corriger les erreurs. Ainsi, lors de la phase montante du cycle, toutes les réalisations doivent être testées et validées.


Depuis les années 80, le cycle en V est considéré comme un standard du développement logiciel et de la gestion de projet dans les industries. A la suite du cycle en V sont apparues diverses variantes telles que, par exemple, le cycle en W qui propose d’effectuer deux cycles en V successivement, le premier servant à la conception d’un prototype de l’application, le second à construire l’application finale.

Cycle en Y


Dans son principe, le cycle de développement en Y, est proche du cycle en cascade dont il reprend l’aspect descendant. Son intérêt est de séparer les préoccupations concernant les aspects fonctionnels liés au domaine métier et les aspects techniques liés aux solutions technologiques à employer pour la mise en oeuvre.

Avec le MDA, un cycle en Y orienté modèle a été proposé afin de séparer les spécifications fonctionnelles (PIM) et les spécifications techniques (PSM). Cette approche a pour avantage de fournir un modèle plus rationnel de la gestion des modèles et de l’utilisation des transformations de modèles employées lors de la phase de conception pour faire coïncider les modèles techniques et fonctionnels (employés également lors de la phase d’implantation sous la forme de génération de code).

Cycle en Spirale

Défini par Barry Boehm, le cycle en spirale est une approche itérative du cycle de développement en V. Ainsi, il en reprend l’essentiel des concepts en s’articulant autour de quatre phases importantes (figure 2.12) : la détermination des objectifs, la détermination des risques, le développement et les tests et enfin la planification de l’itération suivante.




Par contre, à l’inverse du cycle en V, le modèle en spirale met un focus plus important sur l’analyse et la résolution des risques. Ceci est nécessaire car au fur et à mesure des itérations, la réalisation devient de plus en plus conséquente. Il est donc important d’évaluer correctement le risque à chaque itération sachant que toute erreur sera d’autant plus difficile à corriger que le développement sera avancé.

Pre-agilité

Cycle avec Prototypage Rapide (RAD)



Proposé dés la fin des années 1980, le cycle de développement avec Prototypage Rapide (Rapid Application Development aussi appelé semi-itératif) se situe entre une approche prédictive et une méthode agile dans le sens où il s’agit de l’une des premières approches à introduire la notion d’itération au sein du processus de développement. La méthode RAD se structure ainsi autour de cinq phases :
1. L’initialisation pendant laquelle le périmètre du projet et les ressources nécessaires à celui-ci sont définis. Le travail à effectuer est alors organisé par thèmes.
2. Le cadrage qui va définir les besoins et les fonctionnalités du produit. Cette phase est effectuée lors de réunions se basant sur des techniques d’animation spécifiques.
3. La conception des modèles nécessaires à l’élaboration du système logiciel proprement dit. Le client est fortement impliqué dans cette phase puisqu’il a pour rôle de valider les modèles proposés.
4. La construction du système logiciel par l’équipe de développement par une approche itérative selon les fonctionnalités demandées. Le client est toujours présent afin de valider les différentes réalisations.
5. La finalisation est une phase de validation globale du livrable final par le client.

Ainsi, les deux premières phases se placent dans une approche descendante comme celle en V ou en Cascade. Par contre, à partir de la troisième phase, le cycle de développement devient itératif en permettant d’alterner conception et validation. De plus, avec l’intégration du client dans le développement, cette démarche fournit plus de réactivité.

La méthode RAD est pionnière dans l’utilisation de l’itération et d’une intégration plus importante du client dans le processus de développement. A ce titre, elle peut être considérée comme initiatrice des méthodes agiles qui sont fondamentalement tournées vers ces concepts. Les paragraphes suivants présentent les démarches et cycles proposant une approche agile du développement.

Unified Process UP

Tout comme RAD, UP est un cycle de développement qui se positionne entre les approches prédictives et les approches agiles. Ce cycle de vie est né de l’approche orientée objet issue de la collaboration de Ivar Jacobson, Grady Booch et James Rumbaugh. L’approche UP tente de rationaliser les processus de développement logiciel en fournissant un guide de bonne pratique fondé sur six points :

1. Avoir une démarche incrémentale et itérative pilotée par les risques et les cas d’utilisation.
2. Avoir une gestion rigoureuse des exigences.
3. Centrer le développement sur l’architecture.
4. Faire une modélisation graphique des exigences.
5. Contrôler en permanence la qualité.
6. Contrôler les changements éventuels à effectuer.
Ces six bonnes pratiques prônées par UP sont en l’occurrence ce qui permet de rattacher ce cycle de développement aux méthodes agiles. En effet, contrairement aux démarches de développement classiques, UP oriente naturellement le développement pour que celui-ci soit à même de répondre aux changements.
UP définit une démarche de développement intégrant les neuf disciplines majeures nécessaires au développement : la modélisation métier, la définition des exigences, l’analyse et la conception, l’implantation, les tests, le déploiement, la gestion des changements, la gestion du projet et enfin la prise en compte de l’environnement. Basé sur ces disciplines qui seront employées à chaque itération, le processus de développement va alors pouvoir suivre les quatre phases du processus qui consistent en :
1. Le début dont l’objectif est d’unifier les points de vue de chacune des disciplines sur l’ensemble du projet.
2. L’élaboration qui a pour objectif de définir et de valider l’ensemble des modèles permettant la conception du système logiciel.
3. La construction qui doit fournir une version documentée et fonctionnelle du logiciel.
4. La transition dont le but est de finaliser le système.

Avec Unified Software Process Metamodel (USPM), les démarches de développement se sont orientées vers la modélisation des processus en suivant le credo issu de la publication de Lee Osterweil : Software processes are software too. Traduit littéralement que les processus de développement de logiciel sont aussi une forme de logiciel. Cette publication montre la nécessité de maîtriser le processus de développement en modélisant sa structure et son évolution.

L'agilité

L’extreme programming

L’extreme programming est à proprement parler une approche agile qui propose des itérations courtes impliquant au maximum le client et cherche à recentrer le développement sur la composante humaine en revalorisant les bonnes pratiques de développement telles que le binomage, la définition au plus court de tests fonctionnels permettant de valider l'application, la promotion de styles ou de pattern d'écriture de code.
XP fonctionne autour de 5 valeurs fondamentales souvents reprise dans les approches agiles plus récentes:

  • Communication
  • Feedback
  • Simplicite
  • Courage
  • Respect

Scrum

Développée en 1993, Scrum est une approche agile qui met en avant l’intérêt des petites équipes de développement. Dans ces petites équipes, sont avant tout recherchées les compétences multidisciplinaires et la capacité d’intégration sociale des acteurs. Dans Scrum, les itérations appelées Sprint sont planifiées sur quatre semaines maximum. Ces itérations sont axées sur les besoins définis par le client qui constituent alors le référentiel de travail.
Les besoins sont hiérarchisés par degré d’importance et développés selon les priorités définies par le client. Chaque jour constitue une itération pendant laquelle une réunion est organisée pour établir l’état d’avancement du projet et de vérifier que les fonctionnalités et les délais sont bien respectés.



A la fin de chaque Sprint, une réunion établissant le bilan des réalisations est menée afin d’établir l’efficacité de l’équipe et les éventuelles améliorations qui doivent être apportées. La finalité d’un Sprint est de présenter un démonstrateur au client afin que celui-ci puisse valider les réalisations. Scrum définit un certain nombre d’acteurs qui vont intervenir lors de la mise en oeuvre du processus :
1. Le ScrumMaster a pour rôle d’aider les acteurs du développement à communiquer au sein de l’équipe ainsi qu’avec le client. Il doit s’assurer que la philosophie et les pratiques de Scrum sont correctement suivies. Par contre son rôle n’est pas à confondre avec celui du chef de projet dont il est plutôt un conseillé.
2. Le Client ou Product Owner est lui aussi acteur du développement, il a pour rôle de définir les besoins. Il doit également définir les priorités dans les fonctionnalités à réaliser. Ainsi, il participe activement à l’élaboration du produit en suivant les étapes de sa réalisation afin de pouvoir en valider la finalité.
3. Enfin, l’Équipe qui est constituée de l’ensemble des corps de métiers nécessaires à l’élaboration du produit. Ces métiers sont classiquement ceux rencontrés lors des développements logiciels classiques (Développeur, Analyste, Testeur, etc.)

Pour finir, la méthode Scrum s’appuie sur la notion de Visibilité pour qualifier et quantifier les résultats de l’équipe. Des critères de validation doivent exister afin de définir si une fonctionnalité a été complètement réalisée ou non. Des critères d’Inspection doivent être définis afin de déterminer l’existence d’écarts entre la réalisation concrète et l’objectif final. Enfin, la notion d’Adaptation permet, lors d’écarts trop importants détectés pendant des Inspections, de modifier la gestion interne de l’équipe afin d’éviter que ces écarts ne s’amplifient. Ces critères permettront alors de gérer de la dette techniques ou encore d'évaluer la vélocité de l'équipe de développement afin de planifier au mieux les contenus des livraisons futurs

On peut noter que Scrum et XP sont deux approches très proches (on note d’ailleur une forte proximité des valeurs vehiculés) qui cherchent l’une comme l’autre a remettre la vie du développeur au centre du processus. Cependant Scrum a une volonté plus marqué de fournir un processus formellement établi pour gérer le cycle de vie du logiciel alors que XP s'intéresse plus sur les bonnes pratiques. Généralement les equipes de développement pratiquant l’une pratique préférablement la seconde.

Lean

Le lean est une approche de gestion de production développé par Toyota dans les années 90. Avec un héritage assumé issu du Taylorisme, le lean se définit dans une recherche d'accroissement de la productivité, de la qualité et d'une réduction systématique du gaspillage.

Dans les approches agiles, si XP a pour propos de mettre en avant des valeurs humaines et si Scrum a pour objet de recentrer le processus autour de la production des éléments a plus haute valeur, le Lean complète ces approches en visant l’optimisation des processus eux même.

Pour cela, le lean va se focaliser sur 7 règles qui servent d’axes de progressions (qui sont probablement des questions systématiques aux rétrospectives de sprints):

  1. comment reduire les dechets? (temps perdus, réduction de dette technique, etc…)
  2. comment améliorer la monté en compétences?
  3. decider au plus tard
  4. livrer au plus tot
  5. valoriser l’equipe
  6. la qualité commence des la conception
  7. avoir toujours une vision du logiciel dans sa globalité (maintenir le recul)

Conclusion

Les processus de développement sont nombreux et si historiquement l'approche en V a été adoptée majoritairement, les nouvelles approches comme les approches agiles tendent a s'imposer comme étant des solutions plus dynamique et adaptées aux changements actuel. Je reviendrais plus dans le détail des approches telles que Scrum et Lean qui mérite au vue de leur présence actuel d'être approfondie. De la même manière, ces dernières années, au delà des processus de développement, on a pu voir émerger le DevOps dont le but est de regarder au delà des équipes de développement en prenant en considération l'ensemble des besoins des acteurs agissant de près ou de loin dans la livraison du produit au client. Il me semble que même si cela déborde du cadre des processus de développement de l'équipe logicielle, celle ci doit prendre en compte ces nouvelles préoccupations et cela a forcément un impact sur leur activité

jeudi 21 décembre 2017

Ingénierie Dirigée par les Modèles

L'ingénierie dirigée par les modèles (IDM) [13], [16] et [17]  est un cadre méthodologique permettant d'unifier différents domaines. Elle permet cette unification grâce à l'utilisation importante de modèles (potentiellement exprimables suivant différents domaines) et des transformations automatiques entre ces modèles. L’IDM permet le développement plus souple et plus simple de programmes informatiques dans des contextes comme les IHM  ou les systèmes temps réels distribués.

Système d’étude

L’IDM définit la notion de système [13] comme étant l’entité étudiée dans le cadre d’un processus de modélisation. Un système est vu comme étant un ensemble d’entités en interactions décomposable en sous-systèmes. Cette décomposition amène à une relation de composition entre systèmes et sous-systèmes. Dans [13], comme illustré par la figure 48, trois types principaux de systèmes sont distingués permettant une première classification : les systèmes physiques, les systèmes numériques et les systèmes abstraits. Un système physique représente une entité physique concrète et observable sur lequel l’homme peut d’agir matériellement. Un système abstrait est une entité purement conceptuelle comme un objet mathématique (fonction, ensemble, etc.). Un système numérique est un système appartenant à la classe des objets informatiques. Cette liste n'est pas exhaustive mais elle a le mérite de mettre en avant les limites de la modélisation: le monde physique et le monde conceptuel.


Modèle

Un modèle est l’abstraction d'un système réalisé dans une intention et un contexte particulier. Un modèle doit pouvoir être utilisé pour répondre à des questions sur le système. Un modèle peut décrire ou spécifier un système. Dans le premier cas, le modèle doit respecter le système, dans le second cas, c'est le système qui doit respecter le modèle. La relation existante entre le modèle et le système est définie dans les termes de "est le modèle de" ou "est représenté par" comme illustré par la figure 49. Comme le système, le modèle est composé d'éléments qui sont les abstractions des sous-systèmes donc également des modèles.




Méta-modèle

L'IDM définit le contexte de réalisation de modèles par un meta-modèle. Le meta-modèle est le modèle d'un langage de modélisation qui est l'ensemble des modèles réalisables comportant des caractéristiques communes. Le meta-modèle a un rôle important dans la modélisation car il définit les règles de construction de modèles pour le domaine qu'il définit. Un modèle est alors dit conforme à un meta-modèle s'il appartient à l'ensemble des modèles modélisé par le meta-modèle. Cette relation de conformité est illustrée par la figure 50.



Le système, le modèle, le langage de modélisation et le méta-modèle peuvent être réunis au sein d'un même diagramme en faisant apparaître les relations de conformité, de modélisation ainsi que d'appartenance à un langage de modélisation (figure 51). Ce diagramme porte le nom de pattern "Step" dans [13].





Langage spécifique de domaine

Apres les notions de bases de système, de modèle et de meta-modèle, l'IDM offre une définition de la notion de Langage Spécifique de Domaine (DSL). Un DSL est un langage qui capture les aspects spécifiques à un domaine comme le ferait un meta-modèle. Un DSL intègre cependant plus que cela car il intègre la notion de sémantique.

Transformation de modèles

Une transformation de modèles définie par IDM est la modification d'un modèle suivant des règles définies au niveau de son méta-modèle. Les transformations de modèles sont de deux types, les transformations de modèles endogènes et les transformations de modèles exogènes.

 Les transformations de modèles endogènes sont des transformations sans modification du meta-modèle donc au sein d'un même langage de modélisation. Ces transformations sont généralement dues à l'évolution du modèle dans une exécution.

 Les transformations exogènes permettent le changement de meta-modèle auquel le modèle est conforme afin de passer d'un langage de modélisation à un autre. Ce changement de langage de modélisation permet de bénéficier des avantages de chaque langage ou d'automatiser un processus de développement, ce processus se décomposant en diverses étapes qui peuvent être: une étape de modélisation, une étape de vérification puis une étape de ciblage vers une plateforme spécifique. Le passage d'une étape à une autre se réalisant par transformation de modèles.

 Pour la réalisation des transformations de modèles, l'IDM propose un modèle de transformations, illustré par la figure 52, liant les différents éléments du méta-modèles de façon à établir des règles de correspondances. Ces règles, appliquées au modèle à transformer, vont permettre la réalisation d'un nouveau modèle conforme au meta-modèle ciblé.



Exemple:
Avec l'illustration de la figure 53, considérons un fichier XML de base de données contenant l'identité de Thomas ainsi que des informations confidentielles telles que son adresse. Pour l'affichage des informations non confidentielles en HTML, vient tout de suite à l'esprit XSLT afin de générer de l'HTML automatiquement. Dans le cadre IDM ceci est purement une transformation de modèle par filtrage des informations et par la réalisation d'une mise en page.



Conclusions

L'IDM offre un cadre unifié pour la réalisation et la manipulation de modèles grâce aux notions de meta-modèle, de langage de modélisation, et de relations de :
•    Modélisation entre le système et son modèle ainsi qu'entre le langage de modélisation et le meta-modèle.
•    Conformité entre le modèle et son meta-modèle.

 La notion de transformation de modèles donne la possibilité d'intégrer diverses technologies possédant leur propre langage de modélisation dans le but de réaliser des systèmes complexes et fiables par génération automatique de code, par vérification dans des domaines adaptés à cette tâche etc. L'IDM offre le cadre nécessaire pour la mise en place d'un processus visant le développement d'un système logiciel par transformations de modèles. La dernière phase de ce processus est le ciblage vers une plateforme d'exécution permettant de finaliser la réalisation du système logiciel. La définition d'une plateforme d'exécution doit donc être définie.

 References:


[13] J-M. Favre. J. Estublier, M. Blay-Fornarino; L'ingénierie dirigée par les modèles, 2006, Edition Hermes, Lavoisier, Paris.
[16] A. Rasse, J-M. Perronne, B. Thirion. Ingénierie dirigée par les modèles pour une conception fiable des logiciels de commande, 2005 IDM05, p 231-244
[17] A. Rasse, Approche orientée modèles pour la spécification, la vérification, l'implantation des systèmes logiciels critiques, à paraître (2006), Mémoire de thèse, Université de Haute alsace, Laboratoire MIPS.

vendredi 15 décembre 2017

Nous sommes les ancêtres des générations futurs

J'ai entendu cette phrase a la télévision, et pour une fois que la télévision me fait réfléchir, je me suis arrêter dessus. Alors réfléchir en quel sens?

Et bien, jusqu’à maintenant j'ai toujours penser qu'il existait deux types d'individus, ceux dont le nom restera marqué dans l'histoire et ceux qui ne resteront que des inconnus. Cette façon de voir les choses amène a penser que la responsabilité historique repose en fait sur ceux dont les noms seront rappeler à la mémoire des gens par les livres d'histoire. Ainsi on se souviendra des certains chercheurs (de Marie Curie a Mengele) ou de politiciens dirigeants (de Kennedy a Mao) et on fait très souvent l'amalgame de leur contribution avec l’état actuel de la société, permettant ainsi a tout a chacun de se dédouaner d'une quelconque responsabilité.

Pourtant, lorsque l'on regarde plus attentivement l'histoire ou si l'on écoute plus attentivement les historiens, il est intéressant de voir que l'implication des foules dans les redirections politiques sont beaucoup plus fréquentes que l'on peut le penser car même si les foules sont souvent l'outils de ces mêmes personnalités qui resteront dans l'histoire, elles agissent aussi par elles-même lorsqu'il s'agit d'opprimer, se révolter, se venger ou parfois heureusement soigner, soutenir, éduquer.

Ainsi, de la même manière, si nous nous projetons dans l'avenir, nous ne considérons pas vraiment comment nous agissons dessus. On imagine globalement comment le monde sera mais pas comment nous auront participé à le transformer. Et comme nous considérons nos personnages illustres comme responsable de notre passé, sans eux dans notre perspective du futur, celui-ci n'est que la résultant de plein de choses que l'on ne comprend pas mais qui ne relève clairement pas de notre si petit impact et pour beaucoup, cela nous arrange bien.

On se rend bien compte que notre manière de voir notre histoire et l'impact que nous avons dessus n'est pas la bonne mais prendre conscience de cela ne nous donne pas la clef du changement de perspective. Et c'est la qu'intervient cette phrase:  "Nous sommes les ancêtres des générations futurs". elle permet de regarder l'histoire selon une autre perspectives en nous remettant nous simples citoyens comme acteurs principales de notre histoire. Elle élimine de l’équation les personnages illustres et nous force donc a rejeter la simplicité de leur remettre les clefs l'histoire en acceptant sans broncher les directions qu'ils nous imposeront.

Ainsi, en fait, lorsque l'on se considère comme les ancêtres des générations futurs, nous faisons la démarche de nous séparer de l'anonymat que nous impose l'histoire lorsqu'elle passe. Nous nous considérons acteur et partie prenante de l'avenir. Nous pouvons alors nous demander comment nous regarderons ces gens, lorsque de la même manière que nous, ils regarderont l'histoire, la notre, celle d'aujourd'hui, comme nous, nous avons regardé nos ancêtres, eux acteurs anonymes de leur propre époque.

Enfin n'oublions pas qu'en réalité l'anonymat n'existe pas, même si certains sont sous les projecteurs, pendant un temps, chacun d'entre nous aura son nom associé a son époque et pourra être critiqué de son inaction a tenter de céder un monde meilleur, comme nous pouvons l’être avec nos propres ancêtres et leur pratiques que l'on peut juger archaïque.

Ainsi soyez les ancêtres des générations futurs car c'est cette seule posture qui nous permettra de rester, même anonymement, fier et responsable de ce que nous léguerons a nos enfants, de pouvoir supporter le regard de ces gens qui lorsqu'ils voudront comprendre pourquoi leur monde et tel qu'il est, devront choisir entre colère et révolte ou respect et reconnaissance.

jeudi 14 décembre 2017

Supervisory Control Theory

Introduction

Supervisory Control Theory ou théorie de la supervision des systèmes à évènements discrets introduit par P.J.Ramadge et W.M.Wonham [1] se base sur la théorie des langages et des automates [10]. Elle définit l’utilisation de trois entités : le SED, une spécification souhaitée et un superviseur. Cette théorie définit la possibilité de synthétiser un modèle de superviseur dit valide à partir du modèle du SED et de la spécification. Le premier objectif de cette démarche est de fiabiliser un système susceptible d’avoir un comportement qui peut être gênant ou dangereux. Le deuxième objectif est la possibilité pour un système dit ouvert, dont les comportements possibles sont multiples, de réaliser différents superviseurs dont les rôles seront de contraindre le système dans un comportement donné pour un contexte donné.

Principe de la théorie de la supervision

La théorie  de la supervision définit que ces trois entités, le SED, la spécification souhaitée et le superviseur sont modélisés par leurs langages conformément à la théorie des langages et des automates. Ceci permet de bénéficier des opérations liées aux langages et aux automates à états finis puisque les langages utilisés sont des langages réguliers. Dans l’ensemble de ce chapitre, ces entités sont considérées comme des automates notés G pour le système, K pour la spécification et S pour le superviseur de langage respectif L(G), L(K) et L(S).


Idéalement, le superviseur, une fois réalisé, est composé avec le SED pour former le système supervisé. A chaque changement d’état du système, le superviseur va suivre l’évolution du système et lui notifier l’ensemble des évènements qu’il est autorisé à générer (figure 35). Cependant, deux situations prises en compte par la théorie peuvent survenir. La première est que certains évènements, par nature, ne peuvent pas être interdits. La seconde situation est que certaines transitions du système ne peuvent être vues par le superviseur, l’empêchant de fournir un ensemble d’évènements autorisés cohérent. Ces deux situations sont définies dans la théorie de la supervision sous les notions de commandabilité et d’observabilité. Ainsi, un alphabet  est divisé en plusieurs ensembles notés c pour l'alphabet des évènements commandables, uc l'alphabet des évènements non commandable, o l'alphabet des évènements observables et uo l'alphabet des évènements non observables tel que

ce qui signifie qu'un évènement peut être à la fois non commandable et non observable, commandable et non observable, observable mais non commandable ou enfin commandable et observable. Ces notions de commandabilité et d'observabilité sont très importantes car elles vont conditionner les limites du superviseur et sa réalisation. De nombreux travaux approfondissent ces notions dans [1], [3], [5], [6].
Pour la réalisation du système supervisé, la théorie de la supervision définit que le modèle du superviseur, donc le langage L(S), peut être concrétisé par une fonction ou une table d'associations qui à une séquence d'évènements donnée renvoie une liste d'évènements autorisés. Une autre approche, illustrée par la figure 36, utilise l’intersection (ou le produit strict pour les automates) du langage du système et celui du superviseur afin d’obtenir le langage du système supervisé. Ainsi, le modèle du système supervisé est obtenu par:





La théorie de la supervision définit enfin la notion de superviseur bloquant par L(S/G)=Lmpréf(S/G).

Définition d'une spécification

La définition de la spécification est l'opération la plus difficile pour la théorie de la supervision car celle-ci doit répondre à différents critères afin d'être utilisable pour la génération du superviseur [1], [9]. Le but de la spécification est de définir le comportement du système bouclé, ainsi, si K est un automate décrivant la spécification valide, il faut avoir L(K)=L(S/G), comme illustré par la figure 37.




Pour cela, une méthode consiste à définir une première spécification par un automate E en considérant le comportement global voulu en s'intéressant à tous les évènements présents dans le système. Il est possible de réaliser l'opération de produit synchronisé de façon à obtenir L(K) qui sera égal à l'intersection de L(E) et de L(G), comme illustré par la figure 38.




Une autre méthode permet de définir le comportement voulu en ne considérant que certains évènements. Cependant, la spécification E doit être augmentée afin de correspondre au système. Ainsi, l'opération de produit synchronisé permet d'obtenir cette spécification (illustré par la figure 39). Cette méthode a pour avantage d’être simple mais elle implique une attention particulière aux évènements non utilisés pour la définition de E à cause du produit synchronisé qui va augmenter son langage.





L’opération de produit synchronisé est alors utilisée dans les deux cas tels que : K=G||sE car dans la première approche cela amène à faire un produit strict puisque E et G ont le même alphabet, dans la deuxième approche, cela va permettre l'augmentation du langage de E sur la considération du comportement intrinsèque de G. Enfin, il est nécessaire de valider la spécification K obtenue pour le système en vérifiant que celle-ci est non bloquante.

Une autre approche est de définir un automate qui invalide une séquence donnée. Ainsi, un automate est réalisé pour modéliser cette séquence dont tous les états sont marqués sauf le dernier qui représente la survenue de l'évènement qui réalise la séquence comme illustré par la figure 40. Ceci permet de réaliser des spécifications ciblées pour certains cas précis.





Il faut retenir que la théorie de la supervision ne fait pas état de méthode générique pour la définition de spécification. Chose qui n'est d'ailleurs pas son objectif puisque son but n'est que la synthèse d'un superviseur par la validation de la spécification K souhaitée sur le principe du blocage et de l'inclusion dans le langage de SED G. La réalisation d'une spécification reste donc un problème dans la démarche de synthèse de superviseur.

Synthèse du superviseur

La spécification étant définie, la synthèse du superviseur selon [1], [10] s’effectue par le produit du système G et de la spécification K suivi de l’opération Trim. Ceci est la base de la démarche pour la synthèse du superviseur mais elle ne prend pas en compte les aspects liés à la commandabilité et à l’observabilité des évènements. Cette opération de base s’explique par la relation

qui existe entre le superviseur, la spécification et le système, comme ré-illustré par la figure 41. Cette relation signifie que la spécification est l’objectif du système supervisé par l’égalité L(S/G)=L(K). Elle signifie également que le  langage du superviseur ne se limite pas nécessairement au langage de la spécification.




Commandabilité et Observabilité dans la synthèse du superviseur

Les notions de commandabilité et d’observabilité du superviseur pour le système sont liées aux événements commandables et observables. La nature de ces événements amène des particularités dans la relation entre le système et le superviseur lors de la supervision. Les événements non commandables ne peuvent pas être interdits par le superviseur et le système sera toujours susceptible de les réaliser. Les événements non observables ne permettent pas au superviseur de suivre l’évolution du système de manière cohérente. Le superviseur est alors susceptible après la survenue d’un évènement non observable de fournir une commande erronée.

Problèmes liés à la commandabilité

Comme il a été dit précédemment, les évènements non commandables ne peuvent pas être interdit pas le superviseur. Cette particularité, si elle n’est pas prise en compte lors de la synthèse amène à la réalisation d’un superviseur qui composé avec le système sera susceptible de violer la spécification comme illustré par la figure 42.



Pour prendre en compte cette particularité, la spécification est alors l’élément sur lequel vont intervenir les éventuelles corrections pour que la synthèse donne un superviseur commandable. La théorie de la supervision définit alors une spécification comme étant commandable si


Si la spécification n’est pas commandable, alors la théorie de la supervision définit qu'il existe un langage suprême commandable L(K') inclus dans L(K) qui est commandable (illustré par la figure 43). Ce langage est obtenu à l’aide de l’algorithme de Kumar [5]. Cet algorithme identifie dans l’automate K les états à partir desquels, dans le système, des évènements non commandables sont susceptibles d’être générés.



Problémes liés à l’observabilité

La notion d’observabilité caractérise les évènements de l’alphabet selon deux types, les évènements observables et les évènements non observables. Lors de la supervision, à chaque changement d’état du système, le superviseur, par la lecture de l’évènement qui vient d’être réalisé, est mis à jour afin de produire un nouvel ensemble d’évènements autorisés. Lors de la survenue d’un évènement non observable, le superviseur n’est pas notifié du changement d’état du système et n’est pas capable de fournir un ensemble d’évènements autorisés cohérent. Pour cela, la théorie de la supervision impose que la commande souhaitée pour le système soit la même avant et après un évènement non observable sinon le superviseur synthétisé sera non observable et la spécification risque alors d’être violée comme l’illustre les figures 44 et 45.

Exemple:
En considérant "c" comme étant non observable, si l'état 4 est interdit dans le système G alors il y a un problème d'observabilité dans la spécification K qui définit une commande différente avant et après l’évènement non observable. Un superviseur ne pourra donc pas savoir s'il se trouve dans l'état 1 ou l'état 3.








La théorie de la supervision caractérise alors la spécification K comme étant observable si elle permet la synthèse d’un superviseur observable. Si K n’est pas observable alors, contrairement à la notion de commandabilité, il n’existe pas de langage suprême observable qui puisse être calculé. Dans pareil cas, il est nécessaire de se rattacher à la notion de normalité.

Normalité et observabilité

La normalité, c’est l’invariance d’un langage par rapport à un autre suivant un alphabet donné. La normalité permet de vérifier qu’un langage prend en compte tous les évènements contenus dans un alphabet pour un autre langage. Dans le cadre de la théorie de la supervision, la normalité est rapprochée de l’observabilité en définissant l’alphabet intéressant comme étant celui des évènements non observables. Ainsi, la spécification K est définie comme normale pour le système G et pour les évènements non observable si :

La notion de normalité décrite dans [1] et [11] est très pratique car elle permet d'assimiler la notion d'observabilité. En fait, si un langage est normal alors il est observable et de plus il est possible de la même manière que pour la commandabilité de construire un langage suprême normal (cf. algorithme de Kumar [5]) si K n'est pas normal. A cela, il faut tout de même observer quelques restrictions, c'est à dire qu'il faut considérer les évènements non observables comme étant non commadables et ainsi il y a équivalence entre observabilité et normalité.

Supervision modulaire

La supervision modulaire, illustrée à la figure 46 et définie dans [1], [6], [11], [12] a pour intérêt de diviser le problème de la définition de la spécification en plusieurs modules. Pour un système G, n spécifications K seront définies qui permettront la génération de n superviseurs. Ceci permet de limiter la taille et la complexité de la spécification globale si plusieurs objectifs de commandes sont à réaliser. L'intersection des n superviseurs donnera alors le superviseur global. Les spécifications ne doivent pas être en conflit sinon le superviseur sera bloquant. Ainsi, si pour K1 et K2, deux spécifications, l'égalité

 
est respectée alors elles ne sont pas en conflits. Si K1 et K2 sont commandables alors leur intersection l'est aussi sinon leur langage suprême commandable l'est. Pour l'observabilité, il faut utiliser la notion de normalité afin d'obtenir un langage normal pour que le superviseur soit observable.


Supervision décentralisée

La supervision décentralisée [1], [11], [12], illustrée à la figure 47, propose de voir le système sous plusieurs points de vues locaux (en utilisant la projection) et de définir pour chaque point de vue une spécification restreinte afin de générer un superviseur local. Chaque superviseur aura la responsabilité de la gestion d'un sous-ensemble de l'alphabet du système, ces différents sous-ensembles de l’alphabet ne devant pas avoir d’intersection non vide sans un risque de conflit entre les différents superviseurs. Pour le superviseur généré en local, la supervision du système G revient à considérer les évènements supprimés par la projection comme non observables. Il ne va donc s'intéresser qu'à l'aspect du système pour lequel il a été conçu.





La conjonction des différents superviseurs va être réalisée par l'intersection des différents superviseurs en ayant réalisée une projection inverse sur l'ensemble de l'alphabet afin de préserver leurs comportements respectifs. Il faut cependant rester prudent car, si par l'utilisation de la supervision décentralisée il est possible de simplifier localement le problème en plusieurs sous système, la supervision ne prendra pas en compte les interactions possibles entre ces sous systèmes et ces dernières ne pourront pas être supervisées.

Conclusions

La théorie de la supervision donne un cadre théorique idéal pour la modélisation et la commande de systèmes à évènements discrets par la génération d'un superviseur valide en prenant en compte de nombreux aspects susceptibles de poser des problèmes tels que ceux liés aux événements non commandables ou non observables. Ceci reste un cadre théorique qui ne prend pas en compte les problèmes liés à l'implantation d'un superviseur dans un environnement d’exécution. Cet environnement n’est pas défini dans le cadre théorique de la supervision mais importe pourtant dans la réalisation de modèles de SED cohérents et dans la manière dont le ciblage sera effectué. Pour cela, l'ingénierie dirigée par les modèles propose une approche pour la définition et la transformation de modèles et établit alors comment réaliser et cibler un système supervisé dans un environnement d'exécution spécifique.

Références


[1] Ramadge P.J., Wonham W.M. The control of discrete-event systems. IEEE Transactions on Automatic Control, 1989, Vol. 77, N° 1, p. 81-98.

[3] V. K. Garg, R. Kumar, S. I. Marcus. On controllability and Normality of discrete event dynamical systems. Systems and control letters, 1991, Vol. 13, N°3, p. 157-168.

[5] R. Kumar, M. A. Shayman. Formulae relating controllability, observability and Co-observability. Automatica, 1998, Vol. 34, p. 211-215.

[6] H. Flordal. Modular controllability verification and synthesis of discrete event systems, Mémoire de these, Chalmers University of Technology, 2001.

[9] A. Overkamp, and J. H. van Schuppen. Control of discrete event systems. Amsterdam (NL), Stichting Mathematisch Centrum, 1994 p. 453-467.

[10] C. G. Cassandras, and S. Lafortune. Introduction to discrete event systems, Kluwer Academic Publishers, 1999, ISBN: 0-7923-8609-4.

[11] M. H. Lamouchi. Synthèse de superviseur pour des systèmes à évènements discrets partiellement observés,  Mémoire de thèse, Université de Montréal, département de génie électrique et de génie informatique de l'école polytechnique de Montréal, 2002.

[12] B. Gaudin. Synthèse de contrôleurs sur des systèmes à évènements discrets structurés. Mémoire de thèse, Université de Rennes, Institut de Formation Supérieure en Informatique et Communication, 2004.

dimanche 10 décembre 2017

Maven : Introduction

Qu'est ce que Maven ? Je vais vous en faire un résumé rapide mais pour ceux qui veulent une bible et de details, consulter ce livre.

Généralités

Maven est un gestionnaire de build ou constructeur de projet. Il est open source et soutenu par la fondation Apache. Maven a pour but de simplifier, rationaliser et automatiser la construction d'un projet sur l’ensemble de ses phases et activités de façon a garantir la qualité de no build.

Initialement orienté pour les projet Java, Maven est maintenant capable de construire des projets de tout type de nature, c++, Python, etc....

Ainsi, et c'est sa fonction première, Maven va permettre de compiler le code de notre application, ceci en fournissant des moyens de gestion simple pour les dépendances du projet. Cependant, s’arrêter a cela, serait hyper réducteur car Maven a plus la vocation de couvrir tout le périmètre de build.

En fait avec Maven, il est possible de:
  • préparer la compilation (en générant du code par exemple) 
  • effectuer la compilation
  • exécuter des tests unitaire, 
  • faire de l'analyse de code,
  • faire du packaging (construction de jar, war, tar.gz ou même des deb) 
  • exécuter des procédures d'installation sur des plateformes spécifiques de tests, exécuter des tests fonctionnels (avec roboframework par exemple)
  • préparer un livrable
  • générer differentes doc (technique ou utilisateur)
  • etc... car il est possible d'adjoindre des plugins supplémentaires pour compléter son fonctionnement.
Tout ceci concerne les activités directement lié au build de notre projet mais avec maven, il sera aussi possible d'aller plus loin en permettant la constitution de processus plus générique autour de la gestion du projet comme :
  • la construction automatique de template de projet
  • la gestion de multi-projet, de leurs dépendances et de leur orchestration dans un même process
  • la gestion d'un cache local de vos dépendances
  • la gestion des builds passés sous la forme de SNAPSHOT et de RELEASE
  • du deployement de documentation web en ligne

Configuration

Maven s'articule autour d'un runner que l'on telecharge ici. Je ne vais pas rentrer dans le details de l'installation de Mave, mais celle-ci se résume globalement a spécifier convenablement JAVA_HOME qui exécutera Maven. (Attention, ce dernier n'est pas forcement celui employé pour la compilation). On pourra specifier ce JAVA_HOME directement lors de l'appele de Maven en faisant un alias par exemple sous unix/cygwin.

Il est ensuite nécessaire de configurer ce que l'on appelle les Settings. Ce setting est constitué de deux fichiers, le fichier système présent dans le répertoire conf de Maven et un fichier utilisateur présent dans le répertoire .m2 de l'utilisateur courant.

Comme on peut se le douter, le setting système permet de configurer Maven pour toutes ses utilisations alors que celui de l'utilisateur sera spécifique au compte utilisateur lançant le processus Maven. (la commande mvn, que nous verrons plus loin)

L'ordre de chargement de ces settings se réalisera toujours dans le sens Systeme puis Utilisateur, le dernier chargé faisant fois de sa configuration en cas de conflits. A noter qu'il est possible de spécifier un setting lors du build afin de personnaliser celui-ci avec l'option -s

Le settings est le fichier de configuration dans lequel seront définis les variables d’environnement locales (comme les differentes versions Java installées sur la machine),  les repositories de dépendances (artifactory ou nexus, SNAPSHOT ou RELEASE), les serveur web, des serveurs de base de données, des server de vérification de code (Sonar par exemple) , des secrets éventuels pour s'y connecter, etc.... en fait toute configuration et ressource spécifique a l'environnement de build, utilisable non directement par les projets.

Par convention (unix) on build dans un compte spécifique (maven par exemple) et on initialise ces données dans le settings utilisateur, le settings système étant réservé aux configurations partagées.

Par exemple un settings spécifiant les variables pour la compilation en java 6, 7 ou 8, les variables pourront alors être utiliser dans les pom.xml des projets (nous verrons par la suite ce que sont les pom):


<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <localRepository>/home/m2Repo</localRepository>
  <profiles>
    <profile>
      <id>compiler</id>
        <properties>
          <JAVA_1_6_HOME>jdk1.6.0_33_win_x64</JAVA_1_6_HOME>
          <JAVA_1_7_HOME>jdk1.7.0_80_win_x64</JAVA_1_7_HOME>
          <JAVA_1_8_HOME>jdk1.8.0_66_win_x64</JAVA_1_8_HOME>
        </properties>
    </profile>
  </profiles>  
  <activeProfiles>
    <activeProfile>compiler</activeProfile>
  </activeProfiles>
</settings>


Ici nous avons spécifique un répertoire différents du répertoire par défaut du repository maven locale qui permet a Maven de stoker toutes les dépendances dont il aura besoin lors des builds (nous verrons également ce point par la suite)

Dans ce cas ci, nous n'utilisons pas de repository distant permettant a Maven de resoudre les dépendances manquantes de son repository locale. Nous sommes donc dans une configuration hors-ligne. Donc si lors du build Maven, il manque une dépendance dans le repository locale, Maven finira en echec.

Pour permettre a Maven de résoudre des dépendances manquantes et de les mettre dans son repository locale, on ajoutera le serveur central Maven :


<profile>
  <id>securecentral</id>
  <!--Override the repository (and pluginRepository) "central" from the
     Maven Super POM -->
  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo1.maven.org/maven2</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <url>https://repo1.maven.org/maven2</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </pluginRepository>
  </pluginRepositories>
</profile>


Processus Maven

Maintenant que Maven est configuré (sommairement) intéressons nous aux processus de build en lui-même.

Nous l'avons vu précédemment, Maven répond a un grand nombre de besoin, son processus va s'appuyer sur de nombreux plugin décrits sur cette page qui vont interagir afin de procéder a l’exécution de tout ou partie du cycle de vie.

Le cycle de vie Maven est ce que l'on pourra appelé complet. Il se compose d'un cycle par défaut contenant les processus de compilation, test, packaging et déploiement précédé optionnellement d'un cycle de nettoyage des projets et suivi optionnellement d'un cycle de génération de site documentant les projets.




Ainsi via l'appel de la commande mvn (répertoire bin de Maven) et en se plaçant dans notre projet, il sera alors possible de faire appel a un processus déroulant les phases décrites par le schéma ci dessus. A noter que les deux cycles de vie optionnels clean et site ne seront déroulés que si appeler explicitement via la commande Maven alors que le cycle de vie Default sera de toutes façon exécuter jusqu’à l’étape (ou phase dans le jargon Maven) explicitement appelée

Ainsi, la commande


$ mvn compile 


exécute les phases validate a compile du cycle default, tandis que


$ mvn clean test


exécute toutes les phases du cycle clean et les phases validate a test du cycle default.

Ainsi, la commande


$ mvn clean deploy site-deploy


exécute toutes les phases, mais ce ne sera pas forcement une bonne idée....

Mais on a parler de plugins ? qu'est ce que c'est?

Et bien tout le processus présenté ci dessus est la modélisation des activités classiques auxquelles les builds vont répondre. Cependant, on peut facilement imaginer que d'un projet a l'autre les builds ne vont pas s'appuyer sur les même concepts selon les phases. Ainsi tout bêtement la compilation d'un projet Java ne sera pas la même chose qu'une compilation d'un projet C++. De même, certains projets vont s'appuyer sur des configurations differentes de packaging, de compilations, de test. Et même sur des projets relativement semblables, des choix technologiques peuvent amener des outils différents.

Face a cette richesse de besoin et de possibilité, Maven a adopté le principe du : voici un plugin implémentant le comportement par défaut pour le cas le plus général et si le plugin ne correspond pas, est bien il existe des moyens de créer les siens (nous reviendrons sur ce point dans un autre article).

Ainsi pour que pour chaque phase soit proposée  les outils et les moyens de configuration adaptés, Maven va s'appuyer sur ces fameux plugins pour donner une implémentation et une opérationnabilité liés aux spécificités de chaque projet. Le plugin selon le cas sera configuré difficilement ou simplement substitué par un autre, voir même parfois ajouter et exécuté parallèlement.

Pour une liste exhaustive de l'ensemble des plugins "standard" utilisable je vous invite a consulté cette page. Cela donnera une idée des possibilités par défaut, et les plugins utilisables selon les phases des cycles de vie Maven.

Il manque maintenant un dernier élément a tout cela. Comment donner a Maven la carte des plugins a utiliser pour son cycle de vie et leur configuration? Le POM!

Project Object Model

Le POM ou fichier pom.xml est ce qui permet à Maven de connaitre le comment builder le projet courant.

Il va en exister de différents types, si l'on veut suivre de bonnes pratiques Maven, on va s'appuyer sur le pattern parent/module/projet (décrit aussi dans cet article):

  • Des pom projet supportant la production d'un composant logiciel spécifique de type jar, deb, ear, etc... Il s'agit de ce que l'on peut considérer comme étant la composante Maven qui nous vient en premier a l'esprit. Ce pom va donc définir les variables locales au projet, les processus spécifiques nécessaire à la compilation du composant, les dépendances et ou encore de quel pom parent le projet va hériter.
  • Des pom parent qui ont pour but de factoriser des comportements standard de build dont vont heriter des pom projets . Dans ces pom on trouvera alors l'ensemble des spécificités propre à des familles de projets partageant des processus ou des propriétés de compilation commune.
  • Des pom module permettant d'orchestrer la construction d'un ensemble de projets techniquement interdépendant en les agrégeant.

Attention un POM se définit en XML, de ce fait, ce dernier est conforme a ce que l'on appelle un schéma (XSD) pour en structurer les informations a la manière d'une grammaire. Ainsi, tous les types de pom se base sur le même XSD amenant souvent a des utilisations fusionnées des précédents concepts présentés. Alors bien sur, Maven aurait pu simplement définir des XSD différent pour répondre aux différents types. Le choix a été fait de ne pas brider leur utilisation et de permettre malgré tout quelques digressions. Quelques digressions ne signifie pas que cela doit être une généralité car suivre le pattern parent/module/projet permet largement de couvrir 90% des cas d'utilisation. Et comme dans tous les cas d'utilisation des patterns, si vous faites autrement, c'est que vous avez une vraie bonne raison technique (et pas une raison du type : on livre demain...)

Pour avoir une illustration plus précise de cette décomposition, je vous invite a consulter cette question sur stackoverflow. Elle traite bien de la question et nous ramène comme souvent au problème de la division des préoccupations et des besoins comme en POO et ce selon la complexité du problème. En effet, dans un cas simple, on préférera avoir un POM projet classique.... ensuite lorsque les projets commenceront a se multiplier un peu on décidera de construire un POM parent pour factoriser les propriétés et donc on y déposera également une définition des modules à construire (la liste des POM projets). Finalement, lorsque l'on aura des projets dont les POM parent n'auront plus de points communs et qu'il faudra les diviser, alors on placera des POM modules afin d'orchestrer le ou les builds possibles pour les lots de projets a gérer...

Ainsi rien que par cet exemple, certes, on se rend compte que progressivement on en arrivera de toute façon a tendre vers l'application du pattern parent/module/projet... cependant, afin d’éviter des modifications douloureuses dans les dépendances des builds, il est vraiment préférable de définir de suite un structure de POM parent, factorisant des processus standard de build, et des modules définissant séparément les lots de builds.

Je ne vous ferais pas l'affront de vous donner un exemple, avec les differentes références que je vous ai donné ci dessus, vous avez largement les moyens de soit débuter, soit enrichir l'architecture des builds de vos projets.

Voila, un grand tour d'horizon de Maven, ce que l'on en fait et ce qui est important de faire des le départ au niveau structure des projets. Ceci n’était cependant qu'une introduction donc dans les prochains articles sur Maven sous essayeront de voir les points suivant:

  • un POM et une architecture parent/module/projet en vrai
  • comment faire son propre plugin
  • c'est quoi les archétypes

vendredi 8 décembre 2017

La modélisation

La réalisation d'un logiciel informatique nécessite de nombreuses taches de nature multiples. Généralement on définit les activités de production d'un logiciel au travers d'un processus de développement. Il en exige de plusieurs comme par exemple en  V, en cascade, en cycle, etc... Leur point commun est de poser un certain nombre de phases indispensable a la bonne marche du développement.

Ces phases sont généralement : Analyse, Modélisation, Conception, Développement, Test. Il peut en existe plus, on peut en considérer moins en allant parfois dans le pire des cas a se restreindre à la seule phase de développement.

Je traiterai des phases de développement dans un autre article mais j'aimerai me focaliser sur une phase que j'estime fondamentale et pourtant très souvent mise de coté : la modélisation.

Comprise entre la phase d'analyse et la phase de conception, la modélisation est très souvent négligée car assimilée soit à l'analyse soit à la conception, quand elle n'est pas complètement ignorée.

Revenons sur ce qu'est la modélisation et ses concepts:
La modélisation est l'activité consistant a produire des modèles. 
Nous avons deux termes a définir:
  • Produire: la production est la mise en œuvre de quelque chose au moyen d'outils sur la base de plans et schémas de construction ainsi que de méthodes. Produire est donc une activité intentionnelle permettant l'apparition par différents moyens de l'artefact voulu
  • Modèle: élément de représentation, de simplification ou d'abstraction réalisée dans une intention et un contexte particulier.
Ainsi produire des modèles c'est faire usage de moyens pour abstraire, simplifier, mettre en évidence quelque chose pour faire la mise en perspective de notre compréhension d'un problème et ce avec les outils dont nous disposons, c'est a dire langage de modélisation, schéma ou encore langage naturel, etc.

Cette description pourrait être assimiler à de l'analyse , sauf que l'analyse ne se réduit qu'a la compréhension du problème sans l’établissement de solution, de même on pourrait l'associer à de la conception sauf que la conception  nécessite une décomposition fonctionnelle cohérente pour être menée.

En fait on le voit ici la modélisation se superpose clairement sur l'analyse et la conception sans les remplacer complètement non plus. Mais alors qu'apporte la modélisation ? Et bien elle rempli le gap existant entre les deux. Voyons comment :

La modélisation apporte la possibilité de traduire le résultat de l'analyse pas forcement formel en des modèles compréhensibles pour la phase de conception et ce par le biais de langage de modélisation (UML, AADL, SysML, etc... tout langage permettant la mise en perspective des points de vue à aborder)

Et c'est la que c'est important, car concevoir une application c'est souvent s'appuyer sur des architecture connues et maîtrisées (en couche, décentralisées, agents, etc...) mais l’intégration du besoin dans ces architecture nécessite forcement la conceptualisation de ces modèles sans lesquels les concepts seraient dilués (comme on le voit souvent) dans la solution;  les mécanismes techniques associés mis en œuvre se retrouvent alors mal définis et mal identifiable.

En conclusion, on dit que le langage forme les idées, qu'il est impossible de conceptualiser sa penser sans le support de notre langue, il est important a ce titre que nous utilisions les langages de modélisation pour former correctement les programmes. Ces langages nous donne des outils et des méthodes adapter pour combler le vide entre spécification et conception par cette phase qui s’appelle la modélisation.