jeudi 10 juin 2010

Intégration continue avec Hudson et Maven

Environnement


Avant de donner la recette pour la mise en oeuvre de hudson, nous
allons donner quelques définitions. En effet, certains termes
utilisé dans ce document ont un sens variable suivant le
contexte.

Précisons d'abord les rôles des différents
environnements :

  • Environnement d'Intégration : sert à
    valider manuellement que le le comportement du produit est
    identique sur les environnements de développement et sur la
    plateforme cible. L'environnement d'intégration doit être
    un clone des plateformes de production.

  • Environnement Intégration continue : sert à
    valider automatiquement que le le comportement du produit est
    identique sur les environnements de développement et sur la
    plateforme cible. L'environnement d'intégration doit être
    un clone des plateformes de production.

  • Environnement de Validation :
    sert à vérifier
    que le produit est conforme aux spécifications.


Jeu de test :
Ensemble de données nécessaires au passage d'un test

Test unitaire : Théoriquement
il s'agit d'un test vérifiant une exigence, mais dans ce
document, nous l'utiliserons dans son acception consacrée
test
Junit
.

Bénéfices de l'intégration
continue


Dans les configurations de développement JAVA« standard »,
le codage s'effectue sur Windows et l'intégration s'effectue
sur LINUX/UNIX, il est donc fréquent d'avoir des surprises au
moment de passer sur l'environnement cible, les environnements
d'intégration permettent anticiper les problèmes
techniques.
L'intégrateur identifie les dysfonctionnements et les
corrige. Malheureusement, dans la plupart des configurations projet,
personne n'étant affecté exclusivement à
l'intégration et les soucis d'intégration tendent à
être reléguées aux dernières tâches.

Au delà de l'effet de mode, le principal bienfait de
l'intégration continue sera d'améliorer la visibilité
de ces problématiques.
L’intégration continue valide automatiquement le
produit sur la plateforme cible.


  • Permet de détecter au plus tôt les problèmes
    de dépendance aux environnements : File System, Encoding,
    Case-sensitive, performances etc.
  • Permet de lisser le stress dans l'équipe (plus de
    pression dans les phases précoces, moins au moment de la
    livraison)

  • Il donne une aperçu de la qualité du produit au
    chef de projet et donne confiance au moment de la livraison
    .

Impacts structurants de l'intégration
continue


Contraintes de codage


L'ensemble des projets sur le référentiel de source
doit être compilable à tout moment.

Pour l'intégration continue, le développeur est
contraint d'écrire des tests unitaires.

Test unitaires

Dans un monde systématique, chaque exigence devrait être
vérifiée par un test unitaire, inversement, chaque test
unitaire devrait se mettre en relation avec une seule exigence.
Cependant, dans le monde réel, un test unitaire pourra être
associé à plusieurs exigences, une exigence pourra
n'être pas couverte... etc. In fine le développeur
arbitrera (mais avec un minimum d'expérience, cela se passe
bien. )
A chaque TU est associé un jeu de tests, mais aucune
hypothèse de données préalable ne peut être
faite. Que l'on parte d'une base totalement vidangée ou pleine
de donnée, le résultat du test unitaire doit être
le même. D'autre part, le séquence des TU ne doit pas
non plus conditionner le résultat.

Ressources



  • L’intégration
    requiert un serveur dédié pour hudson
  • Il faut une base de données
    par utilisateur

    (Elle peux se situer sur la machine de
    développement ou sur un serveur mutualisé)

Contrainte de conception



  • Il faut utiliser maven pour
    l'assemblage
  • Les test unitaires doivent être
    écrit avec Junit

Au quotidien



  • Il faut vraiment s’impliquer
    dans la supervision des builds et être vigilant tout au long
    du développement du produit : codage, intégration,
    validation
  • L'équipe doit s'organiser
    dans ce but, c'est-à-dire qu'il faut un responsable
    Intégration Continue (le même que le responsable GCONF)


Mise en oeuvre




  • Installer un serveur hudson
  • Planifier les tâches à des horaires où la
    machine n'est pas trop chargée

De The French Hack

De The French Hack

De The French Hack

mercredi 26 mai 2010

Transaction explicites sous Spring et JPA dans les applications Batch

Il m'a été difficile d'utiliser une application de traitement batch utilisant Hibernate, JPA. En utilisant des transactions explicite.

J'avais le message "org.hibernate.SessionException: Session is closed!"

Pour démmarrer le contexte transactionnel, j'ai utilisé les lignes suivantes


DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("MaTransaction");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/** pour démarrer le context transactionnel */
transactionManager.getTransaction(def);


Comment économiser de la mémoire :
- Faire des commit intermédiaires

Comment gagner de la vitesse :
- Faire des insertions et des select dans une table est une opération couteuse (car le recalcul des index prend de plus en plus de temps)

mardi 25 mai 2010

Changer le splash screen sur Ubuntu 10.4

http://maketecheasier.com/change-login-and-boot-screen-in-ubuntu-lucid/2010/05/13

mardi 4 mai 2010

Utilisation des curseurs dans Mysql


DELIMITER |
CREATE PROCEDURE updateTable()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE description_population_type2 TEXT;
DECLARE nom_monentite_type2 CHAR(50);
DECLARE cur1 CURSOR FOR select nom_monentite, description_population from sp_monentite where id_gp=2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO nom_monentite_type2, description_population_type2;
IF NOT done THEN
UPDATE sp_monentite
SET description_population = description_population_type2
WHERE nom_monentite_type2=nom_monentite AND id_gp=1;
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END|


Procédure stockée

mardi 13 avril 2010

Guide de revue de code

Ci dessous un memorandum sur les points qui ont été mis en défaut sur des projets réel avec des conséquences réelles sur les charges et le planning du projet.

Chacun de ces points est à mettre en oeuvre le plus tôt possible, plus le temps passe et plus le coût est élevé pour revenir dans une démarche de qualité.

Bonne pratiques de développement


Structuration des projets


Un projet devrait contenir un minimum de dépendances entre les modules. La seule raison motivant un découpage de garantir l'indépendance des cycles de vie. Un projet IHM possédants des script de traitement par lot devrait être structuré de la manière suivante :

- Un projet-parent
- Un projet dao + business + service
- Un projet IHM (war)
- Un projet batch
- Un projet factorisant le code de test (Constitution de jeu de test)
- Un jeu de test de référence
- Un jeu de test restreint
- Un jeu de test à volumétrie normale

Recommandations


Utiliser des interfaces uniquement si nécessaire, quand il existe une probabilité réelle qu'une interfaces ait plusieurs réalisations.
Ne pas se servir des exceptions pour remonter des codes d'erreurs.

Bonnes pratiques de codage de tests unitaires


Un test unitaire doit pouvoir partir d'une base vierge
Dans les tests junits dérivés de spring, vérifier que les méthodes d'extraction communes sont dans la méthode onSetUp().
Penser à valider le programme par des jeux de test importants. Si certains tests génèrent des erreurs en occupant trop de mémoire, il vaut mieux ne pas masquer le problème en augmentant la taille mémoire sur la machine de développement. Sur le long terme, il vaut mieux résoudre résoudre le problème par la conception sans utiliser la puissance du matériel.

Bonnes pratiques d'écriture


La manière de coder peut améliorer la reprise du code dans le cas de maintenance. Il est possible d'utiliser des outils de type checkstyle ou PMD. Toutefois, ces outils ne sont pas toujours pertinents parce que trop verbeux.
Formater le code de manière homogène en utilisant un outils de formatage automatique
Mettre des commentaires quand c'est nécessaire
Sur la couche DAO : vérifier que les noms de méthode sont cohérents entre eux
Vérifier que les noms de variables permettent de deviner leur contenu
Vérifier que les tests unitaires donne des messages explicite en cas de plantage (pas de fail sans argument)
Ne pas utiliser les séquences : « ? : » pour les tests if. Toujours mettre des crochets

lundi 22 mars 2010

Merger à l'aide de SVN

Utilisation des patch dans SVN



Avec SVN, pour reporter les modifications d'une branche vers une autre. Il existe plusieurs méthodes :

  • La commande merge fournie avec SVN (Méthode recommandée): Cette méthode ne s'applique que si les fichiers modifiés sont connecté au référentiel SVN, mais ce moyen est le plus simple.
  • Méthode utilisant l'IDE eclipse : Elle présente des avantage pour la représentation de changes. Contrairement à ce que l'on pourrait croire, il s'agit rarement de la méthode la plus simple, en effet le fourmillement d'options sur une GUI entraine une certaine confusion.
  • Méthode basée sur les fichiers de patch : cette méthode utilise le standard udiff et peux s'appliquer sur des fichiers n'étant pas connectés au référentiel de source. Cette méthode n'est pas automatique mais elle est souple.

Pour illustrer un report nous allons utiliser l'exemple d'un report d'une correction de bug sur la branche en maintenance (lot 1) vers la branche en cours de développement (lot 2), la branche lot 2 est en cours de développement, c'est donc le tronc.




De The French Hack


Cette opération s'effectue en 5 temps :

  • Récuppération du numéro de révision
  • Checkout de la branche sur laquelle le report est effectué
  • Report des modifications et fusion
  • Résolution des conflits
  • Commit

Méthode en ligne de commande utilisant subversion (Méthode recommandée)



La première opération consiste à repèrer dans l'historique la version à partir de laquelle nous souhaitons effectuer le report. Nous pouvons nous baser sur les dates de modifications, les commentaires, les dates de création de branches... tou ce qu'on veut !

bash> svn log -r{20100401}:HEAD http://svnserver/my-product/developpement/branches/my-module-dao-lot1

Récuppération du numéro de révision


Problème des droits acces
------------------------------------------------------------------------
r3389 | zegugusse | 2010-04-28 12:15:38 +0200 (mer, 28 avr 2010) | 1 line

Le montant des couts pour que les valeurs jusqu'a 9 999 999 999 puissent etre stockées et non arrondies
------------------------------------------------------------------------
r3390 | zegugusse | 2010-04-29 09:25:29 +0200 (jeu, 29 avr 2010) | 1 line

Problème des droits
------------------------------------------------------------------------
r3394 | zegugusse | 2010-05-04 09:12:01 +0200 (mar, 04 mai 2010) | 2 lines


------------------------------------------------------------------------
r3394 | ungusse | 2010-05-04 09:12:01 +0200 (mar, 04 mai 2010) | 2 lines

Création des branches lot2

------------------------------------------------------------------------
r3397 | ungusse | 2010-05-04 09:12:33 +0200 (mar, 04 mai 2010) | 1 line


------------------------------------------------------------------------
r3528 | ungusse | 2010-05-26 12:09:30 +0200 (mer, 26 mai 2010) | 2 lines

Ajout des codes d'erreur

------------------------------------------------------------------------
r3574 | lotrgusse | 2010-06-01 15:25:34 +0200 (mar, 01 jun 2010) | 1 line

Ajout du libellé long . Change D76.
------------------------------------------------------------------------
r3577 | zegugusse | 2010-06-01 16:09:25 +0200 (mar, 01 jun 2010) | 1 line

Defect Client D58
------------------------------------------------------------------------
r3579 | lotrgusse | 2010-06-01 17:35:41 +0200 (mar, 01 jun 2010) | 1 line

Modification du comportement de l'écran de sélection des cibles.
------------------------------------------------------------------------
r3583 | zegugusse | 2010-06-02 12:22:50 +0200 (mer, 02 jun 2010) | 1 line

Defect Client D58
------------------------------------------------------------------------


Checkout de la branche sur laquelle le report est effectué




svn co http://svnserver/my-product/developpement/branches/my-module-branch my-module-dao-trunk-workcopy


Report des modifications et fusion


Maintenant, nous allons reporter les changements intervenu sur la branche my-module-branch entre les versions 1000 et la HEAD


svn merge -r1000:HEAD http://svnserver/my-product/developpement/branches/my-module-dao-lot1 my-module-dao-trunk-workcopy

  • Le premier paramètre (http://svnserver/my-product/developpement/branches/my-module-dao-lot1) indique la branche d'ou est effectué le rapport
  • Le second paramètre (my-module-trunk-workcopy) est le chemin du repertoire sur lequel le report est appliqué



Voici le résultat :

[hudson@vm01 ~]$ svn merge -r2650:HEAD http://svnserver/my-product/developpement/branches/my-module-dao-lot1 my-module-dao-trunk/
U my-module-dao-trunk-workcopy/src/sql/data/load-ref-dev.bat
U my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/service/common/impl/UtilisateurServiceImpl.java
C my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java
U my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/business/projet/impl/ProjetBusinessImpl.java
G my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/business/objectif/impl/ObjectifBusinessImpl.java
C my-module-dao-trunk-workcopy/pom.xml



  • U indique que nous avons procédé à un update
  • G indique que nous avons procédé à une fusion sans conflit
  • C indique un conflit


Ensuite nous pouvons observer le resultat à l'aide de la commande : svn st


[hudson@vm01 ~]$ svn st my-module-dao-trunk-workcopy
? my-module-dao-trunk-workcopy/pom.xml.fusion-gauche.r2650
? my-module-dao-trunk-workcopy/pom.xml.courant
? my-module-dao-trunk-workcopy/pom.xml.fusion-droit.r2862
M my-module-dao-trunk-workcopy/src/sql/data/load-ref-dev.bat
M my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/service/common/impl/UtilisateurServiceImpl.java
? my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java.courant
? my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java.fusion-droit.r2862
? my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java.fusion-gauche.r2650
C my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java
M my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/business/projet/impl/ProjetBusinessImpl.java
M my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/business/objectif/impl/ObjectifBusinessImpl.java
C my-module-dao-trunk-workcopy/pom.xml


  • M indique que le fichier est modifié (Un check in est nécéssaire)
  • C indique un conflit (Il est nécessaire résoudre)


Résolution des conflits


Avec un éditeur résoudre les conflit dans my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java puis indiquer que le conflit est résolu


vi my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java
svn resolved my-module-dao-trunk-workcopy/src/main/java/com/mycompany/jt/dao/BuildingSecondaireDAO.java

Commit


Pour finaliser, il faut commiter nos modifications

svn ci my-module-dao-trunk-workcopy/



Méthode se basant sur les fichiers de patch



Sous UNIX, une ligne de commande génère ces fichiers de patch :

svn diff http://svnserver.mycomp/my-product/developpement/trunk/my-project -rN:M

N est la version d'origine M est la version cible.

Pour appliquer ces patchs, se plaçer à la racine du projet à patcher, utiliser la commande :

patch -p0 >mypatchfile

où p est la profondeur


Méthode sur eclipse



Contrairement à ce que l'on pourrait croire, l'utilisation d'eclipse peut être plus difficile que celle de la ligne de commande.


  • Se placer sur la branche sur laquelle on souhaite effectuer les reports.





  • Choisir l'ensemble des révisions à reporter. Autrement, l'option starts from copy reporte l'ensemble des modification depuis la création de la branche (ce qui peut n'être pas adéquat dans le cas où la branche à subi plusieurs recopies)







  • Preview permet de voir quelle sont les révision concernées :








jeudi 7 janvier 2010

Mysql en case insensitive sur linux Red hat

Dans le fichier my.ini, sous la section mysqld, ajouter la ligne suivante :

lower_case_table_names=1