quel framework de BDD pour .Net et bien adapté à MVC?
Juin 19th, 2010permettez moi tout d'abord de vous inviter à parcourir la présentation que j'ai déroulée au SigmaT 14 , qui fut un peu mon appel du 18 Juin à moi
http://www.slideshare.net/guillaumeagile/to-test-or-not-to-test
"les informaticiens parlent aux informaticiens, venez rejoindre les partisants IT libérés, venez faire du Test Comportementaliste! (BDD)"
vous pouvez trouverez moultitude de références sur le sujet en anglais , comme par exemple (et pour faire court) http://jockeholm.wordpress.com/2010/02/14/combining-tddbdd-with-ddd/
ceux qui comme moi, aiment partir de la théorie et arriver rapidement à la pratique, et qui on fait le choix de .Net, ont surement eu à se poser beaucoup de questions quant au choix de l'outil/framework de BDD/ATDD .
Si le choix semble plus évident pour la communauté Java et Ruby, qui est beaucoup plus active et unanime sur le sujet (ils ont Cucumber et RSpec, eux!), ceux qui travaillent en .Net peuvent se sentir un petit peu perdu, pour ne pas dire découragés.
Alors, voici pour se mettre rapidement et efficacement en selle, quelques liens rapides vers de bons articles en Français (et un peu en Anglais) qui explorent ces technos en détails (et avec tutoriels bien fait):
GHERKIN (sachez avant tout, que tout est centré sur ce langage, qui n'est pas un langage de développement mais un DSL prêt à l'emploi):
http://ryanlanciaux.com/ryanlanciaux/post/Gherkin-style-BDD-testing-in-NET.aspx
http://wiki.github.com/aslakhellesoy/cucumber/gherkin
MSPEC:
http://blogs.developpeur.org/tja/archive/2010/02/05/tests-suite-des-tests-unitaires-avec-mspec.aspx
NBEHAVE:
http://blogs.developpeur.org/tja/archive/2009/12/08/tests-tester-votre-site-asp-net-mvc.aspx
http://blogs.developpeur.org/tja/archive/2010/01/22/tests-nbehave-et-asp-mvc-2-suite.aspx
http://blog.developpez.com/bruno-orsier/p8428/bdd/nbehave-a-la-cucumber/
http://pebblesteps.com/post/Behavior-Driven-Development-with-NBehave.aspx
Cucumber/IronRuby:
http://blog.developpez.com/bruno-orsier/p8440/bdd/cucumber-avec-ironruby-ca-marche/#more8440
Cuke4Nuke :
http://gojko.net/2010/01/01/bdd-in-net-with-cucumber-cuke4nuke-and-teamcity/
http://stackoverflow.com/questions/2113936/cuke4nuke-or-specflow
SPECFLOW:
http://blogs.developpeur.org/tja/archive/2010/01/25/tests-ma-qu-te-bdd-continue-tests-unitaires-avec-specflow.aspx
http://www.specflow.org/specflow/technical-concepts.aspx
http://blog.stevensanderson.com/2010/03/03/behavior-driven-development-bdd-with-specflow-and-aspnet-mvc/
http://www.codeproject.com/KB/architecture/BddWithSpecFlow.aspx
quant à moi, je vous donnerai bientôt mon avis détaillé sur celui qui me semble être le meilleur d'entre eux...
l'Open Source rendra-t-il la planète plus verte à lui tout seul?
Avril 14th, 2010désolé messieurs-dames, je m'inscris en faux. Le seul fait d'utiliser et d'imposer l'Open Source est selon moi tout sauf efficace pour lutter contre le gaspillage, le réchauffement climatique, la réparatition des richesses, l'amitié entre les peuples, le green washin', le social Washin'.... et tout autre concept "bankable".
Pour y voir plus clair, et pour calmer ce débat, si ancien et si houleux, il n'est pas superflu de revenir à quelques définitions.
Impact environnemental (ou trace carbone) généré par un logiciel: tout surplus de calcul (temps CPU), d'espace de stockage (Octets en Kilo, Mega, Giga, Tera, Zeta...) et de transfert de données (flux d'Octets par unité de temps) lors de l'utilisation du dit logiciel qui aboutit à la consommation d'électricité, au réchauffement (refroidissement des machines, des data centers), à la fabrique d'équipements (réseaux, serveurs, postes, écrans) à base de composants polluants (métaux lourds, arsenic, retardateurs de flamme et autres poisons) nécessaire à sa mise en oeuvre.
Ainsi posé, il m'apparait difficile de valider que Open Source => Réduction de l'Impact Environnemental de l'Informatique.
la source de tous les maux?
Pourquoi en serait-il autrement avec le logiciel?
Principes de conception durable (et application au génie logiciel)
Bien que d'un domaine d'application à l'autre, certains concepts ne puissent pas être translatés, voici quelques principe généraux applicables au logiciel:
- Low-impact materials:
choisir des composants et des sous-systèmes qui ont eux même mesuré la réduction de leur impact (malheureusement je ne connais aucun logiciel qui le propose à ce jour) (1) - Energy efficiency:: efficacité énergétique
- efficacité en SLOC: moins de ligne de code = moins de risque de bugs mais aussi de fonctions inutilisées (moins de stockage pour ces fonctions et moins de CPU pour des calculs dont le résultat n'est pas exploité in fine). C'est aussi un facteur indiquant qu'il y a eu refactoring et que les algorithmes sont certainement optimisés (à vérifier avec ce qui suit).
- efficacité en cycles CPU: pour chaque feature, mesurer le nombre de FLOP consommé pour une action (utiliser la base des User Story) donnée.
- efficacité en stockage: mesure en Octects de la quantité de stockage nécessaire à une feature ou une opération.
- efficacité de la persistence et du rappatriement de données: calculer les cycles CPU pour faire une requête, et calculer l'encombrement mémoire (ou sur les flux) des informations remontées depuis le mécanisme de stockage (objectif avoué: bannir le "select * from"). Penser aux atouts (et faiblesses) du NoSql.
- optimisation l'encombrement sur le réseau: calcul du nombre d'informations en transit entre le client et le serveur (web ou autres) en terme de débit moyen en fonction de l'usage (une fois de plus les User Story sont un bon point d'entrée). Format condensé des données (préférez JSON à XML). Pertinence des données échangées (supprimez le superflu). Penser "Just In Time" (la bonne information au bon moment): l'utilisateur n'est pas une machine, pas la peine de lui afficher des tonnes d'informations qu'il ne lira pas.
- efficacité en SLOC: moins de ligne de code = moins de risque de bugs mais aussi de fonctions inutilisées (moins de stockage pour ces fonctions et moins de CPU pour des calculs dont le résultat n'est pas exploité in fine). C'est aussi un facteur indiquant qu'il y a eu refactoring et que les algorithmes sont certainement optimisés (à vérifier avec ce qui suit).
- Quality and durability:
- qualité: absence de bug prouvée: mesure du taux de couverture du code par des tests unitaires qui ont échoué mais qui n'échouent plus.
- durabilité: présence de tests unitaires ayant un rôle évident dans la surveillance de la non-regression et couvrant l'ensemble des fonctions.
- Design for reuse and recycling: c'est la fameuse ré-utilisabilité du logiciel, qui est trop souvent soit un voeux pieux, soit un graal jamais atteint
- Interfaces Publiques Documentées: soit des APIs, soit des Web Services, soit une interface REST, mais toujours documentées avec des exemples concrets d'utilisation (guide sous forme de HOW-TO)
- Ergonomie des API (ou Services): les parties d'inter-communications (interfaces) doivent être très sérieusement pensées dans un souci de non-gaspillage de ressources et de facilité d'utilisation. Pour être viables, elles doivent pouvoir être utilisées (consommées) sans dépenser de surplus d'énergie, c'est à dire sans avoir à passer 3 heures à comprendre comment ca marche, ou à devoir fournir au moment de l'appel des tonnes d'informations qui ne seront peut être même pas exploitées (penser au coût de récupération des données).
- voir mon article sur l'érgonomie des API http://docs.google.com/Doc?id=dhp3ggmx_38f58b3d
- commercial 'afterlife'. dans 10 ans, votre bout de logiciel devrait encore pouvoir servir à d'autres, même s'il n'a plus vocation d'être commercialisé
- Pérénité: votre système ou sous-système doit pouvoir être adapté à tout changement de l'environnement (évolution des échelles, les mesures, conversions, valeurs fluctuantes...).
- Sustainable Design Standards : on peut espérer (ou rêver) dans un avenir proche voir l'émergence d'un éco-label pour le développement logiciel durable. Celui-ci énoncerait des métriques précises et des niveaux de seuil en dessous desquels on peut considérer que le développeur du logiciel a fait des efforts significatifs visant à améliorer la qualité de son produit et la réduction de l'empreinte énergétique.
- Biomimétisme: inspirez vous de ce que la nature fait quand vous devez inventer un algorythme ou un processus. Ce qui a survecu pendant des millénaires est forcément viable (principe de Darwin).
- Service substitution: être capable de changer le mode de consommation des services sous jacents (stockage, services bancaires, services de transaction, d'authentification, de sécurité, de cache...) et se tourner au fur et à mesure qu'ils apparaissent vers des systèmes offrant les même services mais avec une utilisation des ressources minimisée par unité de consommation (par User Story par ex.) Ceci requiert d'avoir mis en place une solide architecture de couches découplées dans le produit logiciel.
- Renewability: Renouvelement du système: votre code devrait pouvoir se renouveler lui-même et offrir de nouveaux services plus efficaces et moins cher quand ceux-ci seront disponibles.
- Eliminer le concept de déchet: le déchet dans le logiciel ce sont les fonctions (features) qui ne servent à rien. Et le code mort (unreachable code). Et bien sur, pas une ligne de code sans tests!
- Recherche de l'amélioration constante par le partage de la connaissance: encourager la communication directe entre les clients (consomm'acteurs) et développeurs (producteurs) du logiciel, mais aussi entre les responsables d'équipes, de projets, d'entreprises, les DSI, permettra de lier développement durable sur le long terme , responsabilité éthique et satisfaction des clients.
- Connaitre et comprendre les limites de son propre design (vertu de la sagesse).
(1) quant au choix des sous-systèmes sur lesquels va se reposer tout ou partie de votre solution, qu'il s'agisse de bouts de code récupérés, d'objets ré-utilisables, APIs, services tiers, Frameworks ou librairies, Open Source OU PAS!!! soyez intransigeant et évaluez les points suivants auprès de votre fournisseur:
- niveau d'abstraction: la vision que l'on peut extraire à la lecture des contrats de service
- style d'apprentissage: le niveau de connaissance requis et le temps d'apprentissage pour être efficace en utilisant ces services/interfaces/objets
- étapes de travail: combien de taches de programmation sont accomplies en une étape d'appel d'opération
- évaluation progressive: est-il possible de (mieux) comprendre comment marche le service au fur et à mesure de son utilisation.
- portée des engagements: le nombre de décisions que le développeur doit prendre dans un scénario impliquant l'utilisation de ce service, et leur portée.
- pénétrabilité: comment l'exposition du service permet d'explorer, analyser et comprendre le métier sous-jacent et l'effort qu'a à faire le développeur pour récupérer les informations dont (le service) a besoin pour fonctionner correctement.
- viscosité: les barrières rencontrées et les changements (dans votre conception initiale) que va induire l'utilisation de ce service.
- consistance: voir en détail l'article http://docs.google.com/Doc?id=dhp3ggmx_38f58b3d
- expressivité du modèle: comment apparaissent les relations entre les opérations entre elles, et les services entre eux également.
- alignement avec le domaine/métier: évidement un aspect essentiel dans l'évaluation d'un service.
- résilience: capacité à fonctionner en mode dégradé et à se remettre en état de fonctionnement
- découplage (visibilité des dépendances): la nature et la complexité des systèmes externes (objets, librairies, services, framework) nécessaire au fonctionnement de ce système, et la capacité à les changer sans toucher au code source (c'est à dire laisser le choix de la dépendance au consommateur du système et non à l'imposer).
Qui se soucie de l'empreinte environnementale d'un logiciel?
en attendant le BDD... Tester une application Asp.net MVC en 10 minutes
Février 9th, 2010Lien: http://bit.ly/aX5vsU
pour ceux qui veulent mettre en place des tests rapidement et efficacement sur une application Asp.Net MVC... voici une version courte de mon précédent article.
A l'essentiel cette fois ci, ou comment mettre en oeuvre une politique de tests unitaires qui marche, et qui fait des vrais tests!
1) choix des fra mework
2) tests des vues
3) tests des contrôleurs
4) isoler (mock) les contrôleurs de leur partie métier (domaine)
5) inversion de contrôle pour fonctionner en test et hors test sans rien toucher
le détail est à lire ici:
Bien Tester une application Asp.net MVC
Janvier 21st, 2010Lien: http://docs.google.com/View?id=dhp3ggmx_168c5md3p52
Bien Tester ASP.Net MVC 1.0
Genèse
ASP.Net MVC est né avec plein de bonnes résolutions, et notament celle d' enfin permettre du test unitaire sur les applications Web programmées avec le framework.Net .
Je dis "enfin" car le Test ne passionne pas les foules, et pas vraiment les développeurs, encore moins les responsables ou les clients qui voient en lui une perte de temps ou source de coûts supplémentaires!
Evidemment - et paradoxalement- nos clients (ou parfois chefs de projets) aimeraient bien voir leurs applications garanties exempte de tout défaut, et donc testées, mais bien souvent n'imaginent pas que cela est possible à faire à moindre coût et par un automate.
Comme ils croient surtout que cela coûte trop cher (ou trop de temps) ils font donc passer à la trappe cette étape, qu'ils rejettent d'ailleurs -à tort- en fin de planning alors qu'elle devrait prendre place dès le tout début du projet en se fondant dans les spécifications (pour en diluer le coût).
Pour ce qui est des technologies .Net, on ne peut pas dire que le test ait été placé au coeur de la plateforme. Il a fallu tout de même attendre la version 4 du framework pour réaliser la notion de "code contract", notion omni-présente dans des langages comme Eiffel dont s'inspire pourtant largement C#.
Pour ce qui est de la programmation Web sur la plateforme Microsoft, les WebForms (ASP.Net classique) étant intestables dans leur coeur, il fallait introduire soi-même le pattern MVC, celui par qui le test est possible, ou utiliser un framework additionnel (Monorail par exemple, donc j'avais parlé ici il y a quelques années http://www.castleproject.org/monorail/index.html )
Heureusement, et presque 10 ans après l'apparition d'ASP.Net, Microsoft rend officiel l'utilisation du pattern MVC. Il était temps! Mais que de retard accumulé par rapport aux autres plateformes!
Aidé par un puissant site de présentation et d'aide aux développeurs ( http://www.asp.net/mvc/ ), les développeurs vont enfin pouvoir sortir du modèle "dictatorial" des Webforms et retrouver des façons de programmer le web plus "dans les normes", ou du moins, plus proches des autres frameworks (JSF, RubyOnRails, PHP, etc...)... et pouvoir enfin envisager de tester facilement et sereinement!
Pourtant, trouver des bons exemples de code de tests (TDD) pour ASP.Net MVC, relève du parcours du combattant: code obsolète, différentes releases de ASP.Net MVC, examples incomplets, y compris dans la doc officielle (et quand ca compile, on peut s'estimer heureux), informations contradictoires, besoin d'utiliser à la fois des Mock-ups et de de l'injection de dépendance.... de quoi décourager le plus motivés des adeptes du TDD comme moi.
Quasiment tous les articles qui datent de 2008 sont obsolètes (par exemple http://dotnetslackers.com/articles/aspnet/ASPNETMVCFrameworkPart2.aspx ) mais ils contiennent des idées qu'il faut assimiler.
Indispensable, la classe utilitaire donnée par Scott H. mais qui compile pas :((( http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
... que d'embuches!
Quand on sait que l'approche TDD (et BDD) [Test Driven Development et Behavior Driven Development ] est la seule qui permette de GARANTIR qu'un logiciel est conforme à ce qu'on attend de lui (via l'écriture de spécification formelles), on a besoin d'y voir clair dans les tests.
Alors voici un article en français qui explique tout, simplement (j'espère), et dont les exemples compilent!
1 - Que faut-il pour tester?
un framework de test est indispensable. Mais lequel choisir? il y en a tellement....
pour comparer d'un point de vue pratique, vous pouvez consulter cette page:
http://xunit.codeplex.com/wikipage?title=Comparisons
mais chacun a ses préférences... difficille de faire un classement objectif et trouver des critères de notations entièrement acceptés par la communauté.
Pour ma part, j'ai choisi xUnit, uniquement pour sa simplicité
http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html
voici quelques unes de ses caractéristiques:
· Single Object Instance per Test Method.
· No [SetUp] or [TearDown].
· Aspect-Like Functionality.
· Reducing the Number of Custom Attributes.
· [TestFixture] was removed entirely, so tests can be anywhere.
· [Ignore] is expressed using the Skip= parameter on [Test]
· [ExpectedException] was replaced with Assert.Throws.
· [TestFixtureSetup] and [TestFixtureTearDown] are instead expressed as implementations of an interface (ITestFixture).
· Support for IDisposable was added for tests.
2 - Tester, tester.... oui mais tester quoi?
Une application, qu'elle soit Web ou pas, est un ensemble composite.
Il y a multitude de choses qui s'y passe.
Quand on n'utilise pas de pattern et qu'on ne se pré-occupe pas d'architecture logicielle, tout est mêlé dans un code "spaghetti", souvent dans peu de fichiers qui font chacun des milliers de lignes. Dans ce cas, on va avoir beaucoup de mal d'effectuer des tests clairs.
Une Séparation des Responsabilités dans le code (SoC: Separation of Concerns), une architecture N-tiers, une approche Domain Driven, un couplage lâche, une architecture bien pensée, sont évidemment les pré-requis d'un bon projet guidé par les tests (Tests Driven Development).
Le pattern MVC va beaucoup nous aider, puisqu'il sépare le code de la vue, de celui du contrôleur, et du modèle.
Tester la vue en elle même
Pour ce qui est de tester le contenu d'une page HTML, qu'une zone de texte soit bien remplie par la bonne valeur, que la bonne CSS s'applique ou que le nombre d'éléments dans une boite déroulante soit conforme à ce que l'on attend, le Unit Testing n'est pas vraiment l'outil idéal.
Quoiqu'il existe des frameworks qui ont tenté de le faire : http://nunitasp.sourceforge.net/ projet abandonné, ou http://htmlunit.sourceforge.net/ mais pas de portage .Net à ma connaissance.
Il existe malgré tout des outils de tests qui agissent directement sur l'IHM et donc dans notre cas sur le navigateur Web , avec des capacités de comprendre ce qui se passe sur la page HTML (à l’aide de notre ami JQuery) comme le très puissant Selenium IDE ( http://seleniumhq.org/ ) qui va vous générer le code NUnit de test des pages Html à intégrer dans votre solution .Net. Malheureusement vous serez dépendant d’un serveur Web pour effectuer vos tests, et le principe d’isolation des tests unitaires n’est pas respecté.
En attendant la solution qui comble la brèche…
Tester qu'une vue s'affiche bien
C’est assez trivial mais c'est un début :
|
[Fact] public void ReturnsViewResultWithDefaultViewName() { // Arrange var controller = new HomeController();
// Act var result = controller.Index();
// Assert var viewResult = Assert.IsType<ViewResult>(result); Assert.Empty(viewResult.ViewName); } |
Cela permet de vérifier que vous n'avez pas fait de grosses erreurs dans le montage de votre solution Asp.Net MVC. Malheureusement ca ne teste pas des erreurs éventuelles dans le fichier de vue (.aspx)
Notez au passage le tryptique classique d'une méthode de test 1)Arrange 2)Act 3)Assert.
Si votre contrôleur fait passer des bouts de données à la vue par l'intermédiaire du dictionnaire ViewData , il vous suffira de rajouter une ligne:
Assert.Equal("Welcome to ASP.NET MVC!", viewResult.ViewData["Message"]);
Toujours trivial. Et relativement peu utile.
La bonne pratique est d'utiliser une vue fortement typée, ce qui donne quelque chose comme ca dans l'entête de la déclaration de votre vue:
|
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ManagePassword.Domain.OperationResult>" %> |
ManagePassword.Domain est la librairie de domaine de notre application, et OperationResult est l'objet Modèle (au sens MVC) qui va transiter entre la vue et le contrôleur.
Notre test pourra déjà s'assurer que le contrôleur renvoie bien un objet de ce type là.
|
// ASSERT Assert.NotNull(results); Assert.NotNull(results.ViewData.Model); var res = Assert.IsAssignableFrom<OperationResult>(results.ViewData.Model); |
L'idée d'avoir un modèle déterminé (et donc fortement typé) afin de pouvoir passer de multiples valeurs et tester ce que le contrôleur va retourner à la vue.
Par exemple, on a souvent besoin d'une page qui fait le résumé de l'opération qui vient d'être demandé, et un modèle simple (mais récurrent) pourrait être:
|
public class OperationResult { public bool isOk; public string errorMessage; } |
Notre test va pouvoir porter maintenant sur les membres du Model, et donc faire plus de vérifications.
|
// ASSERT Assert.NotNull(results); Assert.NotNull( results.ViewData.Model); var res = Assert.IsAssignableFrom<OperationResult>(results.ViewData.Model); Assert.Equal(false, res.IsOk); |
Tester les redirections
Une redirection peut avoir lieu dans votre contrôleur, la tester permet de savoir par quel point ^de code le contrôleur a terminé son exécution. Pour cela le code de test ressemblera à ceci :
|
///ACT var results = controler.ChangePassword(userInfo) as RedirectToRouteResult;
// ASSERT Assert.True(controler.ViewData.ModelState.IsValid); // permet de tester que c'est bien un RedirectToRouteResult qui a été retourné (à cause du AS plus haut) Assert.NotNull(results); |
La ligne 1) ne plantera pas au cas où le code du contrôleur ne renvoi pas un objet de redirection ( ). Par contre Assert.NotNull(results); génèrera un échec du test car en cas d’echec du cast par AS, la variable contient le pointeur vers Null.
Pour rappel, une méthode de test ne doit attendre qu’un seul comportement possible.
Si vous voulez tester le cas où le contrôleur ne fait pas d’indirection (et renvoi des valeurs via le modèle), écrivez alors une autre méthode de test pour ce cas là. Attention à ne pas mettre de logique IF… ELSE… dans une méthode de test. Car cela est banni.
Dans la vraie vie, le but du programme est de faire en sorte que le Contrôleur appelle un (ou plusieurs) objets du domaine avec un minimum de logique (car la logique doit être dans le domaine). Le contrôleur s’occupe de la logique nécessaire pour préparer l'affichage (et donc le Modèle pour alimenter la vue), et c'est de cela dont il va falloir maintenant s’occuper.
Tester le contrôleur tout seul
Comme je le disais plus haut, la meilleure pratique nous conseille de déporter la logique du domaine (que l'on appelle souvent Métier en France) de l'application.
Hors, dans une démarche de test, la meilleure pratique est de ne tester d’une seule chose à la fois (isolation du test).
Si nous testons le contrôleur, nous devons ne tester que les appels de code dans son corps et non pas tous les objets dont il dépend et/ou auxquels il fait appel.
Il va donc falloir « débrancher » le Contrôleur de tout ce qui pourrait parasiter le test.
Comment faire sans écrire du code compliqué, et surtout sans toucher au code du contrôleur qui doit être transparent au test ? On ne doit pas changer le code de ce qui doit être testé pour le rendre testable ! Sinon le test est biaisé.
Les 2 choses typiques à débrancher sont : le ou les objets de domaine (ou système d’accès aux données), et le contexte sous-jacent au contrôleur (routage, requête http, contexte session, etc.).
Pour ce dernier, ASP.Net MVC est assez bien fait et les dépendances en place n’empêchent pas les tests de fonctionner en isolation, c'est-à-dire sans la présence d’un serveur HTTP.
Ceci dit, si on a besoin de tester le comportement d’un contrôleur en fonction de ce qui peut se passer au niveau Requête HTTP par exemple, on a la possibilité de fournir un faux contexte HTTP.
Vous trouverez de quoi réaliser ceci avec une classe d’aide aux tests, que vous devrez intégrer dans le projet de test : MvcMockHelpers
Vous en trouvez le code ici : http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
Elle vous propose (entre autres) un FakeHttpContext que vous brancherez à votre contrôleur avec une méthode d’extension, comme celle ci :
|
controler.SetFakeControllerContext(); |
Cette classe repose sur un framework de Mock-up. Le code donné fonctionne avec différentes librairies : RhinoMocks, TypeMock ou Moq.
Personnellement j’ai choisi Moq, car c’est le plus « fluent » au niveau API, sans être abscon, et celui qui a la syntaxe la plus claire pour spécifier le comportement des bouchons, mais nous allons le voir plus loin.
Le seul (petit) problème c’est que cela peut ne pas compiler. Il vous faudra chercher un certain moment sur le net avant de trouver ce « hack » :
http://stackoverflow.com/questions/205644/error-when-using-extension-methods-in-c
et qui vous conseille d’ajouter ces quelques lignes de code au fichier dans lequel vous aurez mis le MvcMockHelpers:
|
namespace System.Runtime.CompilerServices { /// <summary>/// to avoid the following error: Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' /// </summary> public class ExtensionAttribute : Attribute { } } |
Les méthodes d’extension SetHttpMethodResult et SetupRequestUrl vous seront bien utiles pour tester le comportement de votre contrôleur quand l’invocation se fait par une méthode HTTP GET ou HTTP POST, ou si son code vérifie l’URL demandée.
Bouchons à la rescousse
Mais une bonne partie du comportement d'un contrôleur repose sur l'appel à (et sur les réponses fournies par) un ou plusieurs objets de domaine.
Personnellement je mets toute la logique de mon application dans ces objets et je ne fais pas d'appel aux données directement. Pour ceux qui font le contraire, la logique de tests est de toute façon la même. Pour que le test puisse tourner indépendamment (sur un serveur de Build ou dans Gallio Icarus par exemple), il ne faut pas de liaison à une base de données ou à tout autre système externe.
C'est aussi pour cela que passer par des objets de domaine, même s'ils ne font que du CRUD, va simplifier le code dans le contrôleur et donc faciliter les tests.
L'avantage majeure résidant dans ces objets de domaine, puisque c'est nous qui les écrivons "à la main", c'est d'avoir une interface que les bouchons vont exploiter.
Je ne vous fais pas l'affront d'expliquer pourquoi une interface est bonne pour votre architecture.
Tout ce qui est à l'extérieur de notre contrôleur à tester devrait avoir une interface. C'est le cas par exemple d'un Web Service. Quand vous allez vous brancher à une Web Reference, Visual Studio va avant tout construire une Interface (au sens C#) et vous allez pouvoir travailler avec celle-ci.
De toutes façons, il est aisé d’admettre (ou de constater) que tous les frameworks de bouchonnage (mockup) vont exiger une interface afin de pouvoir travailler, donc vous n'avez pas le choix.
Partons du cas où nous avons été de bons élèves et où nous disposons d'une IquelqueChose pour nos objets de domaine (Si ce n'est pas le cas, un petit coup de refactoring et en 3 secondes nous auront ce précieux fichier).
Armé de cette précieuse Interface, donc, vous la passerez en carburant au constructeur du Mock. Avec Moq, cela ressemble à ceci :
|
//Arrange // create the mock var mockRepository = new Mock<IDomainManagingPasswords>(); |
L’idée est ensuite de faire passer au contrôleur, un objet factice fabriqué par le mockRepository, qui va répondre à l’interface voulue.
Donc vous aurez à modifier le code du contrôleur pour qu'il travaille non plus avec une instance interne du (ou des) objet de domaine, mais avec une référence sur l'Interface, et fourni à l'extérieur du contrôler. C’est la seule chose que vous devez modifier dans votre contrôleur pour le rendre testable, mais à bien y réfléchir, c’est plus une façon de programmer qu’une contrainte donnée par la démarche de test. Je m’en expliquerai dans un prochain article sur la qualité du code et les enjeux du test dans l’optique de la programmabilité et de la maintenabilité du code.
Cette différente façon de faire consiste à très fortement découpler les objets entre eux. A bien y réfléchir, un objet (ici le contrôleur) a toujours besoin d’un (ou plusieurs) autre objet pour réaliser le comportement attendu. Ne serait-ce que parce que nous avons à notre disposition foultitude d’objets prêt à être réutilisés.
Pour ce faire, nous avions souvent l’habitude d’instancier ces objets tiers, au moment où nous en avions besoin. Parfois, au mieux, nous procédions à leur instanciation/initialisation dans le constructeur de l’objet qui en fait usage.
Ce n’est pas une bonne pratique, car cela ne laisse aucun contrôle sur ces objets (comment ils doivent être initialisés, etc). Il est donc plus profitable (et pas que pour des besoins de tests) de passer des pointeurs sur ces objets au moins au constructeur de celui qui en fait usage, et voir même à chaque méthode dans certains cas.
Pour notre contrôleur cela donne ceci :
|
private readonly IDomainManagingPasswords _domainObject;
/// <summary> /// constructeur avec parametre pour accepter le Mocking... /// </summary> /// <param name="domainObj">The domain object.</param> public ManageController(IDomainManagingPasswords domainObj) { _domainObject = domainObj; } |
Ensuite à l’intérieur des méthodes du contrôleur, on utilise librement la variable _domainObject comme si de rien n’était.
Cette variable sera occupée par l’objet bouchon lors du test, et cela nous permettra d’ordonner au bouchon d’avoir un comportement A ou B, selon les besoins du test.
Les possibilités donc de « jouer » avec le test sont maintenant très nombreuses.
Par contre, il faut que le contrôleur continue de fonctionner dans son environnement initial, à savoir lorsque le site Web fonctionne dans IIS ou Cassini (ou Apache). Et dans ce cas, le framework Asp.Net MVC s’occupe d’initialiser les contrôleurs, et pour cela il appelle le constructeur sans paramètre de chacun ; ce qui est bien normal, car il n’est pas capable de décider quelle instance d’objet tiers lui passer.
Et évidement, dans ce contexte, on ne travaille plus avec les bouchons mais avec les implémentations « qui marchent » !
Alors comment faire ?
Inversons le contrôle
Il faudrait avoir un mécanisme qui de manière transparente à tout mécanisme (je pense en particulier au mécanisme d’initialisation de Asp.Net MVC, puisse instancier lui-même les objets « qui marchent » et les donner à ceux qui s’en serve.
Dans notre cas, il s’agit de faire passer des objets de domaine correctement instanciés et initialisés, aux constructeurs des contrôleurs lorsque ceux-ci sont mis en route par l’infrastructure de Asp.Net MVC, sur laquelle bien sur nous ne pouvons pas opérer de modification de comportement, puisque le code ne nous appartient pas et qu’il est déjà compilé.
C’est là où l’Inversion Of Control (IoC, tellement plus chic) entre en scène et trouve une de ses nombreuses utilités.
L’idée initiale de l’AOP (qui a inspiré l’Injection de Dépendance) était de permettre au développeur de supprimer la plomberie dans son code, c'est-à-dire sortir toutes les lignes de code qui n’avaient pas vraiment attrait à son algorithme mais qui étaient nécessaires ; sans quoi, justement, les objets dont il dépendait (accès aux données ou à une information tierce) ne pouvaient pas opérer comme il le souhaitait.
Dans le cas du test d’un projet Asp.Net MVC avec de l’injection de dépendance, vous trouverez foison d’exemples et de frameworks.
Quelques points d’entrées :
http://www.mikesdotnetting.com/Article/117/Dependency-Injection-and-Inversion-of-Control-with-ASP.NET-MVC
http://www.rickardnilsson.net/post/2009/12/25/Dependency-injection-in-ASPNET-MVC-with-Unity-IoC-Container.aspx
http://scottfindlater.blogspot.com/2009/11/tdd-mvc-12-inversion-of-control-ioc.html
http://codeclimber.net.nz/archive/2009/02/05/how-to-use-ninject-with-asp.net-mvc.aspx
Mais nous voulons rester pragmatiques, et le problème qui nous intéresse ici est « comment faire en sorte que le contrôleur obtienne un objet de domaine correctement instancié et initialisé quand le projet tourne en mode non-test, c'est-à-dire avec un constructeur sans paramètre ? ».
Mon critère est assez simple : j’ai retenu la solution qui m’oblige à écrire le moins de code possible, qui soit la moins intrusive dans le code existant, et qui m’épargne des lignes de configuration XML qu’on ne sait jamais comment écrire correctement (et auxquelles ont préfère une API fluente, qui permette à l’Intellisense de nous guider intuitivement dans l’usage des objets exposés).
StructureMap est l’un d’entre eux.
Nous avons écrit plus haut un contrôleur MVC doté d’un constructeur avec paramètre qui permet de faire passer une instance d’un objet de domaine.
Hors la fabrique de contrôleurs que Asp.Net MVC utilise en interne ne sait instancier les contrôleurs qu’en utilisant un constructeur sans paramètre. Il faut donc fournir une autre fabrique plus souple.
Heureusement que Scott et son équipe ont tout prévu, et que nous pouvons surcharger la fabrique de contrôleurs par défaut (DefaultControllerFactory) en préparent une autre comme ceci :
|
using System; using System.Web.Mvc; using StructureMap;
namespace yourProject { public class DependencyControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(Type controllerType) { return ObjectFactory.GetInstance(controllerType) as Controller; } } }
|
L’ObjectFactory permettra à StructureMap de résoudre les dépendances et trouver la bonne implémentation concrète de tous ce qui présente une interface remplaçable à la volée par un objet concret.
Ce nouveau Controllerfactory sera enregistré dans la logique Asp.Net MVC en ajoutant une petite ligne dans Global.asax.cs, dans Application_Start() plus précisément :
|
ControllerBuilder.Current.SetControllerFactory(new DependencyControllerFactory()); |
Et juste ensuite (toujours dans Application_Start) nous préciserons à StructureMap quel mapping opérer entre les interfaces et les implémentations concrètes, comme ici :
|
ObjectFactory.Initialize(registry => registry .ForRequestedType<IDomainManagingPasswords>() .TheDefaultIsConcreteType<DomainManagingPasswords>()); |
Et voila!
C’est assez simple, notez juste que dans cet exemple, mon classe d’implémentation concrète DomainManagingPasswords disposerait d’un constructeur sans paramètre. Pour les cas plus complexes, lire la documentation ici : http://codebetter.com/blogs/jeremy.miller/archive/2008/08/20/smartinstance-in-structuremap-2-5.aspx
Il y a des frameworks IoC qui sont plus explicites encore, et qui vous laissent choisir quelle implémentation viendra s’injecter selon telle ou telle condition.
Cela peut être aussi en intéressant à utiliser si vous voulez par exemple, changer un fournisseur de données par un autre, à la volée dans votre programme.
http://www.iridescence.no/post/Inversion-of-Control-ASPNET-MVC-and-Unit-Testing.aspx
Mais y-a-t-il plus simple ?
Sortir les patterns qui vous font passer pour le roi de la programmation est parfois superflu.
Le crédo est d’être économe, de n’utiliser que ce dont on a besoin. Pourquoi lancer toute la machine d’un IoC, sinon à passer pour un érudit ?
Dans notre cas, nous avions simplement besoin de fournir à la factory par défaut de construction des Contrôleur Asp.Net MVC, un constructeur sans paramètre (tout en gardant celui avec paramètre qui sert aux tests).
Il suffisait d’écrire ce constructeur, et c’est lui qui se chargeait d’instancier l’objet de domaine concret répondant à l’interface IDomainManagingPasswords :
|
public ManageController() { _domainObject = new DomainManagingPasswords(); } |
Un bien pour un mal. En faisant cela nous économisons toute la coûteuse introspection qu’opère un Injecteur de Dépendances, mais nous introduisons avant compilation du couplage très fort entre nos classes…
Retour au test, comment pousser le bouchon plus loin ?
Maintenant que nous savons comment faire pour préparer notre objet testé (le contrôleur) pour pouvoir fonctionner de manière identique dans un cas de test ou dans un cas de non-test, voyons comment spécifier le comportement des bouchons pendant le test.
C’est la que notre ami Moq refait surface, et nous permet de piloter le comportement de l’objet « bouchon ».
|
// create the mock var mockRepository = new Mock<IDomainManagingPasswords>(); |
Je veux que lorsque la méthode X mon contrôleur fera appel à la méthode FindUserInAdam de l’objet de domaine qu’elle emploie, et quelque soit la valeur des paramètres, il me retourne une valeur de mon cru, rien de plus simple :
|
mockRepository.Setup(cr => cr.FindUserInAdam (It.IsAny<string>())) .Returns(new resultOfSearchingUser { errorMessage = "test error", codeResult = codeResult.NotFound }); |
Ce qui se lit (donc se programme) aisément :
Permet de poster les choses. La lambda expression permet d’exprimer ce qui se passera en cas d’appel à la méthode voulue. Les arguments sont gérés aussi par Moq. It est un objet pratique qui permet de dire « Ceci » est une valeur « peu importe » de type string : It.IsAny<string>().
Ou d’autres formules (une regex par exemple).
L’expression qui s’en suit dit quoi faire quand la méthode sera réellement invoquée. Ici c’est un retour (Returns) d’une valeur assemblée de toute pièce pour les besoins du test (new resultOfSearchingUser).
N’oubliez pas que les Mocks sont des objets creux, ils répondent à une interface mais ne font rien. Donc à vous de programmer leur comportement.
On pourrait vouloir tester comment le contrôleur réagit si l’objet Bouchon de domaine renvoit une exception. Là aussi, c’est assez simple à exprimer :
|
mockRepository.Setup(cr => cr.FindUserInAdam (It.IsAny<string>())) .Throws(new System.OverflowException("test error")); |
Pour terminer, on n’oubliera pas de donner en carburant cet objet bouchon au contrôleur avant de lancer (ACT) l’opération à tester:
|
//bind the mocked object to the controller var controler = new ManageController(mockRepository.Object);
///ACT var results = controler.DoFindUser() as ViewResult; |
A partir de là, vous avez toutes les billes en main pour tester tout ce que vous pouvez imaginer.
C’est d’ailleurs cette trop grand liberté qui peut être désarmante, et on cherche une méthode pour savoir quoi écrire comme cas de test. La réponse est 2 paragraphes plus loin.
Tester le Modèle
le "Modèle" en tant que structure de données que l'on passe du contrôleur à la vue ne se teste pas en lui-même. Par contre c'est le "fournisseur du modèle" c'est à dire l'objet que vous devez invoquer (et que nous avons substitué par un Mock) qui doit être testé pour lui-même.
A ce moment là c'est un projet de test autour des classes de domaine (classes métier pour ceux qui préfèrent ce terme) aux quelles il faut ajouter une batterie de Tests Unitaires "classiques" pour vérifier leur comportement.
Tout ce que je viens de dire sur les contrôleurs s’applique évidement aux classes de domaines. Elles doivent elles-aussi être fournie avec un jeu de test « en isolation complète ».
3 - Plaidoyer pour une approche Comportementaliste (BDD)
Si vous êtes en mal d’inspiration pour écrire vos tests, voici une idée qui pourra faire son chemin…
Le Behavior Driven Development (ou développement conduit par le comportement et donc les spécifications) devrait être LA façon de programmer universelle.
Affirmer aujourd'hui que la programmation d'un logiciel ne peut se faire qu'en fonction des spécifications passe pour une vérité des plus banales.
Or, jusque là, personne ne s'était occupé de rendre vérifiable, "prouvable" une telle démarche. Le développeur écrivait donc son programme, bon an, mal an. Et vérifiait une fois déployé (en général lors de la préparation de la recette ou de lors de la recette elle même) si le logiciel produit était bien conforme aux spécifications.
Entre écriture des spécifications (en majorité sous forme littéraire) et code (forme "machine", c'est à dire langage de développement) il y a un certain écart, pour ne pas dire un gouffre.
Ce que propose l'approche BDD c'est d'éliminer purement et simplement tout écart.
Et d'écrire les spécifications de manière formelle (donc dans une langue compréhensible par l'ordinateur) et reliée au langage du développement.
Ainsi un automate (un framework de tests unitaires est préposé à cela) peut relier la vérification des spécifications ainsi décrites au code réellement produit.
Le tout, de manière systématique, automatique, constante et répétée (dans le cadre d'une usine logicielle bien construite).
Ce ne sont pas les ressources qui manquent sur le net pour vous expliquer que faire du BDD c'est bon pour vous, essayez par exemple http://behaviour-driven.org/
Ou lisez Dan North, qui est celui qui a posé l'article fondateur : http://dannorth.net/introducing-bdd
Pour ma part, je vous proposerai bientôt un article entièrement consacré au sujet, autour d'une exemple concret bien entendu.
Le BDD est présenté par beaucoup d'éminent spécialiste comme l'aboutissement des méthodes SCRUM et XP
http://www.code-magazine.com/Article.aspx?quickid=0805061
Cette approche est également la plus fidèle à la notion d'Agilité, puisqu'elle permet d'exploiter à 100% les efforts faits en matière de spécification par UserStories et Scenarios.
Mais si elle est légion en Ruby et Python, si on la trouve beaucoup en Java, il faut dire que .Net est à la traine. Et c'est quelque peu frustrant voir même insultant (n'avons nous pas le droit de faire de meilleurs logiciels?)
Cela me rend plutôt inquiet, .Net est-il une plateforme laissée aux seuls Geeks et bricoleur de l'informatique? ou aux sociétés de service pressées de faire du chiffre et ne mettant pas vraiment l'accent sur la qualité logicielle?
Toujours est-il qu'il faut se lever tôt pour trouver un framework prêt à l'emploi, qui fonctionne (sic), et simple à prendre en main (re-sic) pour la plateforme .Net
Beaucoup de projets sont abandonnés en phase initiale (BDD Extensions project on Google Code.)
J'ai essayé de tester tout ce qui était compilable et seul NBehave semble tenir ses promesses; mais comme vous pouvez le voir dans cet article, l'écriture reste peu lisible hélas http://pebblesteps.com/post/Behavior-Driven-Development-with-NBehave.aspx
les BDD extensions de xUnit semblait offrir une forme plus sympathique à lire, mais bon.
Il y avait des initiatives très prometteuses comme MisBehave, basé sur M et Oslo... mais là encore aucun engouement, ni de la part de la communauté ou des têtes pensantes chez Microsoft (d'ailleurs, que devient M à part un textual DSL pour de la modélisation de données).
Il faudra attendre que la communauté .Net se (re)mobilise et trouve enfin de l'intérêt à faire du BDD pour voir naître un framework nous donnant vraiment envie de faire du comportementalisme et que cette pratique n'apparaisse plus comme une perte de temps, alors que justement c'est le contraire qui devrait en résulter.
4 - D’autres exemples ?
Un projet complet TDD avec MVC plus NHibernate est à découvrir (avec des pages Wiki complètes) sur http://sharparchitecture.net/
Allez voir aussi sur http://scottfindlater.blogspot.com/2009/10/tdd-mvc-adventures.html
Enjoy!
pour les brèves, préférez Twitter
Janvier 21st, 2010Lien: https://twitter.com/guillaume_agile
finalement, Tweeter s'avère parfait pour les reflexions instantannées, je vous invite donc à me suivre aussi là bas
https://twitter.com/guillaume_agile
et ici, toujours des articles de fond et/ou pratiques ; comme le prochain sur le Test avec Asp.Net MVC
de la réalisation à la production
Décembre 7th, 2009je m'amuse souvent (et pas forcement innocement) à faire le parralèle entre mon métier actuel de "faiseur de logiciel" et mon passé d'étudiant en cinéma et audio-visuel (passé trop court, mais les contraintes matérielles de ce bas monde et quelques autres paramètres en ont décidé autrement).
parlons du futur un peu....
Novembre 20th, 2009Comme ils nous cassent tous les oreilles avec ChromeOS (ok, j'aime Android et j'assume), n’oublions pas que MS va aller beaucoup plus loin qu’un simple Linux revampé et des WebApps (même si c’est l’avenir) tournant sur un omni-navigateur (Chrome+Gears)
Un article de référence pour soutenir mes propos:
http://www.sdtimes.com/MICROSOFT_S_PLANS_FOR_POST_WINDOWS_OS_REVEALED/About_CLOUDCOMPUTING_and_MOBILEDEVELOPMENT_and_NET_and_SOASAAS_and_SOFTWAREDEVELOPMENT_and_WINDOWS_and_MICROSOFT/32627
Peut être vous saviez déjà que ca s’appelle Midori, mais le modèle de programmation va changer :
The Midori programming model will tackle state management, which Microsoft admits in its documentation is a challenge in Windows, by migrating APIs, applications and developers to a constrained model.
Là où ca devient palpitant (pour les développeurs):
Other objectives are eliminating dynamic loading and in-process extensions; developing a failure model based on reliable transactions, so the system understands exactly which processes are impacted by a cascading failure and how to restart the computation; and having a standard way of dealing with latency, asynchronous behavior and cancellation, throughout the stack.
Un OS intelligent qui se protégé tout seul des plantages et qui arrête de faire confiance aux programmes qu’il execute ? comme par hasard, c’est aussi l’idée de Google dans ChromeOS
Mais, plus de protection, et donc plus de contrôle = moins de souplesse
restricting dynamism at the OS level will not impact dynamism at the programming level.”
ouf, on est sauvés!
Et OSLO pourrait revennir sur le devant de la scène :)
In a possible link to Microsoft’s Oslo composite application initiative, the programming model will have a dependence on metadata, with the aim of allowing the system to more reliably manage applications.
the proposed OS would have a non-blocking object-oriented framework API. This would have strong notions of immutability—in the sense of objects that cannot be modified once created—and strive to foster application correctness through deep verifiability by using .NET programming languages.
Un OS orienté objet et transactions? On en rêvait….
Mais la concurrence est là:
“A lot of these problems are being solved, at least partially, by the ideas of store-and-forward and message synchronization,” Hammond noted. “Google Gears, Adobe AIR, even the mobile OSes with things like SMS can handle occasional connectivity. Why shouldn’t this be built into core OS communication protocols, especially if they are asynchronous by default?” he asked.
Qui sera le vainqueur des OS de demain ? non pas de savoir quel éditeur car il s’agit d’une guerre commerciale… mais quelle technique ?
Y-a-t-il un futur pour la recherche sur les OS tels que nous les connaissons aujourd’hui, et donc pour les suites de Windows… (ou MacOs)
Ou bien l’OS va-t-il devenir le grand perdant de cette bataille, et toutes les nouveautés ne seront-elles pas reportées sur les omni-navigateurs (ou plateforme applicatives virtualisées comme pourra le devenir Air ou même Eclipse), sur les interpréteurs et sur les petits moteurs de synchronisations comme Gears. Mais qui laisseront l’OS à une place dérisoire, et qui n’intéressera plus aucun développeur…
A lire : Une très intéressante présentation des principes de Singularity (mais vieille de 2006 !) :
http://research.microsoft.com/en-us/um/redmond/events/fs2006/presentations/23_Hunt_071706.ppt
http://research.microsoft.com/en-us/projects/singularity/
la guerre continue: http://blogs.zdnet.com/microsoft/?p=4650&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+zdnet/microsoft+(ZDNet+All+About+Microsoft)&utm_content=Google+Reader
mais Microsoft fait toujours office de suiveur... dommage
Agile Development From A Developers Perspective
October 14th, 2009je ne saurais trop vous recommander de jouer cette brillante (et agile) présentation, pour vous développeurs, pour un chef de projet, pour un architecte...
Tout est excellement condensé. Le MUST de l'application des bonnes pratiques de conduite d'un projet de développement logiciel, et de méthode de réalisation (TDD, intégration continue, code quality metrics, acceptance tests, etc...)
http://www.slideshare.net/rbanks54/agile-development-from-a-developers-perspective
faites le savoir!
Agile Tour 2009: c'est parti! ... et aussi à Toulouse
October 8th, 2009pour tous ceux impliqués de près ou de loin dans l'adoption de démarches Agiles, et surtout pour ceux qui se demandent quel est cet oiseau bizarre, et qui voudraient bien en savoir plus, il n'y a qu'un rendez vous:
c'est l'Agile Tour 2009 partout en France!
et en particulier à Toulouse où pas moins de 20 sessions vous attendent: retours d'expériences, conférences, ateliers, présentation d'outils, débats!
les échanges seront riches et nombreux.
Une journée que vous ne serez pas près d'oublier ...
le programme et les inscriptions Toulousaines se font ici: http://www.agiletour.org/fr/at2009_toulouse_programmation.html
http://www.agiletour.org/fr/at2009_toulouse_inscription.html
appels aux orateurs
September 4th, 2009
l'Agile Tour 2009 se dessine et nous recherchons des orateurs sur le sujet
Je fait partie de l'équipe d'organisation de Toulouse et c'est aux sudistes que je m'adresse en particulier.
L'édition de cette année est orientée sur les retours d'expériences, n'hésitez donc pas à venir partager les votres!
Tous les détails pour s'inscrire (en orateur ou auditeur) sur le site http://www.agiletour.org/
Ou si vous cherchez à mettre au point un sujet à plusieurs, n'hésitez pas à me contacter.
Bonne rentrée agile à tous.
les conseils beauté de vos présentations (slides, keynotes, prez)
Août 21st, 2009Pour finir vos devoirs de vacances, je vous propose des petits idées pour améliorer les présentations PPT que vous êtes parfois amenés à faire.
Les règles d’une présentation PPT réussie :
Le texte à l’écran ne doit JAMAIS être le texte récité par le présentateur.
Le slide est un support à la narration, il doit présenter des éléments visuels qui NE SONT LA QUE POUR soutenir ce que dit le présentateur.
Il ne faut pas endormir l’auditoire.
DONC
• Des textes très courts et écrits gros
• Des belles images qui marquent ! (ne pas hésiter à aller sur Flickr pour prendre des jolis clichés, ils sont souvent en Creative Common Licence, par ex http://www.flickr.com/photos/lucas3d/3794517546/ )
• Il vaut mieux 100 slides avec 3 mots dans chaque, que 3 slides avec 100 mots.
• Utiliser une charte graphique
• Utiliser un police agréable à lire en gros
• Utiliser HABILEMENT les couleurs pour mettre en évidence un mot en particulier dans une slide, tout en gardant une charte de couleurs cohérente et sobre
• Une SEULE phrase et un SEUL concept par slide
• Un concept compliqué s’explique sur PLUSIEURS slides
• Pas d’animation dans les slides
• Si vous voulez faire apparaitre ou disparaitre des éléments, dupliquez le slide autant de fois que nécessaire pour faire l’effet
• Votre présentation doit faire entre 60 et 100 slides, en passant au max 10 à 20 secondes par slide
Une excellente prez sur le TDD
http://www.slideshare.net/bencarey/beyond-tdd
ma préférée (graphiquement) sur les CSS
http://www.slideshare.net/stubbornella/object-oriented-css
une très bonne sur l’agilité
http://www.slideshare.net/eig/agile-software-development
plus de texte, mais quand meme des bonnes idées gfx
http://www.slideshare.net/jurgenappelo/what-else-can-agile-learn-from-complexity
un rapide tour de méthodes agiles avec des images qui parlent
http://www.slideshare.net/Siddhi/introduction-to-agile-methods
le bout du tunnel?
Juin 11th, 2009enfin, on sort des ténèbres... après presque 10 ans de règne sans partager sur l'accès aux données depuis la création du Framework .Net, les DataSets rendent les armes.
C'est une vision personnelle, mais je ne peux me rappeler que mes soirées de debuggage intenses avec les DataSet... absence de typage, requêtes SQL construites sur des concaténations de chaînes de caractère... en tout cas au début, on était obligé de commencer comme ca.
Même s'ils ont mûri, les DataSets sont synonymes de lignes et lignes de codes de plomberie techniques, lourdes, fastidieuses, inutiles... et à mon sens une vision tordue de l'accès aux données.
Tout cela m'avait vite poussé à regarder NHibernate et ses confrères. Vive le Mapping Objet Relationnel!
Pour moi Linq et surtout Ado.Net Entity Framework allait enterrer définitivement les odieux DataSets... il n'en a rien été.
Et cette nouvelle m'apparaît comme une sortie du tunnel: "here are no plans to add DataSet into future releases of Silverlight"
Un signe? Un espoir?
Une promesse d'une aube nouvelle???? ;)
Si une technologie qui a le vent en poupe ne soutient plus cet ancêtre, peut être est-ce l'annonce du début de la fin?
Allez, il faut croire au progrès.
http://blogs.msdn.com/adonet/archive/2009/05/26/dataset-and-silverlight.aspx
http://www.sheysrebellion.net/blog/2008/07/31/datasets-are-evil/
http://jelle.druyts.net/PermaLink.aspx?guid=61676665-06a7-443a-9462-71dae713539e (DataSets Are Not Evil)
une excellent présentation des méthodes agiles
Juin 4th, 2009http://www.slideshare.net/mcottmeyer/adopting-agile-1521562
exactement le genre de présentation que je fais
rapide, concis, une idée par slide, des idées claires & simples
des diapositives compréhensibles par tous et d'elles-même!
a MUST HAVE and a MUST FOLLOW
Une journée extra-ordinaire
Janvier 29th, 2009Pour changer de .Net, un petit billet d'humeur sur... le travail.
Voila donc cette grande journée de grève avec une paralysie quasi-totale annoncée.
Et qu'est ce que je remarque ce matin au boulot: 2 fois moins de mes collègues sont venus travailler, les autres sont restés travailler chez eux.
C'est un des avantages à bosser dans les domaines de l'IT ou du service. Nous n'avons pas *vraiment* besoin de nous déplacer sur notre lieux de travail tous les jours, dans l'absolu.
Résultat de cette journée: l'ambiance était particulièrement décontractée voire joviale. Travaillant dans un OpenSpace, voila que -tout d'un coup- une quiétude et un calme nécessaire à la concentration régnaient autour de nous. Le travail allait en être plus efficace.
Les gens étant restés, pour bon nombre, chez eux, la circulation fut plus fluide que d'habitude (source Europe 1) et la qualité de l'air était bonne ( http://www.airparif.asso.fr ).
L'analyse de la courbe de cumul de bouchon en IdF fait ressortir une étrangeté ( http://www.sytadin.fr/ ): l'intensité des bouchons était exactement égale à la courbe des moyennes (donc aucun effet de sur-bouchon) mais elle était décalée dans le temps; c'est à dire que les bouchons se sont produits beaucoup plus tôt dans la matinée puis résorbés, pour avoir retrouvé à 9h30 une valeur quasi nulle... du jamais vu pour Paris et sa banlieue!
75% des métros ont fonctionné mais comme il y avait beaucoup moins de monde, les voyageurs étaient détendus.
Et de réfléchir, en ces temps de crise, à la nécessité de repenser nos modes de travail. Avons nous besoin de dépenser autant de CO2 pour transporter autant de monde à des distances parfois incroyables (plus de 3h de transport par journée pour certains). Et tous en même temps (ne pouvons nous pas imaginer des horaires mieux adaptés?).
Selon le WWF, 50% des émissions de CO2 des entreprises sont liées aux déplacements professionnels : voyages d’affaires, trajets domicile-bureau, etc. L’ONG vient donc de lancer le challenge One in five pour pousser les entreprises à réduire leurs déplacements professionnels de 20% d’ici 5 ans. (source: http://www.greenit.fr/article/acteurs/50-des-emissions-de-co2-liees-aux-voyages-daffaires )
En bon provincial (et Occitan de surcroît) je suis convaincu qu'il y a trop de monde en Ile de France, et que concentrer 1/5eme de la population sur 1,7% de la surface du territoire est une aberration environnementale (et idéologique).
Les instances territoriales font toutes les études qui démontrent que les trajets domicile-travail coûtent trop cher en CO2 ( http://www.hauts-de-seine.equipement.gouv.fr/IMG/pdf/p6_pda_covoiturage_vf_cle636a11.pdf ).
Le gouvernement et la CEE s'y mettent aussi ( http://www.bougezautrement.gouv.fr/ ).
Je saluerai donc toutes les initiatives qui vont dans le sens du télétravail et de la dématérialisation, tel que http://www.cyberworkers.com/
et de suivre les actualités de sites "IT durable" tels que http://www.greenit.fr/
Il est temps de vivre au 21e siècle et de laisser loin derrière nous la révolution industrielle. L'ère a changé!
la Modélisation Métier est elle soluble dans le CRUD (et inversement)?
Janvier 28th, 2009http://docs.google.com/Doc?id=dhp3ggmx_115g524prcq
je vais lever une veille taupe, peut être un débat sans fin, mais il me parait important d'essayer de remettre les cartes sur table.
Plus les années avancent, et plus je me questionne sur où vont les technologies et les éditeurs ou les projets Open Source?
Et je me demande si on ne frôle parfois pas la schizophrénie...
Par exemple chez Microsoft, on nous dit : "CRUD, Only When You Can Afford It" ( http://msdn.microsoft.com/en-us/library/ms978509.aspx )
et après on met en avant ASP.NET Dynamic Data, qui permet de faire des applications 100% orientées CRUD.
Au début était l'informatique, les carte perforées, puis les disques durs. Et tout cela stockait des données, des données, des données.
Puis vint Merise en grand éclaireur de la pensée informatique industrielle (pendant que les scientifiques n'en avaient cure, et persistait dans une voie fonctionnelle).
Ce que faisaient alors les logiciels se résumait en 4 verbes: Créer, Lire, Modifier, Effacer des données (Create Read Update Delete, CRUD en anglais).
Et après de nombreux logiciels produits sur ce modèle, on s'est rendu compte que:
1) cela ne faisait que produire des logiciels d'informaticiens, c'est à dire pas du tout "User Friendly";
2) la complexité de la réalité dépasse le stade de ces 4 opérations basiques.
On a commencé à réfléchir du point de vue de l'utilisateur. On s'est aperçu qu'il avait un besoin de logiciel dans le but de l'assister dans l'exécution de son métier (et accessoirement que l'utilisateur était livré avec des yeux).
On a donc sorti une artillerie lourde pour décrire - MODELISER - les processus métier, issus du besoin réel de l'utilisateur, représentés bien souvent par des Scénarios Utilisateurs (merci UML).
Des paradigmes tels que le "Model Driven Design" ou le "Domain Driven Design" sont venus consolider cette nouvelle façon de faire du logiciel.
Pourtant le CRUD n'avait pas pour autant disparu...
On a l'habitude de dire qu'il ne faut pas exposer les données directement au dessus d'une couche métier, tels que ce que l'on peut trouver exposé par un Web Service, et pourtant nombre d'applications le font.
et Microsoft qui va droit dedans avec SdS et ASP.NET Dynamic Data.
"Data-driven application" redevient un mot que l'on peut prononcer sans honte.
Microsoft n'est pas le seul, avec la lame de fond qu'est REST, tout est orienté ressource, donc données, et les opérations permises sont encore au nombre de... 4!
Question légitime: comment exprimer du métier avec ce genre d'outils?
Comment faire dans cet incessant aller-retour entre une paroisse et une autre? Est-ce un éternel recommencement? (et piétinement?)
la suite sur http://docs.google.com/Doc?id=dhp3ggmx_115g524prcq
