Subsections of Mes projets
Bulletin NG - Guide du développeur
Cette page est mini guide du développeur (ma définition du guide du développeur) pour le projet BulletinNg (projet en cours de refonte au 31/12/2024).
1/ Gestion de projet
Aucun suivi des tâches n’est en cours pour le moment car les demandes arrivent et sont traitées au fil de l’eau.
Sont présents en tâches de fond les éléments suivants :
- mettre en oeuvre un maximum des fonctionnalités de Angular, AngularMaterial et des outils de build (NPM, Karma, Jasmine, Protractor, …).
2/ Exigences
Les exigences sont actuellement fournies par la principale utilisatrice. Aucune formalisation n’existe en dehors des quelques lignes ci-dessous.
2.1/ Métiers
Du point de vue métier, le besoin est très spécifique et ne sera pas détaillé. Les principales contraintes métiers ayant amener à des choix techniques discutables sont :
- le caractère privé des données nécessite que ces dernières ne soient pas stockées dans une base de données centralisées. L’utilisateur a besoin d’avoir une maitrise complète de leur stockage.
- les données sont donc stockées dans un fichier uploadé et téléchargé par l’utilisateur au début et à la fin de sa session
- les utilisateurs disposant d’un serveur de stockage de données (NAS Network Attached Storage) peuvent l’utiliser pour sauvegarder et charger leurs données (à eux de sécuriser leur serveur)
- l’application ne doit réaliser aucun transfert de données (sauf dans le cas de la sauvegarde sur un serveur qui est le résultat d’une action explicite de l’utilisateur)
- l’application doit être sécurisée dans la mesure du possible pour éviter l’injection de script qui pourrait tenter de voler les données
2.2/ Techniques
Du point de vue technique, l’application doit être
- l’accessibilité n’est pas un besoin car l’utilisateur doit avoir ses données sur son terminal ;
- évolutive : chaque nouveau besoin doit être facilement réalisé pour fournir le service rapidement ;
- fiable (point primordiale) : l’application ne doit pas subir de régressions intempestives portant atteinte à son utilisabilité ou à la fiabilité de ses données ;
- la structure des données sauvegardées ne doit pas être modifiée afin de conserver la rétrocompatibilité avec la précédente application.
3/ Environnement
Ce projet ne compte pas tous les environnements d’un projet classique.
(cf. chapitre Environnement du guide du développeur du projet Mariage)
4/ Architecture technique
Pour limiter les transferts réseau, l’application se résume à un FrontEnd. Afin de simplifier le code et d’en augmenter la maintenabilité, le développement n’est pas réalisé en JS/JQuery mais avec Angular (très bon framework pour faire du binding données/HTML)
Les tests sont cruciaux dans le cadre de cette application. Donc, sans aller jusqu’à une couverture de code de 100%/100% (en ligne / en branche), toutes les fonctionnalités doivent être testées (cf. paragraphe dédié aux tests).
5/ Tests
5.1/ Que tester
Les cas nominaux de tous les composants doivent être testés ainsi que les cas d’erreur principaux.
Aucune exigence n’impose une couverture de code particulière mais 80% est souhaitable pour tous les composants contenant de la logique (les services).
Jasmine et Ts6-Mockito sont utilisés pour les tests unitaires des services.
Protractor est utilisé pour les tests de bout en bout (e2e - end to end).
6/ Règles de conception
6.1/ Données
Le modèle de données ne doit pas évoluer au point de briser la rétrocompatibilité avec l’application précédente.
6.2/ Service
Toute logique ou manipulation de données doit se faire dans un service.
La manipulation du singleton de données est de la responsabilité de DataRepository (ce qui facilite les tests unitaires en offrant un point d’entrée à un bouchon).
Les lectures ou agrégations de données doivent se faire dans LectureService.
Les manipulations complexes, non réutilisables et propres à un sous-ensemble du jeu de données doivent être placés dans un service dédié.
6.3/ Composants Angular
Les composants doivent être les plus simples possibles et limités la duplication de code. Pour cela, les éléments communs à tous les écrans comme la saisie de note ou de compétence doivent être l’objet de composant dédié.
Les injections de dépendances doivent se faire par la déclaration d’un membre privé dans le constructeur
7/ Règles de développement
Les règles ci-dessous doivent être appliquées par tout développeur souhaitant participer à ce projet (non négociable). Par contre, il est toujours possible de discuter de la modification d’une règle.
7.1/ Langue
Les entités, les attributs et les méthodes sont nommés en français.
Les préfixes, suffixes et concepts inhérents au langage reste en anglais (get, set, is, …)
7.2/ Nommage
Les composants applicatifs sont suffixés selon les règles définies par Angular :
- “xx.service.ts” pour les service (sauf l’unique exception de DataRepository) ;
- “xx.component.ts” pour le code TypeScript des composants d’IHM ;
- “xx.component.html” pour le code HTML des composants d’IHM ;
- “xx.component.css” pour les styles des composants d’IHM ;
- et “xx.spec.ts” pour les tests.
Parmi les composants d’IHM, un préfixe est ajouté en fonction de l’usage et du type de composant :
- “compo-xxx” pour les composants réutilisables ;
- “div-xxx” pour les cadres présents dans la page et visibles à tout instant ;
- “tab-xxx” pour un onglet.
Les entités métier et les classes utilitaires ne sont pas suffixées mais doivent avoir des noms parlant (l’usage du nom d’un pattern est utile pour décrire l’usage/l’utilité du composant)
Les noms de méthode commence par un verbe à l’infinitif
Microsoft VsCode est l’IDE préconisé même si le plugin pour Eclipse n’est pas mal mais plante encore régulièrement (testé en aout 2017). La configuration VsCode est présente dans le repository et les règles de validation TsLint doivent être respectées !
8/ Processus de développement
8.1/ Gestion de configuration logicielle (GCL)
- Que comprend la GCL :
- Les sources applicatives et de test sont dans un repository GIT ;
- Le présent “guide du développeur” est lui aussi dans un repository GIT mais séparé (pas de gestion de version cohérente nécessaire) ;
- Le bug tracker a utilisé est celui du repository GitHub ;
- Les plans de test “métier” ne sont pas formalisés. Mais une partie d’entre eux sont automatisés.
- La gestion de version :
- une seule version existe pour le moment (branche ‘master’).
- si des POC sont réalisés, ils doivent l’être dans une branche dédiée
- aucun TAG n’est posé pour le moment (c’est une chose à faire prochainement)
- l’usage de featureBranch est autorisé et même encouragé
8.2/ Commit
Les messages de commit doivent être explicites.
8.3/ Industrialisation
8.3.1/ Outils
La gestion des exigences est totalement informelle. Ce qui ne pose pas de problème pour ce projet car le délai entre l’expression du besoin et la mise en production est court et qu’aucune contractualisation n’existe (ni sur les moyens ni sur le périmètre métier).
GitHub héberge une partie des outils du projet : repository GIT & guide du développeur, …
L’outil d’intégration continue utilisé est Jenkins (hébergé sur un serveur EC2).
La qualimétrie est réalisée avec SonarQube (hébergée sur le site officiel en ligne).
Les relectures de code sont possibles avec GitLab mais ne sont pas utilisées actuellement (un seul développeur pour le moment)
8.3.2/ Processus
Quitte à faire un petit projet sympa, autant utiliser les outils correctement. Donc le processus de développement (même s’il est minimal) est piloté par un pipeline (cf. pipeline).
Le pipeline est lui aussi en GCL : dans le JenkinsFile
Le pipeline commence au commit du code et enchaîne les étapes suivantes : compilation, tests métiers, tests E2E, qualimétrie, promotion manuelle et mise en production
Mariage - Guide du développeur
Cette page est un court guide du développeur (ma définition du guide du développeur) pour mon projet Mariage.
1/ Gestion de projet
Un suivi minimaliste des tâches est réalisés dans le fichier “backlog.txt” placé à la racine de la branche “master”. Cette backlog est alimentée en fonction des besoins métiers exprimés ou des opportunités techniques.
2/ Exigences
Les exigences sont actuellement fournies par la principale utilisatrice. Aucune formalisation n’existe en dehors des quelques lignes ci-dessous.
2.1/ métiers
Du point de vue métier, le besoin est assez simple : gérer les données d’un mariage. Cela comprend :
- la gestion de
- la liste des invités,
- la liste des différents courriers,
- le suivi de
- l’envoi des courriers,
- la réception des réponses,
- la planification des événements,
- le calcul des statistiques nécessaires aux mariés et prestataires,
- le partage de ces informations avec les proches participants à l’organisation (parents, témoins, …)
Il existe déjà des sites pour faire tout ça. Mais aucun qui nous correspondait exactement. Et tous, systématiquement, sont envahis de publicité (donc, en bon geek, j’ai fait le mien).
2.2/ techniques
Du point de vue technique, l’application doit être
- facilement accessible sur tout support : PC, tablette, téléphone ;
- disponible à tout moment : 24/ 7 sans contrainte temporelle de redémarrage en cas d’arrêt ;
- évolutive : chaque nouveau besoin doit être facilement réalisé pour fournir le service rapidement à l’utilisatrice principale ;
- fiable (point primordiale) : l’application ne doit pas subir de régressions intempestives portant atteinte à son utilisabilité ou à la fiabilité de ses données.
3/ Environnement
Ce projet ne compte pas tous les environnements d’un projet classique (comprendre “projet d’une ESN pour un de ses clients”). Comme l’équipe “projet” ne comprend qu’un seul membre et qu’il n’existe qu’une seule version de l’application (pour le moment en tout cas), il n’est pas nécessaire de prévoir plus de 3 environnements (un projet classique en comprend au moins 6) :
- Développement & tests :
- pourquoi : il faut bien coder l’application avant de pouvoir l’utiliser.
- caractéristiques : poste Windows avec un Eclipse (Néon ou supérieur) avec le plugin HibernateTools (cf. billet dédié)
- différences notables avec l’environnement de production : OS Windows vs Linux en production, pas de reverse-proxy HTTPd ni de HTTPs, pas de manipulation du cache par les entêtes HTTP
- Intégration :
- pourquoi : aucun développeur, même tout seul, n’est infaillible. De temps en temps, une régression peut être introduite ou un défaut de qualité peut échapper à notre vigilance. L’intégration continue est mon garde-fou et nécessite un environnement dédié.
- caractéristiques : sur la même VM que la production. Donc l’application démarrée durant les tests d’intégration doit démarrer sur un autre port que celle en production.
- différences notables avec l’environnement de production : pas de reverse-proxy HTTPd ni de HTTPs, pas de manipulation du cache par les entêtes HTTP
- Production :
- pourquoi : pour faire fonctionner l’application sur un serveur stable, suffisamment disponible pour répondre aux exigences (cf. ci-dessus) et exposé à Internet
- caractéristiques : Linux maintenu à jour régulièrement sur une VM hébergée par Amazon (EC2)
4/ Architecture technique
En bon développeur Java, l’application se base sur Hibernate et Spring. Pour ne pas avoir à installer de composant tiers sur les environnements et parce que les exigences le permettent, l’application est autoporteuse avec SpringBoot. Ce dernier démarre un serveur WEB (Tomcat) et une base de données (HSQL) automatiquement.
Pour réduire les bugs, rien de tel que de réduire le volume de code. Donc SpringData pour la persistance. Ce qui impose l’usage de JPA à la place de l’API Hibernate native.
L’exposition des services en API REST avec SpringMVC (pour continuer avec Spring et se faciliter l’intégration des composants).
L’application WEB est assez simple (voire simpliste) et se compose principalement de tableaux de données chargées depuis l’API REST. Une application Angular eut été possible mais, vu le besoin, une simple application avec JQuery, JQueryUI et JQxgrid a été retenue.
Les tests sont cruciaux dans le cadre de cette application. Donc, sans aller jusqu’à une couverture de code de 100%/100% (en ligne / en branche), toutes les fonctionnalités doivent être testées sur toutes les couches (cf. paragraphe dédié aux tests).
5/ Tests
5.1/ Que tester
Les cas nominaux de tous les composants doivent être testés ainsi que les cas d’erreur principaux.
Aucune exigence n’impose une couverture de code particulière mais 80% est souhaitable pour tous les composants contenant de la logique (hors getter, setter, constructeur, code de programmation défensive, …)
Les composants métiers (Service, Repostitory et Entité) doivent être testés avec des tests d’intégration. Il n’est pas concevable de tester un système entièrement basé sur la notion de transaction et de requêtes SQL (Spring, Hibernate et la BDD) sans une connexion à une base de données et sans activer les commits.
Si certains composants métiers présentent une grande complexité, alors un test de granularité unitaire est tout à fait envisageable. Un tel composant n’existe pas pour le moment.
Les contrôleurs REST doivent être testés unitairement. Ces composants ne sont pas transactionnels et les services sont testés par ailleurs. Mais, pour bien vérifier le paramétrage et le code, il est nécessaire de réaliser le test des contrôleurs en démarrant un serveur WEB (l’adjectif “unitaire” utilisé plus tôt est donc discutable - cf. test de développement).
Les écrans de l’application sont testés en mode “bout en bout”. Selenium est utilisé pour piloter le navigateur et un jeu de données est utilisé pour initialiser le test. ATTENTION : les tests Selenium ne sont donc pas tous indépendants les uns des autres. Ce n’est pas une bonne pratique mais faire autrement avec un test de bout en bout est trop coûteux.
5.3/ Avec quels outils
JUnit et TestNG sont tous deux des exécuteurs de tests. JUnit est utilisé dans les tests des composants métiers. TestNG, étant plus pratique à utiliser avec Mockito, est utilisé pour l’exécution des tests des contrôleurs.
Mockito est donc utilisé pour bouchonner les services métiers dans les tests des contrôleurs.
La classe utilitaire JdbcTemplate (fournie par Spring-jdbc) peut être utilisée dans les tests métiers afin d’exécuter simplement des requêtes SQL en base de données pour valider le contenu.
La classe utilitaire RestTemplate (fournie par Spring-web) peut être utilisée dans les tests des contrôleurs pour réaliser les appels HTTP simplement.
Selenium est une API très riche. La classe MyDriver rassemble les opérations usuelles utiles aux tests (il est tout à fait possible de l’enrichir).
Les sélecteurs à utiliser dans les tests Selenium sont tous rassemblés dans la classe Selectors. Tous les sélecteurs doivent être rassemblés dans cette classe.
Cette classe contient une hiérarchie de sous-classes structurée ainsi : NomDeLaPage / TypeDelements / selecteurElement. Exemple : Index.Button.CONFIRMER_SUPPRESSION
Toute modification d’une page HTML doit entraîner l’enrichissement de la classe Selectors avec le sélecteur permettant de sélectionner les éléments ajoutés/modifiés/supprimés.
6/ Règles de conception
6.1/ Persistance
Toute requête de recherche sans paramètre optionnel doit être codée dans un repository SpringData.
6.2/ Service
La gestion des transactions et des erreurs se traite au niveau des services qui sont les points d’entrée et de sortie des transactions.
6.3/ API
Les services ne sont exposés via l’API que s’ils sont utilisés par l’IHM.
La validation des paramètres d’entrée se fait dans le “contrôleur”.
La transformation des entités en DTO se fait dans le “contrôleur” (dont c’est la responsabilité).
6.4/ WEB - Pages
Les tableaux de données sont réalisés avec le plugin JQxGrid.
Dans un premier temps, les filtres, paginations et tris sont réalisés du coté client (par le framework).
Une fois l’usage courant du tableau défini, les bons filtres et tris (et donc aussi la pagination) doivent être implémentés coté serveur.
6.5WEB - JS
Aucun script ne doit être présent dans la page HTML. A chaque page est associé un script. Les éléments communs à toutes les pages sont dans le script common.js.
7/ Règles de développement
Les règles ci-dessous doivent être appliquées par tout développeur souhaitant participer à ce projet (non négociable). Par contre, il est toujours possible de discuter de la modification d’une règle.
7.1/ Langue
Les entités, les attributs et les méthodes sont nommés en français.
Les préfixes, suffixes et concepts inhérents au langage reste en anglais (get, set, is, iterator, …)
7.2/ Nommage
Les composants applicatifs sont suffixés en fonction de leur type :
- “Application” pour les configurations SpringBoot,
- “Exception” pour les exceptions,
- “DTO” pour les structures de données de transport,
- “Service” pour les services métiers,
- “DAO” pour l’accès à la persistance,
- “contrôleur” pour l’exposition de service en REST
- et “Test” pour tous les tests
Les entités métier et les classes utilitaires ne sont pas suffixées mais doivent avoir des noms parlant (l’usage du nom d’un pattern est utile pour décrire l’usage/l’utilité du composant)
Les classes implémentant une interface sont suffixées par “IMPL”
Les noms de méthode commence par un verbe à l’infinitif
L’usage des Save Actions d’Eclipse est obligatoire pour conserver l’homogénéité du code (cf. petit tour d’Eclipse)
Le formatage des sources est celui par défaut dans Eclipse (version Néon) : 120 caractères par ligne (80 pour les commentaires) et indentation par tabulation.
Les membres sont triés systématiquement.
Les lignes ne contenant que des tabulations et/ou des espaces sont vidées.
Le mot clef “final” est placé sur toutes les variables affectées une seule fois et sur les paramètres.
Le mot clef “this” est utilisé systématiquement.
Les cast inutiles sont supprimés.
7.4/ HQL
Les requêtes HQL simples peuvent être écrites sur une seule ligne. Les plus complexes sont formatées pour être plus lisible. L’usage des commentaires “//” en fin de ligne est autorisé pour forcer Eclipse à conserver à la ligne la chaîne de caractère à concaténer.
Toujours définir par défaut l’attribut READ_ONLY à true sur une méthode chargeant des entités persistantes. Seules les entités nécessitant d’être “managed” doivent l’être (cf. documentation hibernate sur le cycle de vie des objets dans une session)
Ne jamais créer un lien entre deux entités en instanciant une entité et ne définissant que son ID. Toujours utiliser EntityManager.getReference
La gestion des transactions est faite via les annotations Spring. Les exceptions du projet sont runtime et déclenchent donc le rollback. Seuls les composants de type “Service” et “DAO” peuvent être transactionnels (par les “contrôleur”)
8/ Processus de développement
8.1/ Gestion de configuration logicielle (GCL)
- Que comprend la GCL :
- Les sources applicatives et de test sont dans un repository GIT ;
- Le présent “guide du développeur” est lui aussi dans un repository GIT mais séparé (pas de gestion de version cohérente nécessaire) ;
- Le bug tracker a utilisé est celui du repository GitHub ;
- Les plans de test “métier” ne sont pas formalisés. Mais une partie d’entre eux sont automatisés avec Selenium.
- La gestion de version :
- une seule version existe pour le moment (branche ‘master’).
- si des POC sont réalisés, ils doivent l’être dans une branche dédiée
- aucun TAG n’est posé pour le moment (c’est une chose à faire prochainement)
8.2/ Commit
Les messages de commit doivent être explicites. Toute nouvelle fonctionnalité doit être commitée avec un message commençant par “[FEATURE]” (afin que le commit soit correctement affiché dans la page releaseNote de l’application).
9/ Industrialisation
9.1/ Outils
La gestion des exigences est totalement informelle. Ce qui ne pose pas de problème pour ce projet car le délai entre l’expression du besoin et la mise en production est court et qu’aucune contractualisation n’existe (ni sur les moyens ni sur le périmètre métier).
GitHub héberge une partie des outils du projet : repository GIT & guide du développeur, …
L’outil d’intégration continue utilisé est Jenkins (hébergé sur un serveur EC2).
La qualimétrie est réalisée avec Sonar (hébergée sur le site officiel en ligne).
Les relectures de code sont possibles avec GitLab mais ne sont pas utilisées actuellement (un seul développeur pour le moment)
9.2/ Processus
Quitte à faire un petit projet sympa, autant utiliser les outils correctement. Donc le processus de développement (même s’il est minimal) est piloté par un pipeline (cf. pipeline).
Le pipeline est lui aussi en GCL : dans le JenkinsFile
Le pipeline commence au commit du code et enchaîne les étapes suivantes : compilation, tests métiers, tests des contrôleurs, packaging, tests IHM, qualimétrie, promotion manuelle et mise en production
Sujets non traités ici (le projet est terminé, ce guide n’évoluera plus) :
- conception
- quels sont les outils de conception et/ou de modélisation ?
- quels sont les objectifs des modèles (compréhension, communication, …) et quelle est leur durée de vie ?
- règles de conception (programmation défensive, @designByContrat, modularité, …)
- jeu de données de test
- développement
- liste des frameworks disponibles, leur usage et le pointeur sur leur documentation
- qualimétrie obligatoire avec le site “online” (avec sa configuration imposée par la plateforme d’où les violations non corrigée qui ne le seront pas)
- HQL propre
- code en français
- méthode = verbe à l’infinitif
- largeur 120 (on a tous des résolutions d’écran suffisante)
- …
- industrialisation :
- aucune installation de poste automatique car seul l’IDE est nécessaire et l’application est autoporteuse
- IC = jenkins toujours à jour avec un pipelineAsCode (lien vers le blog sur le sujet)
- pipeline = git/compile/TU/TI/TA/qualimétrie/promotion/production
- à quand un second développeur et la mise en place des pullrequest et des revues de code ?
Application Blanche
Cette page est un court guide du développeur (ma définition du guide du développeur) pour un projet assez particulier : une Application Blanche.
L’objectif de l’application blanche est de fournir un exemple d’application (régulièrement utilisé quand je donne des formations) mais aussi une structure minimale pour créer une nouvelle application. A ce titre, l’application doit être particulièrement bien codée (dans le fond comme dans la forme) mais aussi bien documentée (il y a du boulot de ce coté-là).
1/ Exigences
Le fichier “todoList.txt” présent à la racine de la branche master contient une backlog.
1.1/ métiers
L’application n’a pas d’objectif métier.
1.2/ techniques
Les sources évoluent au grès des besoins techniques que je veux prototyper et/ou des nouveaux usages/frameworks que je découvre.
Mais, l’application doit tout de même répondre aux exigences suivantes :
- facilement accessible sur tout support : PC, tablette, téléphone ;
- évolutive : chaque nouveau besoin doit être facilement réalisé (toujours resté sur des solutions simples et efficaces) ;
- fiable (point primordiale) : l’application ne doit pas subir de régressions intempestives portant atteinte à son utilisabilité ou à la fiabilité de ses données.
2/ Environnement
Ce projet n’était pas déployé où que ce soit jusqu’en septembre 2018. Avant cette date, seule la PIC démarre l’application à travers les tests (unitaires, d’intégration et d’application).
Depuis cette date, l’application est déployée sur le serveur Unix et sera bientôt déployée sur le cloud de Google (GCP).
3/ Architecture technique
Cette application se compose :
- d’un backend coupé en quatre modules :
- un projet contenant les classes réutilisables pour les projets “métiers”
- un projet contenant les classes réutilisables pour les projets “REST”
- un projet de services métiers et de persistence
- un projet de composants REST sécurisés (avec JWT)
- d’une application WEB développée avec Angular
- de la même application WEB (même écrans et fonctionnalités) développée avec VueJS
- de batch (simple en SQL et une autre avec JPA)
Les applications WEB sont simples (voire simpliste) et mettent en oeuvre des composants différents pour faire des tests :
- un formulaire Material
- l’internationnalisation avec des libellés venant d’une API
- une application PWA
- table Material
- …
4/ Tests
4.1/ Que tester
Les cas nominaux de tous les composants doivent être testés ainsi que les cas d’erreur principaux.
Aucune exigence n’impose une couverture de code particulière mais 80% est souhaitable pour tous les composants contenant de la logique (hors getter, setter, constructeur, code de programmation défensive, …)
Les composants métiers (Service, Repostitory et Entité) doivent être testés avec des tests d’intégration. Il n’est pas concevable de tester un système entièrement basé sur la notion de transaction et de requêtes SQL (Spring, Hibernate et la BDD) sans une connexion à une base de données et sans activer les commits.
Si certains composants métiers présentent une grande complexité, alors un test de granularité unitaire est tout à fait envisageable. Un tel composant n’existe pas pour le moment.
Les contrôleurs REST doivent être testés unitairement. Ces composants ne sont pas transactionnels et les services sont testés par ailleurs. Mais, pour bien vérifier le paramétrage et le code, il est nécessaire de réaliser le test des contrôleurs en démarrant un serveur WEB (l’adjectif “unitaire” utilisé plus tôt est donc discutable - cf. test de développement).
Les écrans de l’application sont testés en mode “bout en bout”. Selenium est utilisé pour piloter le navigateur et un jeu de données est utilisé pour initialiser le test. ATTENTION : les tests Selenium ne sont donc pas tous indépendants les uns des autres. Ce n’est pas une bonne pratique mais faire autrement avec un test de bout en bout est trop coûteux.
Avec quels outils
JUnit et TestNG sont tous deux des exécuteurs de tests. JUnit est utilisé dans les tests des composants métiers. TestNG, étant plus pratique à utiliser avec Mockito, est utilisé pour l’exécution des tests des contrôleurs.
Mockito est donc utilisé pour bouchonner les services métiers dans les tests des contrôleurs.
La classe utilitaire JdbcTemplate (fournie par Spring-jdbc) peut être utilisée dans les tests métiers afin d’exécuter simplement des requêtes SQL en base de données pour valider le contenu.
La classe utilitaire RestTemplate (fournie par Spring-web) peut être utilisée dans les tests des contrôleurs pour réaliser les appels HTTP simplement.
Selenium est une API très riche. La classe MyDriver rassemble les opérations usuelles utiles aux tests (il est tout à fait possible de l’enrichir).
Les sélecteurs à utiliser dans les tests Selenium sont tous rassemblés dans la classe Selectors. Tous les sélecteurs doivent être rassemblés dans cette classe.
Cette classe contient une hiérarchie de sous-classes structurée ainsi : NomDeLaPage / TypeDelements / selecteurElement. Exemple : Index.Button.CONFIRMER_SUPPRESSION
Toute modification d’une page HTML doit entraîner l’enrichissement de la classe Selectors avec le sélecteur permettant de sélectionner les éléments ajoutés/modifiés/supprimés.
5/ Règles de conception
5.1/ Persistance
Toute requête de recherche sans paramètre optionnel doit être codée dans un repository SpringData.
5.2/ Service
La gestion des transactions et des erreurs se traite au niveau des services qui sont les points d’entrée et de sortie des transactions.
5.3/ API
Les services ne sont exposés via l’API que s’ils sont utilisés par l’IHM.
La validation des paramètres d’entrée se fait dans le “contrôleur” et dans l’écran.
6/ Règles de développement
Les règles ci-dessous doivent être appliquées par tout développeur souhaitant participer à ce projet (non négociable). Par contre, il est toujours possible de discuter de la modification d’une règle.
6.1/ Langue
Les entités, les attributs et les méthodes sont nommés en français.
Les commentaire sont en français.
Les préfixes, suffixes et concepts inhérents au langage reste en anglais (get, set, is, iterator, …)
6.2/ Nommage
Les composants applicatifs sont suffixés en fonction de leur type :
- “Application” pour les configurations SpringBoot,
- “Exception” pour les exceptions,
- “DTO” pour les structures de données de transport,
- “Service” pour les services métiers,
- “DAO” pour l’accès à la persistance,
- “REST” pour l’exposition de service en REST
- et “Test” pour tous les tests
Les entités métier et les classes utilitaires ne sont pas suffixées mais doivent avoir des noms parlant (l’usage du nom d’un pattern est utile pour décrire l’usage/l’utilité du composant)
Les classes implémentant une interface sont suffixées par “IMPL”
Les noms de méthode commence par un verbe à l’infinitif
L’usage des Save Actions d’Eclipse est obligatoire pour conserver l’homogénéité du code (cf. petit tour d’Eclipse)
Le formatage des sources est celui par défaut dans Eclipse (version Oxygen) : 150 caractères par ligne (150 pour les commentaires) et indentation par tabulation.
Les membres sont triés systématiquement.
Les lignes ne contenant que des tabulations et/ou des espaces sont vidées.
Le mot clef “final” est placé sur toutes les variables affectées une seule fois et sur les paramètres.
Le mot clef “this” est utilisé systématiquement.
Les cast inutiles sont supprimés.
6.4/ HQL
Les requêtes HQL simples peuvent être écrites sur une seule ligne. Les plus complexes sont formatées pour être plus lisible. L’usage des commentaires “//” en fin de ligne est autorisé pour forcer Eclipse à conserver à la ligne la chaîne de caractère à concaténer.
Toujours définir par défaut l’attribut READ_ONLY à true sur une méthode chargeant des entités persistantes. Seules les entités nécessitant d’être “managed” doivent l’être (cf. documentation hibernate sur le cycle de vie des objets dans une session)
Ne jamais créer un lien entre deux entités en instanciant une entité et ne définissant que son ID. Toujours utiliser EntityManager.getReference
La gestion des transactions est faite via les annotations Spring. Les exceptions du projet sont runtime et déclenchent donc le rollback. Seuls les composants de type “Service” et “DAO” peuvent être transactionnels (par les “contrôleur”)
6.5/ Spring Data
Les requêtes sont, pour la quasi totalité d’entre elles, positionnées dans un Repository Spring Data. Elles sont donc dans les annotations d’une interface et non dans une classe.
L’usage de méthode default est interdit sur mon projet. Si je dois coder un algorithme, il doit être dans le service. Si la requête est complèxe (multi-critères optionnels par exemple), il faut créer une classe à part.
Astuces et penses-bêtes :
- ne jamais mettre de clause order by dans une requête si la requête est paginée (usage d’un paramètre de type org.springframework.data.domain.Pageable)
- toujours définir la requête countQuery d’une requête paginée si la requête contient un join fetch
6.6/ REST
Les méthodes de contrôleur REST retournant uniquement une chaine de caractères doivent retourner la dite chaine entre double quote.
7/ Processus de développement
7.1/ Gestion de configuration logicielle (GCL)
- Que comprend la GCL :
- Les sources applicatives et de test sont dans un repository GIT ;
- Le présent “guide du développeur” est lui aussi dans un repository GIT mais séparé (pas de gestion de version cohérente nécessaire) ;
- Le bug tracker a utilisé est celui du repository GitHub ;
- Les plans de test “métier” ne sont pas formalisés. Mais une partie d’entre eux sont automatisés avec Selenium.
- La gestion de version :
- une seule version existe pour le moment (branche ‘master’).
- si des POC sont réalisés, ils doivent l’être dans une branche dédiée
- aucun TAG n’est posé pour le moment (c’est une chose à faire prochainement)
7.2/ Commit
Les messages de commit doivent être explicites. Toute nouvelle fonctionnalité doit être commitée avec un message commençant par “[FEATURE]” (afin que le commit soit correctement affiché dans la page releaseNote de l’application).
7.3/ Industrialisation
7.3.1/ Outils
GitHub héberge une partie des outils du projet : repository GIT & guide du développeur, …
L’outil d’intégration continue utilisé est Jenkins (hébergé sur un serveur EC2).
La qualimétrie est réalisée avec Sonar (hébergée sur le site officiel en ligne).
Les relectures de code sont possibles avec GitHub mais ne sont pas utilisées actuellement (un seul développeur pour le moment)
7.3.2/ Processus
Quitte à faire un petit projet sympa, autant utiliser les outils correctement. Donc le processus de développement (même s’il est minimal) est piloté par un pipeline (cf. pipeline).
Le pipeline est lui aussi en GCL : dans le JenkinsFile
Le pipeline commence au commit du code et enchaîne les étapes suivantes : compilation, tests métiers, tests des contrôleurs, packaging, tests IHM, qualimétrie, promotion manuelle et mise en production
8/ Installation des environnements
8.1/ Sur le serveur unix
Le déploiement sur un serveur Unix demande la création
- d’un répertoire hébergeant l’application WEB dans un sous répertoire de /var/www/html.
- Attention à bien changer le root dans la configuration du build pour prendre en compte le nom du sous répertoire dans /var/www/html/.
- De plus, il faut donner les droits à l’utilisateur Jenkins d’écrire dans ce répertoire.
- Enfin, il faut modifier le fichier de configuration Apache pour permettre le chargement du WORKER :
Header set Content-Security-Policy "worker-src https://*.guillaumetalbot.com;"
- d’un répertoire hébergeant le Backend
- Le répertoire doit contenir des scripts de démarrage et d’arrêt (cf. sources de l’application)
- Le répertoire doit aussi contenir les fichiers de configuration propres à l’environnement (log4j2.xml et application.properties)
- De plus, il faut donner les droits à l’utilisateur Jenkins d’écrire dans ce répertoire pour le JAR, les logs et la bases de données (attention aux fichiers créés par un autre compte que Jenkins !).
- Il ne faut pas oublier d’ajouter les redirections dans la configuration Apache !!
Sujets non traités ici (pour le moment) :
- conception
- quels sont les outils de conception et/ou de modélisation ?
- quels sont les objectifs des modèles (compréhension, communication, …) et quelle est leur durée de vie ?
- règles de conception (programmation défensive, @designByContrat, modularité, …)
- jeu de données de test
- développement
- liste des frameworks disponibles, leur usage et le pointeur sur leur documentation
- qualimétrie obligatoire avec le site “online” (avec sa configuration imposée par la plateforme d’où les violations non corrigée qui ne le seront pas)
- HQL propre
- …
- industrialisation :
- aucune installation de poste automatique car seul l’IDE est nécessaire et l’application est autoporteuse
- IC = jenkins toujours à jour avec un pipelineAsCode (lien vers le blog sur le sujet)
- pipeline = git/compile/TU/TI/TA/qualimétrie/promotion/production
- à quand un second développeur et la mise en place des pullrequest et des revues de code ?
- roadmap :
- tag à la promotion (fin du développement au fil de l’eau et passage en mode paquet de code)
- …
9/ FAQ
- Erreur de sérialisation d’un attribut @OneToMany dans Jackson à cause d’une LazyInitializationException
- Utiliser la méthode MutableUtil.getMutable dans le getter
PSL
Professionnellement, j’ai découvert le SI de la Plateforme de Service en Ligne créé par la DILA.
A titre personnel, j’ai tenté de repenser les besoins et reconcevoir les solutions à partir de mes connaissances et une dizaine d’année plus tard.
Avec l’idée en tête de créer un système extrêmement paramétrable, j’ai tenté de constuire un prototype de “moteur” Angular capable d’afficher une saisie de formulaire. Le prototype m’a plu et j’ai continué, des années durant, le soir et le weekend, à reconstuire ce SI.
En voici le résultat :