121102 aetc_consultingconf4d

862 vues

Publié le

2012 : Conférence "Industrialisation du développement 4D avec les composants" réalisée par A&C Consulting
4D est un environnement de développement rapide. La productivité et la qualité peuvent être améliorées avec, entre autres, la réutilisation de code. Les composants apportent une solution adaptée et élégante pour répondre à ce besoin.
La démarche de structuration des composants, les avantages et inconvénients par rapport aux différentes approches a été présentée.

Publié dans : Technologie
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
862
Sur SlideShare
0
Issues des intégrations
0
Intégrations
3
Actions
Partages
0
Téléchargements
3
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

121102 aetc_consultingconf4d

  1. 1. 4 D S U M M I T E U R O P E 2 0 1 2 Industrialisation du développement 4D avec les composants Presented by : Bruno LEGAY - A&C Consulting 1
  2. 2. INDUSTRIALISATION ? De quoi parle-t-on lorsqu'on parle d'"industrialisation" ? L'industrialisation est caractérisée par l'optimisation des processus de fabrications de produits manufacturés. On est ainsi passé d'une production "artisanale" à une production "industrielle". Cette évolution remonte au XIXeme siècle (1801) avec la révolution industrielle qui apparaît en Grande Bretagne. Elle est caractérisée par l'utilisation de machine, la production en série, la standardisation pour abaisser les coûts de production et améliorer la qualité. Quelques dates clés et les tendances dans deux domaines spécifiques • Automobile : o 1886 première voiture ; o 1908 Ford T – Taylorisme : production à la chaîne ; o 1961 premier robot industriel ; o 1990 "commonolisation" (partie cachée commune – partie visible personnalisée). • Informatique – matériel o 1943 Colossus o 1976 Apple I o 1984 Macintosh - IBM PC/AT o standardisation des composants (processeurs, mémoire, disques). On remarque plusieurs tendances : automatisation des taches, standardisation de composants. Toutefois, ces domaines comportent des différences significatives par rapport au logiciel. La conception d'un logiciel s'apparente peu à une succession de tâches prédéfinies et répétitives qui peuvent être découpées, optimisées et enchaînées. Enfin, ces deux domaines ont pour objectifs de produire des biens matériels alors que l'industrie logicielle relève plus d'un travail de conception consistant à produire un bien numérique et immatériel. La question de production en masse ne se pose pas de la même manière. Qu'en est-il de l'industrialisation appliquée au génie logiciel (utopie ou réalité) ? Deux axes : • • automatisation de tâches répétitives standardisation des composants. 2
  3. 3. AUTOMATISATION Automatisation de tâches répétitives Pourquoi ? • • • • cohérence / consistance qualité (éviter les erreurs humaines) éviter les dérives se concentrer sur les tâches à valeur ajoutées. Génération de librairies, de code compilé, d'exécutables (construction d'applications avec GENERER APPLICATION, génération d'installeurs, compression, archivage sources, publication, signature md5, etc…). Possibilité d'utiliser plusieurs "profils" d'application (fichier xml "BuildApp"), générateur d'installeur "nsis" sur windows. Les tests unitaires sont destinés à vérifier le bon fonctionnement d'une partie spécifique d'un logiciel (et ceci en toutes circonstances). Les tests unitaires doivent aussi permettre de vérifier qu'une modification du logiciel (modification du code) n'introduit pas de régressions (apparition de nouveaux dysfonctionnements). Les tests unitaires permettent aussi de vérifier rapidement l'impact des changements liés aux plateformes ou aux environnements. En cas ce bug, le contexte est ajouté dans le "test" pour valider la correction et vérifier que ce bug ne réapparaitra plus. Cf méthodes XP (Extreme Programming) ou TDD (Test Driven Development). Génération de documentation. Les documentations techniques sont difficiles à maintenir. La documentation la plus à jour et la plus précise doit se situer au niveau du code. On peut s'inspirer de Javadoc qui est utilisé dans le monde Java. Il s'agit de structurer des informations sur la méthode dans les commentaires à l'aide de balises (ou "tags"). Les macros permettent alors de préparer cette zone avec un "modèle". Le développeur n'a qu'à compléter cette zone. 3
  4. 4. STANDARDISATION DES COMPOSANTS Préhistoire des composants 4D Insider est l'ancêtre des composants actuels (apparus en v11). 4D Insider était l'outil de prédilection pour déplacer des objets (méthodes, formulaires, etc…) entre diverses structures. Avec 4D Insider, on pouvait créer des librairies ou composants (avec une notion de composants protégés). 4D Insider avait un certain nombre de limites (l'utilisation des composants n'était pas très souple entre autres). 4D Insider est mort ! Vive les composants ! 4
  5. 5. PRINCIPE DES COMPOSANTS Rappel du fonctionnement des composants Un composant est une base de données (placée dans le répertoire "Components"). NOTE : à partir de 4D v12, on peut placer des composants dans l'application 4D (comme pour les plugins). On a une notion de base "hôte" et une (ou plusieurs) base(s) "composant(s)". Pour les sources du composant on parle parfois de la base "matrice". Une base interprétée peut utiliser un composant interprété ou compilé. Une base compilée utilise nécessairement un composant compilé. Attention à la compatibilité des options de compilation (compilation 64 bits par exemple). Les modes "Unicode" de la base "hôte" et la base "composant" doivent être compatibles (c'est-à-dire identique). Les méthodes du composant visibles par la base "hôte" doivent être "partagées". L'inverse est vrai aussi, pour qu'un composant appelle/exécute une méthode de la base "hôte", celle-ci doit aussi être partagée. Les dépendances des composants doivent être maîtrisées (et documentées). Certains objets sont utilisables dans un composant, d'autres ne sont pas utilisables. Objet Utilisable en mode composant Méthode oui Formulaire projet oui Formulaire table non Table et champ non Trigger non Méthode base ("sur ouverture" par exemple) non Utilisateur et Groupe non Préférences/propriétés de la base non De ce fait, certaines commandes n'ont pas de sens (et ne peuvent donc pas être utilisées) comme par exemple "ECRIRE IMAGE DANS BIBLIOTHEQUE". 5
  6. 6. Certains objets sont partagés, d'autres sont cloisonnés. Objet Partagé / cloisonné Variable (process et interprocess) cloisonné Variable système (ok, Document, etc…) cloisonné Feuille de style cloisonné Infobulle cloisonné Enumération cloisonné Image bibliothèque cloisonné Menu (éditeur menu) cloisonné Sémaphore cloisonné Ensemble partagé Sélection temporaire partagé Liste hiérarchique partagé Menu (cf Créer menu) partagé Référence xml partagé Référence fichier partagé Pointeur partagé 6
  7. 7. AVANTAGES DES COMPOSANTS Quels sont les avantages d'un composant ? Les composants permettent de partager et réutiliser le code de manière efficace. Un composant permet de cloisonner les environnements d'exécution et d'éviter des "collisions". C'est une alternative possible à l'utilisation systématique de préfixes sur les variables. Un composant compilé peut permettre des gains de performances significatifs dans une base interprétée (en développement par exemple). 7
  8. 8. CONTRAINTES Quelles sont les contraintes rencontrées lors de la création de composants ? L'implémentation de composant nécessite de bien comprendre les mécanismes de dépendances. Par exemple, si un composant utilise explicitement un plug-in, la base "hôte" devra avoir accès à ce plugin. On rencontre la même contrainte avec les composants (un composant utilisé explicitement dans la base "matrice" devra être installé dans la base "hôte"). La documentation est impérative. En effet, il n'est pas possible de consulter le code d'un composant compilé. Au minimum une description de la méthode avec le détail des paramètres doit figurer dans la zone "commentaires" de l'explorateur (en v12). Les commentaires situés au début de la méthode d'un composant ne sont pas visibles depuis la base "hôte" si le composant est compilé (mais ils sont visibles si le composant est interprété). 8
  9. 9. PIEGES Quelques pièges liés aux composant (et comment les éviter / contourner) ? La commande "RESOUDRE POINTEUR" pouvait parfois être utilisée pour comparer si deux pointeurs pointaient bien sur la même variable. Si l'origine des pointeurs est différente, ils peuvent porter le même nom et pourtant ils pointent sur des variables différentes. La comparaison de pointeurs (en passant par RESOUDRE POINTEUR est donc fausse). Il faut simplement comparer directement les pointeurs : Si($vp_ptr1=$vp_ptr2) La commande "Pointeur vers" utilisée dans un composant retournera un pointeur vers une variable du composant. Une astuce consiste à utiliser une méthode de "rétro-appel" (ou "callback"). Dans la base "hôte", on crée une fonction qui fera appel à "Pointeur vers" (on oublie pas de partager cette méthode) et on passe au composant le nom de cette fonction. Le composant pourra alors appeler cette fonction (via la commande "EXECUTER METHODE"). La création de cette méthode de "callback" peut même être automatisée. 9
  10. 10. DEPENDANCES SOUPLES Comment gérer des dépendances souples ? On peut avoir besoin d'avoir de composants qui font appel de manière optionnelle à un autre composant. Soit parce que ce composant n'est nécessaire que dans un contexte (contexte de développement dans la base "matrice") ou parce que ce composant fournit une fonctionnalité optionnelle lors de l'utilisation. Dans ce cas, si l'appel à ce composant est effectué de manière explicite, on aura un message d'erreur à l'ouverture de la base "hôte". Le composant doit détecter de manière transparente la présence de l'autre composant et agir de manière appropriée. C'est ce qu'on appelle une dépendance souple. Pour détecter la présence d'un composant, il y a la commande LISTE COMPOSANTS. On peut ensuite faire appel aux méthodes du composant via la commande EXECUTER METHODE pour éviter les problèmes de dépendances fortes. // LOG_debug ($vt_message) TABLEAU TEXTE($tt_componentsList;0) LISTE COMPOSANTS($tt_componentsList) Si(Chercher dans tableau($tt_componentsList;"LOG_component")>0) EXECUTER METHODE("LOG_debug";*;$vt_message) Fin de si TABLEAU TEXTE($tt_componentsList;0) 10
  11. 11. ASTUCES Quelques astuces Il est parfois nécessaire de déterminer si le code s'exécute dans le composant ou dans la base "hôte". Pour cela on peut comparer le résultat de la commande "Fichier structure" avec et sans l'option "*". Par défaut (sans "*") Fichier structure retourne le nom long/chemin du fichier structure (fichier .4db ou .4dc) du composant. Si "*" est passé, Fichier structure retournera le nom long/chemin du fichier structure de la base hôte (si on est dans un composant) Si(Fichier structure # Fichier structure(*)) // on est dans un composant … Sinon // on est pas dans un composant … Fin de si On peut en faire une fonction, mais attention, par définition cette méthode ne pourra pas s'utiliser comme une méthode partagée d'un composant. Il faut la copier… On a parfois besoin de déterminer quelle est la langue du langage 4D utilisée (les commandes sontelles en français ou en anglais) ? C_ALPHA(2;$va_language) C_TEXTE($vt_commandNameOfCommandName) $vt_commandNameOfCommandName:=Nom commande(538) //538  "Command name" Au cas ou : ($vt_commandNameOfCommandName="Nom commande") $va_language:="fr" : ($vt_commandNameOfCommandName="Command name") $va_language:="en" Sinon $va_language:="en" Fin de cas 11
  12. 12. LES COMPOSANTS FOURNIS PAR 4D 4D fourni quelques composants standard 4D fourni déjà quelques composants 4D SVG : images vectorielles SVG pour le runtime 4D Widgets propose un datePicker et timePicker pour le runtime 4D Pop propose des fonctionnalités au développeur. Composant orienté vers l'environnement de développement. Sans oublier tous les composants fournis par Keisuke Miyako Au delà des composants fournis par 4D, quel est l'intérêt pour un développeur à créer ses propres composants ? 12
  13. 13. POURQUOI CREER UN COMPOSANT Dans quel cas doit-on envisager de créer un composant ? Dans un logiciel, on peut déterminer un ratio "glue" / "substance" (cf Alexander Stepanov). La partie "glue" correspond au code qui ne répond pas directement au besoin du projet et la "substance" correspond à la partie spécifique (au métier). On peut mesurer ceci sur la base du nombre de lignes. Par exemple, dans un de nos projets, nous avons effectué récemment des métriques et nous avons constaté que sur 310 000 lignes de code (méthodes projet) 43,5 % du code était du code générique et que le reste 56,5 % était du code spécifique. Objectif d'efficacité : se concentrer sur le métier/fonctionnel et simplifier la ré-utilisation du code technique générique testé et éprouvé (mise en place, maintenance). Objectif de qualité : en simplifiant la mise en place (et la mise à jour) de code générique, on facilite la réutilisation. L'amélioration continue du code générique (ajout de fonctionnalités, optimisation, correction de bugs) est plus facilement mutualisée entre les projets et contribue à une amélioration de la qualité globale des applications. Ces objectifs sont surtout intéressant pour les développeurs qui travaillent sur plusieurs projets. 13
  14. 14. QUE PEUT-ON FAIRE AVEC UN COMPOSANT Un composant, oui, mais pour faire quoi ? On peut créer des composants pour packager des méthodes bien évidemment (génération de codes barres), on peut afficher des formulaires (formulaires base) pour l'affichage des thermomètres, une zone Web area (pour une fenêtre GoogleMaps par exemple) par exemple. On peut aussi utiliser les composants pour packager des binaires ou outils externes. On peut par exemple placer les exécutables (OS X et Windows) dans le répertoire "Resources" et les appeler via la commande LANCER PROCESS EXTERNE. Idem pour des fonctions PHP (scripts php). Par exemple, 7z pour la compression zip, xmllint pour la validation schéma xml avec XInclude, rsync+cygwin, ImageMagick, wkhtmltopdf, etc… On peut facilement placer des méta-données dans un composant. Par exemple, on peut placer des meta-données au format xml dans le répertoire "Resources" qui seront accessibles via une méthode partagée du composant (par exemple les codes escape url http et/ou html). Les composants peuvent aussi être utilisés pour wrapper les plugins (4D for OCI par exemple). On peut créer des composants qui permettent de basculer entre différents plugins similaires (commandes TCP des Internet Commands, NTK et ITK) ou entre un plug-in et du code 4D pur (ObjectTools, XML Plugin, etc…). 14
  15. 15. CHOIX Quelles questions doit-on se poser avant de se lancer ? Quel type de composant va-t-on créer ? Un seul composant avec toutes les méthodes à l'intérieur (approche monolithique) ou un plusieurs composants (approche modulaire) ? Dans le cas d'une approche modulaire, comment seront gérées les dépendances entre les composants ? Composant interprété ou compilé (si oui pour quelle plateformes) ? Composant Unicode ? Comment mettre en place, définir et stabiliser ses API (maturation des points d'entrée, flexibilité/souplesse de fonctionnement avec l'utilisation de paramètres optionnels et callback, stabilité, pérennité et rétro-compatibilité) ? 15
  16. 16. NOTRE CONTEXTE Le contexte dans lequel nous avons été amenés à mettre en place des composants est le suivant A&C Consulting est une SSII avec 3 développeurs 4D expérimentés. Nous travaillons sur de nombreux projets spécifiques. Nous avons construit au fil des années une bibliothèque de code générique, mais les méthodes de mutualisation de ce code étaient encore artisanales. A&C Consulting a une expérience de commercialisation d'un composant. Ce composant est lié au plugin 4D for OCI : ociLib. C'est un composant qui a été mis au point pour les besoins d'un de nos clients et ensuite proposé à des développeurs tiers qui étaient intéressés. Nous travaillons depuis plusieurs années avec une approche générique modulaire 16
  17. 17. NOTRE APPROCHE Voici l'approche qui a été retenue : Dans un premier temps (première phase), nous nous focalisons sur les "couches basses". Pour ces couches basses, nous avons retenu une approche modulaire (file system, blob, env, http, html, io, log, objectTools, tableaux, text, zip, etc…) Nous avons une volonté de limiter les dépendances (quitte à dupliquer du code entre des composants) pour des raisons de souplesse mais aussi pour éviter les problèmes de compatibilité liées aux versions. C'est un travail de longue haleine (135 000 lignes de code) qui se fait petit à petit (un ensemble logique de code générique correspondant à un module est converti en composant et ce code est retiré des projets pour être remplacé par le nouveau composant). La documentation est impérative et prend du temps. La re-factorisation prend du temps (module fourre-tout "UTL" qui nécessite d'être réorganiser de manière plus logique). Plus tard, nous prévoyons de mettre en place un composant de niveau intermédiaire qui s'appuiera sur les composants "couches basses" avec des dépendances fortes. 17
  18. 18. CONVENTION DE NOMMAGE Les conventions de nommage des méthodes sont importantes Nous utilisons un système de préfixe dans les noms des méthodes pour facilement identifier l'origine d'une méthode (quel composant). Pour chaque composant nous fixons un code mnémotechnique de deux à quatre lettres : HTTP_GET => composant "http_component" FS_macPathToUnixPath => composant "fs_component" Dans le composant (base "matrice"), les méthodes qui ne sont pas partagées (et invisibles) contiennent deux "_" après le préfixe. Ceci permet de s'appuyer sur la convention de nommage pour fixer rapidement les attributs des méthodes (via l'écran "Modifier attributs globalement") et de les trier dans l'explorateur. NOTE : la notion de "partagé entre composant et base hôte" n'est pas visible dans l'explorateur des méthodes tandis que la notion "visible/invisible" est repérable tout de suite, il est donc judicieux de les fixer de manière similaire/cohérente. 18
  19. 19. DOCUMENTATION Comment gérer la documentation des composants La documentation est fondamentale pour la mise en place de composant (rappel le code source et les commentaires d'un composant compilé ne sont pas accessibles). L'approche Javadoc qui est une solution proposée dans un autre langage pour répondre une problématique similaire (documentation d'API) est une bonne source d'inspiration Principe basé sur des "balises" (ou tags) placées dans les commentaires en entête L'entête défaut (avec les tags) est généré par une macro. Ensuite, un peu d'API Pack pour automatiser tout ça… Un composant maison "xdoc" (s'appuyant sur API Pack) est utilisé pour lire le contenu de chaque méthode, identifier les balises/tags de documentation, effectuer une conversion en xml. Cet xml peut ensuite être utilisé pour générer différents formats de documentation (rtf, html, pdf, etc…). Pour l'instant, nous utilisons 4D Write pour générer un texte stylé rtf (par méthode) qui est ensuite placé dans la zone "Commentaires" de la méthode. Attention : c'est un hack (reverse engineering) : il n'y a malheureusement pas, à ma connaissance, de moyen officiel pour alimenter cette zone. 19
  20. 20. TESTS Pourquoi tester et valider son composant et comment y arriver ? Tester son composant avant de le déployer est important si on veut éviter des "aller-retour" superflus. Les tests permettent de valider le fonctionnement nominal, de vérifier la non-régression, de valider une optimisation, de valider le comportement lors d'un changement de version de 4D, de tester sur une plateforme spécifique, etc…). L'utilisation de tests unitaires permet de valider le fonctionnement du composant en automatisant les tests. Les tests unitaires permettent de réduire les tests manuels qu'un développeur consciencieux devrait faire (parcourir quelques fonctionnalités de l'application pour vérifier le bon fonctionnement). Pourquoi ? Parce que ces tests sont répétitifs, qu'ils sont chronophages, et qu'ils sont donc rarement effectués en pratique. Les tests unitaires permettent d'éviter (ou toutefois de limiter) le nombre d'anomalies/de bugs contenues dans une application livrée au client. La mise en place de ces tests unitaires est aussi chronophage… Donc il faut faire preuve de bon sens et pragmatisme sur les tests unitaires… Par exemple, il n'est pas prioritaire d'ajouter des tests unitaires sur une méthode simple et qui marche bien. Par contre, lors de la correction d'un bug lié à un contexte particulier, il est souvent souhaitable d'ajouter ce contexte dans les tests unitaires en ajoutant un "test case". Pour les méthodes complexes, l'ajout de tests unitaires permet de garantir leur bon fonctionnement (vecteur de test md5 par exemple). 20
  21. 21. GESTION DES VERSIONS Comment gérer les versions de ses composants ? Une approche simple pour gérer les versions de son composant est de créer une fonction : xxx_componentVersionGet Cette fonction retourne la version du composant et on peut commenter l'historique du composant dans le code source de cette méthode (dans les commentaires). Si le composant génère des fichiers de logs lors de l'exécution, cette méthode peut être appelée à l'initialisation du composant et le résultat est envoyé dans le fichier de log. 21
  22. 22. INITIALISATION Les composants on parfois besoin d'être initialisés. Comment gérer cette initialisation ? Les composants contiennent des variables (et des tableaux notamment) qui nécessitent des déclarations et parfois des initialisations. Ces variables peuvent être des variables “process/globales” ou “interprocess”. Ces opérations sont effectuées dans des méthodes qui correspondent : initialisation process ou inteprocess. Attention l'appel à une méthode d'initialisation effectué de manière erronée/inopinée ne doit pas vider les tableaux déclarés (qui peuvent être alimentés). Il faut donc gérer, avec un flag booléen (un flag process et un flag interprocess), le fait que l'initialisation du composant a été effectué (ou pas). Ces initialisations peuvent être publiques et explicites (c'est au développeur qui utilise le composant de faire appel à la méthode d'initialisation de manière appropriée) ou cette initialisation peut être privée, elle doit alors être implicite et transparente. 22
  23. 23. MODELE DE COMPOSANT Lorsqu'on crée régulièrement des composants, on s'aperçoit qu'on utilise souvent des préférences et quelques méthodes identiques. Nous avons standardisé l'organisation d'un composant avec trois répertoires : - build - src - test Des préférences standard sont définies dans la base "modèle de composant". Les quelques méthodes standard sont pré-installées dans le modèle (xxx_componentVersionGet, etc…) Enfin, une petite "checklist" permet de s'assurer qu'on a bien effectué toutes les tâches de personnalisation du modèle. 23
  24. 24. GESTION DES VERSIONS DE 4D Comment gérer les composants selon les différentes versions de 4D ? La transposition directe du code n'est pas toujours évidente (par exemple les caractères de commentaires ` en v11 et // à partir de v12). Les composants ont principalement été créés et mis au point en v11. On a donc converti ces composants en v12 en maintenant les deux versions en parallèle. Les corrections ont été reportées manuellement au cas par cas. Certaines commandes ou préférences sont spécifiques à une version. Par exemple la notion "compilation 64 bits" n'existait pas en v11. Il y a des commandes qui changent de nom (attention à l'export de code en texte) ou qui apparaissent et peuvent nécessiter une amélioration du code pour en tenir compte (en v13 : GENERER DIGEST, HTTP Client, etc…). Le code peut toutefois anticiper et s'adapter. On peut, par exemple, dans une méthode v12 tenir compte d'un nouveau comportement spécifique à la v13 et s'adapter. Lorsque le composant sera converti en v13, la méthode s'exécutera de manière optimale sans avoir été modifiée. Hormis les nouveautés apparues en v13, les composants v12 sont compatibles v13. Les composants v11 sont compatibles v11 uniquement. 24
  25. 25. CONCLUSION Quel bilan peut-on tirer de notre expérience avec les composants ? En quelques mots : "les composants : ça marche !" Les composants sont une solution adaptée, intéressante et élégante pour la gestion du code générique lorsqu'on doit gérer plusieurs projets. Une attention particulière doit être apportée sur la documentation pour faciliter l'utilisation du composant. 25
  26. 26. BIBLIOGRAPHIE http://www.cad-magazine.com/content/standardiser-pour-mieux-personnaliser http://nsis.sourceforge.net/Main_Page http://fr.wikipedia.org/wiki/Test_unitaire http://fr.wikipedia.org/wiki/Extreme_programming http://fr.wikipedia.org/wiki/Test_Driven_Development http://fr.wikipedia.org/wiki/Javadoc http://en.wikipedia.org/wiki/Name_collision http://www.stepanovpapers.com/ http://www.stepanovpapers.com/Industrializing%20Software%20Development.pdf http://sources.4d.com/trac/4d_keisuke/wiki/Components 26

×