Archive

Archive for the ‘Microsoft .Net’ Category

Retours d’expérience sur CQRS

février 5, 2014 Laisser un commentaire

Nous sommes actuellement sur la phase finale de réalisation d’un « extranet » qui interagit fréquemment avec une base de données distante. Cette interaction étant forte (l’application était d’ailleurs une appli Oracle Forms, mais à refondre sous DotNet); il fallait au départ trouver le bon « pattern » qui devra s’adapter à de telle situation, tout en facilitant par ailleurs la vie des développeurs. On était donc parti sur le pattern CQRS (Commands and Queries Responsibility Segregation). Pour plus d’informations, vous pouvez googler (:-P) ou par exemple visiter ce billet de Martin Fowler.

Ce qui va suivre va juste récapituler brièvement nos retours d’expérience sur ce pattern :

CQRS est plus ou moins facile à mettre en place

Et oui, vous suivez habituellement un tutoriel (comme celui-ci), et la suite n’est qu’adaptation selon vos besoins fonctionnels. En résumé : il s’agit :

– d’écrire le code « moteur » pour les commandes : on crée en ce sens un objet CommandInvoker qui possède une méthode Invoke() (ou Execute(), c’est selon le feeling), et qui va donc pouvoir exécuter une commande en appelant cette méthode Invoke().

– optionnellement, de décrire des interfaces pour les commandes et pour les « queries ». Et pourquoi pas écrire des classes abstraites correspondantes.

– d’écrire au fur et à mesure les objets Command et les objets Query. Rappelons qu’un objet Command consisterait à exécuter des traitements pour modifier des données (insérer, modifier, supprimer), tandis qu’un objet Query aura pour rôle de lire des données (filtrer, trier, etc.)

– et enfin, de coder les Handlers des objets Command. A chaque objet Command, on peut avoir un ou plusieurs codes de traitements qu ‘on appelle « CommandHandlers ».

=> pour notre application, on a même pu concevoir un générateur de codes qui crachent les objets Command/Query/CommandHandler, en pointant sur la base de données, et moyennant d’éventuelles configurations…

CQRS se marie bien avec une architecture basée sur de l’IoC

En partant du principe que chaque objet Command ou Query n’est qu’une implémentation d’un interface ICommand ou IQuery; on peut bien s’amuser à faire abstraction de ces objets au code utilisateur. Et la création des instances concrètes se feront pendant l’exécution, grâce à un moteur d’IoC (entre autres Castle Windsor). C’est exactement comme ce que font les adeptes des architectures orientées « Service », dans lesquelles on fait abstraction des contrats de services, en exposant au code utilisateur des interfaces.

Parfois, choisir entre Command ou Query n’est pas si simple…

Par définition : un objet Command doit exécuter des traitements pour modifier les données, tandis qu’un objet Query fait le travail inverse : lire les données en préparant la présentation de celles-ci. Or, souvent, on peut tomber sur des cas où l’on veut exécuter un traitement (assez complexe d’ailleurs), et que ce traitement doit ramener ensuite un ensemble de résultats, ou carrément des données. En construisant un objet Command : l’objet qui en résulte est plus ou moins « dénormalisé » car il faut créer donc une propriété du Command, qui aura pour essence de véhiculer les données en retour des traitements. Par contre, en choisissant d’implémenter un Query : d’une part, l’objet « SearchModel » (qui regroupe les critères de requêtes par exemple) devient rapidement compliqué, et d’autre part; un objet Query ne doit pas être utilisé pour des traitements qui provoqueront des « charges » importantes, car c’est l’une des principales raisons de la séparation des commands et des queries, donc du pattern CQRS en lui-même.

Comment ordonnancer les « Handlers » pour un Command qui peut en avoir plusieurs ?

L’un des points forts du pattern CQRS, et surtout de l’utilisation des Command, est le fait de pouvoir rattacher des « objets d’exécutions » (handler) à chaque objet Command.

Par exemple : vous voulez une suppression en cascade qui s’effectue au niveau « métier » : vous avez donc un objet Command (DeleteCommand) qui est sensé provoquer cette suppression. Cet objet contient les paramètres qui vont restreindre sur le (ou les) enregistrement(s) à supprimer. Supposons ensuite que l’objet métier (entre autres un POCO par exemple) à supprimer possède un ou plusieurs autres objets métiers enfants. L’idée serait de rattacher des handlers pour l’objet DeleteCommand, de telle sorte que : un Handler va supprimer l’objet parent, alors que les autres handlers auront la charge de supprimer les objets enfants. Mais ensuite, nous avons besoin de spécifier que les suppressions des objets enfants doivent se faire AVANT celle de l’objet parent, sinon on aura un souci d’intégrité au niveau de la base de données. Comment établir cet ordonnancement dans l’exécution des handlers ? A cela, il n’y a pas de réponse unique, et ce n’est pas bien décrit dans les différents tutos ou introductions à CQRS… Dans notre cas, on a mis une convention de nommage sur les handlers (avec un suffixe numérique), et l’ordonnancement se fait donc en triant selon ce suffixe. On peut aussi rajouter une propriété « Order » dans chaque objet Command ou dans la classe abstraite dont toutes les Command vont hériter.

On a une sensation de redondance entre un objet Command, un modèle de vue et un objet POCO

Dans un formulaire classique : l’interface est mappé à un modèle de vue. En cliquant sur un bouton de traitement (enregistrer par exemple) : ce modèle de vue est envoyé vers le serveur d’application (ou vers le code côté serveur) qui contient donc un objet Command spécifique au traitement demandé. Ce command va contenir à peu près les mêmes informations contenues dans le modèle de vue. Ensuite, avant de s’exécuter au niveau de la base : le Handler de l’objet Command va transformer les informations contenues dans cet objet Command pour les véhiculer vers un modèle POCO… Et enfin, c’est le modèle POCO qui va être manipulé par une couche d’accès aux données afin de lancer par exemple des requêtes SQL. Visiblement, la plupart des informations véhiculées sont les mêmes, mais elles passent par trois objets différents !

Conclusion

Comme tout autre pattern d’architecture; le CQRS s’adapte à certaines situations, mais pas à toutes. A mon avis (et cela a peut-être été dit X fois), il faut le privilégier : si on veut vraiment séparer les domaines d’exécution des commands et des queries. Ce qui suppose que les interactions vers la base de données (écriture) sont beaucoup plus intenses que celles partant de la base de données (lecture).

Publicités

Inversion de contrôle (suite)

mai 28, 2013 1 commentaire

Comme promis dans l’article d’introduction à l’IoC, nous allons illustrer par un exemple très simple ce qui se passe lorsqu’on effectue une inversion de contrôle (ou une injection de dépendance).

L’exemple consiste à afficher sur une page web (entre autres MVC, mais peu importe…) la liste de personnels pour un projet. Imaginons qu’on nous demande de développer une application de gestion de projets informatiques, et donc de pouvoir gérer les ressources pour les projets.

Premièrement, lorsqu’on veut architecturer une application en se basant sur le D-D-D (Domain-Driven-Design); il faut penser à se focaliser sur le code métier. Autrement dit, ce que l’on va écrire en premier lieu, c’est le code qui correspond au domaine métier. De tac au tac, pour afficher une liste de personnels, on a besoin bien évidement d’un objet « Personne »… cette classe sera à mettre bien évidement dans le projet « métier » (créer un objet de type « Class Library » et nommez-le comme vous le voulez, par exemple : Learning.Business.csproj

   public class Person

   {
        public string Name { get; set; }
        public string FirstName { get; set; }
   }

Pour illustration, je vais faire très simple, donc pas la peine de mettre des tonnes de propriétés pour notre objet « Person ».

Ensuite, dans le même projet Learning.Business.csproj, ajoutons une interface IPersonRepository. Cette interface servira de « contrat » pour le code utilisateur, afin de leur obliger de définir les méthodes nécessaires pour pouvoir « persiter » un objet « Person ». Ici, notons bien que : c’est le code métier qui exigera au code d’accès aux données, ce qu’il devra faire pour satisfaire la bonne exécution du métier, car n’oublions pas : on est en DDD, c’est le métier qui dirige tout.

public interface IPersonRepository 

{

    IEnumerable<Person> GetAllPersons() ;

}

Maintenant, passons au niveau du code d’accès aux données : créons un projet (Class Library) Learning.DataAccess.csproj, et ajoutons une référence de Learning.Business à ce projet. Remarquons que c’est le projet métier qui est ajouté comme référence (c’est l’inverse de ce qui se passe si on ne fait pas d’inversion de contrôle). En fait, le but c’est de pouvoir avoir une couche « métier » aussi indépendant que possible. Comme cela, si les autres couches évoluent, le métier ne sera pas impacté. A l’inverse, si le métier évolue – et comme c’est la couche qui dirige tout – les couches environnantes doivent changer. Dans ce projet, ajoutons une class PersonRepository qui implémente (vous l’avez deviné 😉 ) l’interface IPersonRepository.

public class PersonRepository : IPersonRepository

{

    IEnumerable<Person> GetAllPersons()

   {

        return (from p in DataContext.PersonsSet select p).ToList();

   }

}

Ne vous souciez pas du code « return … » c’est juste un exemple. Ici, on veut récupérer une liste de personnes à partir de la base de données, et on pourra passer par exemple par un DataContext (Entity Framework), mais on peut bien utiliser de l’ADO.Net pur, ou du NHibernate ou tout ce que vous voulez… Jusqu’ici, nous avons un code d’accès aux données qui respecte bien le contrat imposé par IPersonRepository, donc un code qui permet de récupérer une liste de personnes comme le métier l’a voulu.

Imaginons maintenant que la liste de personnes sera affichée dans une page Web. Comme je fais du MVC4 (ASP.net) actuellement, c’est ce qui me passe premièrement en tête. Mais l’IoC ne se limite pas à ce genre d’application, car le principe reste le  même. Enfin bref,… créons une application ASP.Net MVC4, et nommons ce projet Learning.Web.csproj. Ajoutons comme référence à ce projet le projet métier Learning.Business. Encore une fois, rappelons-le : on fait toujours référence au projet métier (partout ou presque partout). Créons ensuite un Controller MVC qui s’appelle PersonController.

public class PersonController : IController

{

     public ActionResult List()

     {

           // Ici on devra faire appel à un objet IPersonRepository pour ramener une liste de personnes

      }

}

 

J’ai mis exprès un commentaire dans la méthode List() : on a besoin d’une instance de IPersonRepository pour pouvoir lister les personnes. Mais comment pourrions-nous faire une instance de IPersonRepository ? Nous ne pouvons pas écrire IPersonRepository toto = new IPersonRepository() car IPersonRepository est une interface et non une classe. Nous ne pouvons non plus écrire IPersonRepository = new PersonRepository(), car on n’a pas de référence au projet Learning.DataAccess et une utilisation directe de Learning.DataAccess va court-circuiter la couche métier, et on perd toute notion d’architecture en couches, ainsi que la centralisation au niveau « métier ».

C’est là que viennent participer les moteurs d’injection de dépendance (Windsor Castle, Unity, NInject, etc.). Un moteur de DI (Dependency Injection) va faire en sorte de résoudre pour nous l’instance de IPersonRepository sans qu’on fasse appel à une instanciation bête et méchant de PersonRepository.

Supposons que nous utilisons Windsor Castle. Il existe plusieurs façons (d’autres moins élégantes mais plus faciles à comprendre, et d’autres plus élégantes mais une peu compliquées) de résoudre une instanciation.  Ce que je vous conseille, c’est de visiter le site de Castle Project, et de se conformer aux bonnes pratiques indiquées dans ce site. Ce qui va suivre est une illustration , qui peut ne pas s’adapter dans toutes les situations :

Ajoutons alors une référence au moteur Castle (ce sera des DLL à télécharger sur le site de Castle Project), dans notre projet Learning.Web.

Ensuite, ouvrons le fichier Global.asax.cs (pour un projet ASP.Net, Global.asax contient les codes d’initialisation et de suivi d’une demande Http), et mettons dans la méthode Application_Start() le code qui initialise notre « injection de dépendance »…

public void Application_Start()

{

     WindsorContainer Container = new WindsorContainer();

     Assembly assImpl = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + @ »bin\Learning.DataAccess.dll »);

     Assembly assContracts = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + @ »bin\Learning.Business.dll »);

     foreach (Type Timpl in assImpl.GetTypes())
    {
         foreach (Type Tcontr in assContracts.GetTypes())
        {
               if (Timpl.GetInterfaces().Contains(Tcontr))
              {
                     Container.Register(Component.For(Tcontr).ImplementedBy(Timpl).LifeStyle.PerThread);
              }
       }
   }

}

😀 Je vous l’accorde, le code ci-dessus est un peu tordu (a priori). Mais au final, ce qui y est écrit veut dire : pour chaque « interface » défini dans l’assembly Learning.Business.dll, nous demandons au moteur Windsor (l’objet Container) de trouver son implémentation dans l’assembly Learning.DataAccess.dll. Si plus tard, notre couche d’accès aux données change : il suffit de modifier le nom de cet assembly puis de recompiler. Ou mieux, on peut le mettre dans le fichier de configuration (web.config ou app.config)… Remarquez ensuite le code Container.Register(…) : car c’est ceci qui permet à Windsor de mémoriser quelque part l’implémentation pour une interface donnée.

Enfin, revenons à notre PersonController. Comme dit plus haut; ce qui nous manque, c’est un code qui instancie un IPersonRepository et qui fait appel ensuite à sa méthode GetAllPersons(). Mais comme nous avons une référence vers Windsor Castle, nous allons juste utiliser l’objet WindsorContainer pour réaliser notre instanciation. Autrement dit, à la place de la ligne de commentaire (voir plus haut), nous aurons le code suivant :

var container = new WindsorContainer();
IPersonRepository personRep = container.Resolve<IPersonRepository>();

return View(« PersonsList », personRep.GetAllPersons());

Ce qui est important dans ce code : c’est l’appel à la méthode Resolve(…) : nous disons au moteur d’IoC de « résoudre » à notre place l’instanciation de  l’interface IPersonRepository. Et comme en amont, nous lui avons déjà dit de chercher l’implémentation là où il devra le faire : notre objet personRep sera bel et bien une instance de PersonRepository (défini dans Learning.DataAccess); alors que nous ne faisons même pas référence à cette couche.

===

Pour terminer, je tiens juste à noter que les moteurs de DI, entre autres Windsor Castle, peuvent effectuer des manipulations beaucoup plus « magiques » et « impressionantes » en dehors des notions classiques de Register – Resolve… Si vous aimez aller plus loin, vous vous aventurerez bien sûr dans les notions de Component, Factory, FactoryFactory, etc. 🙂

Catégories :Microsoft .Net, Pattern

70-486 : ASP.Net 4.5 MVC 4 Web Applications (C#)

avril 13, 2013 6 commentaires

Aujourd’hui, je viens de passer à succès la certification 70-486 : Développement d’applications ASP.Net MVC 4, en C# sur framework 4.5.

Ci-dessous quelques petites « idées » pour ceux qui veulent passer le même examen. Ceci ne se prétend point être un guide complet ! C’est juste pour orienter les manières de réviser, car en aucun cas : on ne peut dévoiler les questions ( 😀 ), et qu’actuellement, les questions et les « case study » changent fréquemment, donc cela ne servira pas à grand chose… L’examen peut comporter – selon le cas – des questions à choix multiples et/ou des études de cas (qu’il faut bien bien lire car il y a des petites pièges à gauche et à droite).

0. Le langage C# avec ses nouveautés dans la version 4.5 (ou aux moins la 4) doit être plus ou moins connu/maîtrisé : programmation parallèle, type générique, type dynamique, méthode générique, Code Contracts, etc.

1. Il faut avoir pratiqué ASP.Net MVC (du moins les versions 3 ou 4). En ce sens qu’il est nécessaire de bien savoir manipuler les « routes » (RegisterRoutes() vs MapRoute() vs Routes.Add() etc.), les Http Module vs HttpHandler vs RouteHandler (en MVC), les passages de données entre modèle, vue et controller, les différents types de ActionResult. Enfin, une notion sur Web API peut s’avérer utile. Pour petit rappel; dans le Web API, il n’est pas obligatoire de préciser le type d’une ActionResult car le moteur Web API sait fournir les données attendues par la négociation Http.

2. Des notions générales sur l’architecture Domain-Driven Design sont aussi demandées : injection de dépendance (avec le cas particulier des IoC en MVC). Et à côté : Controller Factory, Model Binding, etc.

3. Authentification et sécurité : très très important car cette section concerne la majorité des questions (selon le site officiel de l’examen ) : différence entre les types d’authentification basique (Windows, Forms, Kerberos, …) et leur subtilité (dans quels cas utiliser un tel ou tel type d’authentification). OpenID et oAuth : login avec fournisseur d’authentification tiers : facebook, gmail, windows live, etc. Mécanisme de gestion de rôles et d’authentification à travers les « Claims » : notion de STS, SAML et de ClaimsIdentity.

4. Gestion d’erreur et gestion des logs : configuration de logs dans les web.config, redirection des exceptions spécifiques, utilisation des ActionFilters pour gérer les exceptions, etc.

5. Programmation web côté client : HTML5 / CSS3 (essentiellement les nouveautés), et aussi et surtout (bien sûr 😉 ) : jQuery ! Pour ce point, il faut bien avoir manipulé jQuery car les questions sont assez « subtiles » : selector, ajax, animations, évenement, etc.

6. Et enfin, quelques notions sur Windows Azure

 

Il se peut que d’autres sections sont omises. De toute façon, le mieux est d’aller sur le site officiel de l’examen pour voir les détails et les pré-requis.

Catégories :Microsoft .Net

NHibernate : Session is closed !

janvier 23, 2013 Laisser un commentaire

Si comme moi, vous avez utilisé NHibernate comme OR/M sur des applications web suffisamment complexes (pas nécessairement en terme métier mais en termes de flux entre le serveur et la couche client), vous aviez probablement rencontré l’exception « intermittente » : ObjectDisposedException => Session is closed ! , qui se déclenche d’une manière complètement non reproductible (le débogueur attaché au processus web n’arrive même pas à situer le point de départ de l’exception dans le code). Et en release, rien ne se manifeste visuellement mais les requêtes effectuées par NHibernate derrière ne se passent plus normalement.

Origine probable du problème : une session NHibernate est ouverte au démarrage d’une demande http, et est fermée par je-ne-sais-quoi, avant que certaines parties du code ait besoin d’un rafraîchissement des objets POCO ou de certaines collections (par lazy-load)… et donc effectivement : la session en cours d’utilisation est subitement fermée => boom !

Dans certaines discussions sur le web, beaucoup de gens proposent la non-utilisation du lazy-loading, mais à mon avis :

–          Cela ne résout que partiellement le problème (on évite le rafraîchissement des collections ou des propriétés en lazy-load mais on n’évite pas le rafraîchissement des objets POCO)

–          et déjà, le lazy-loading est  un besoin évident pour certains types d’application (je ne vais quand même pas requêter des milliers de ligne si je n’ai besoin que des infos d’une table parent, et que si le chargement de ces milliers de lignes n’est nécessaire qu’à la demande de l’utilisateur)

Pour y remédier, voici selon moi les précautions à prendre (cela après des jours de recherche google et de refactoring de codes) :

  • Dans une application web, ne jamais utiliser les sessions NHibernate dans un bloc using. Car à la fin du « using », l’objet est détruit et au moment du rafraîchissement ou du lazy-loading, bah, le message le dit si bien « Session is closed ! ». Opter par l’initialisation/fermeture de session en adoptant le pattern OSIV (Open Session In View) qui signifie : créer une session au démarrage d’une demande http (Application_BeginRequest) et disposer cette même instance à la fin de la demande (Application_EndRequest). Avec les versions 3.xxx de NHibernate, on peut rajouter une ligne de code à chaque instanciation de session, pour dire que la session est « bindée » avec un contexte Web :

ManagedWebSessionContext.Bind(HttpContext.Current, session);

  • Si de plus, l’application tourne avec un moteur d’IoC ; utiliser une injection des objets Session au niveau de la couche de présentation (controller dans le cas d’une architecture MVC) et dire au moteur IoC de garder la session ouverte pendant le traitement d’une demande http : i.e. LifeStyle = PerWebRequest.

Exemple avec Windsor Castle :

container.Register(Component.For<ISession>().Instance(session).LifeStyle.PerWebRequest);

  • Et surtout surtout ! (ce qui nous est arrivé récemment) : ne jamais utiliser plusieurs fabriques de session (SessionFactory). Si par besoin métier, on veut avoir différentes façons d’accéder à la base, rattacher plusieurs sessions (ISession) à une instance unique de SessionFactory ; mais jamais en créant plusieurs instances de SessionFactory…
Catégories :Microsoft .Net

Comment générer du code avec des modèles T4

Que vous soyez un développeur .net, java, C, php,… ou quelqu’un qui fait quotidiennement du SQL , des batch, du XML, etc. Il vous est sûrement arrivé de vouloir générer vos scripts ou codes car ils se ressemblent beaucoup. Pour moi personnellement, à une époque où je faisais beaucoup de Php (du CodeIgniter :-P), je me lassais d’écrire tout le temps les codes des modèles d’accès aux données, des controllers et même des vues (qui ne font tout le temps que : lister/ajouter/modifier et supprimer des enregistrements en base de données); j’avais utilisé un outil bien connu pour la génération de code, qui s’appelle CodeSmith. Et cela faisait bien l’affaire, mais le hic, c’est que c’est un outil payant 😦

Mais si vous avez déjà Visual Studio, et même si vous voulez générer d’autres scripts/codes en dehors de C# ou VB; vous pouvez bien l’utiliser pour générer des codes. Et pour ceux qui ont déjà essayé CodeSmith, cela a une certaine ressemblance ! Il s’agit des modèles T4. Voici un how-to rapide pour ceux qui veulent s’initier. En tout cas, voici comment je l’utilise :

Premièrement, comment créer un modèle T4 ?

Après avoir créé un projet (une librairie de classe ou une application console ou même une application windows…), ajouter un nouvel élément et choisir un modèle T4 prétraité. Cela nous permet d’avoir un fichier d’extension .tt avec un fichier .cs associé qui porte le même nom.

Utilisation simple des balises T4

Comme de nombreux utilitaires de génération (entre autres CodeSmith), un modèle T4 se base sur l’utilisation de balises spécifiques.

<#@      #> => pour écrire un code en en-tête comme le type de langage à utiliser par le moteur de génération (généralement c’est du C#), définir le type de code à générer (du texte ou du C# ou du SQL ou du XML, ou tout ce qu’on veut), ou importer des assembly, référencer des namespace. Habituellement, ce que l’on va trouver dans un en-tête de template T4, c’est le genre de code qui suit :

T4

Ces lignes de code signifient que : on va générer du code avec du C#, et on va générer du texte (.txt). Par défaut; le code généré est d’extension .cs. Mais ce qui est embêtant avec Visual Studio, c’est que lorsqu’on fournit une extension .cs ou .vb au code à générer, il tente de le compiler à la volée au moment où l’on lancera la génération proprement dite. C’est utile dans certains cas, mais parfois, c’est gênant car nous n’aurons pas forcément les références aux assembly que le code généré aurait besoin en exécution. En effet, le moteur de génération peut être un projet vraiment à part… Mais de toute façon, même si on génère du .txt, au moment où l’on crachera le contenu vers un fichier, nous pouvons spécifier la vraie extension, comme le nom du fichier d’ailleurs.

Ici, en plus, et c’est un exemple réel 🙂 nous faisons référence à un assembly externe : Xxx.CodesGenerator.Library ainsi qu’aux namespaces définies juste en dessous. Cet assembly nous sert – juste en passant – de requêter la structure de notre base de données. Mais tout ça reste en dehors de cet article !

Le balise <# #> permet d’ écrire du code C# pour le moteur. Ceci nous permet d’écrire du code pour personnaliser notre génération : des clauses if, des boucles, des appels à des variables externes (on verra cela plus bas), etc. C’est équivalent à <% %> pour ceux qui connaissent du ASP.Net.

<#= #> sert à écrire du code qui va cracher quelque chose en sortie. C’est comme faire un « echo » en PHP… c’est équivalent à <%= %> lorsqu’on fait du ASP.Net.

Et c’est tout !!! Tout ce que vous écrivez en dehors de ces balises sera généré en sortie. Du moins, dans mon cas, ces trois balises me suffisent pour générer quelques choses d’utilisables.

Utiliser une variable fournie par du code externe

Dans tout le code du template, on peut récupérer une variable fourni par du code externe en passant par une propriété qui s’appelle Session. Dans l’exemple ci-dessous, nous utilisons une variable de type TableSchema (qui représente pour nous un schéma d’une table en base de données – c’est une classe que nous avons créé nous-même pour modéliser le schéma de notre base, ce la n’a rien à voir avec T4). Cela nous permet de générer un modèle POCO ou un mapping à partir d’une table donnée.

use_sessiont4

Nous verrons dans ce qui suit comment le code externe fournit la variable en question…

Lancer notre générateur à partir d’une application console

Dans le cas que je montre en exemple, nous avons juste besoin d’une application console très simple pour générer les codes et les cracher dans des fichiers. Pour cela, deux points sont à remarquer :

–          Un modèle tt est associé à un fichier cs qui porte le même nom. Ce fichier cs décrit en fait un objet que l’on peut utiliser pour générer le code proprement dit. Cet objet a une propriété Session (une variable de type dictionnaire) dans laquelle nous pouvons passer n’importe quel type d’objet. Et ce sera utilisé à l’intérieur du template lorsque ce dernier va générer le code.

–          L’objet associé à notre modèle possède aussi une méthode particulière qui s’appelle TransformText() qui permet de générer le code en interprétant les balises T4 à l’intérieur. C’est comme un moteur asp.net qui interprète les balises asp.

Voici un bout de code qui après avoir parcouru les tables en bases de données, va générer pour chaque table les modèles POCOs, les mappings etc. Remarquez la façon de passer une variable vers le template, et l’appel à la méthode TransformText(). Le reste n’est que du code qui permet de créer des fichiers et des dossiers relatifs à la génération…

Pour les débutants : les interfaces/contrats en POO

août 23, 2012 1 commentaire

Quand j’ai commencé à programmer en Orienté-Objets, il y a quelques années de cela, j’avais du mal à comprendre l’utilité des interfaces. Pour ceux qui ne connaissent pas encore, un interface en POO est une définition d’objet sans les implémentations. Euh, c’est quoi ? un petit exemple :

Ici, on a un interface qui possède une méthode Refresh(), mais comme c’est un interface, la méthode Refresh() ne contient aucune implémentation. Et donc, on ne sait pas qu’est qu’elle va faire cette méthode… Un interface n’a donc aucune raison d’être si on ne décrit pas l’implémentation (ou les implémentations) qui va derrière. En C#, écrire qu’une classe implémente un interface c’est comme écrire un héritage, donc avec le caractère « : »

Ma première question en tant que débutant à l’époque c’est : pourquoi on perd du temps à écrire le contenu de IRefreshable, alors que cela ne servira a priori à rien car le code qui va faire quelque chose se trouve dans l’implémentation. Dans cet exemple, écrire uniquement le contenu de MyFirstRefreshable doit être suffisant, non ?

Et bien, la réponse, c’est que cela dépend !

En effet, le code utilisateur (le code qui va utiliser MyRefreshable) n’est pas sensé connaître ce que va faire la méthode Refresh(). Pour le code utilisateur, l’important est de savoir que face à un objet « IRefreshable », il a une méthode Refresh(), qui comme son nom l’indique, est sensé faire un refresh de quelque chose. Imaginons que l’assembly qui contient notre interface IRefreshable est un boitier qui communique de deux côtés : un côté avec le code utilisateur et un autre avec le code qui implémente notre interface (l’assembly qui contient MyFirstRefreshable).

– La communication avec le code utilisateur est du genre :  » voici un objet IRefreshable, et comme c’est un objet IRefreshable, il a une méthode Refresh(), alors utilises-le si tu en as besoin ! »

– La communication avec le code d’implémentation est du genre :  » si tu veux me fournir un objet IRefreshable, tu dois respecter un contrat : tout objet IRefreshable possède obligatoirement une méthode Refresh()… ».

Pas clair ? euh. Prenons un exemple plus ou moins bête :). Imaginons que l’assembly qui contient IRefreshable est un fabricant de PC (un ordi) qui sont munis de ports USB. Et bien, c’est comme si ce fabricant discute avec les fournisseurs de périphériques USB ainsi qu’aux utilisateurs de ports USB comme suit :

« Voici la forme d’un port USB, avec telle dimension. Pour échanger des données avec ce type de port , il faut respecter tel ou tel fréquence, tel ou tel amplitude de courant, etc. Donc si vous voulez être un fournisseur de port USB, il faut respecter tout ça. Et de la même manière, pour tout ce qui veut utiliser un port USB, sachez que ce type de port possède les caractéristiques suivantes : … une fois que vous connaissez ces caractéristiques, utilisez-le comme bon vous semble. »

Autrement dit, ce fabricant  présente aux utilisateurs ce qu’est un port USB et ce qu’il peut faire => il leur présente un « interface » . L’utilisateur s’en fout de comment cela fonctionne derrière, mais il sait que cela fait ce qu’il veut et il l’utilise ! Et de l’autre côté, le fabricant impose aux fournisseurs de port USB de respecter tel ou tel caractéristiques pour que le port fonctionne comme les utilisateurs l’attendent => il leur présente un « contrat ». C’est en ce sens que le terme « interface »  signifie aussi « contrat » dans le monde de la POO. En fait, l’appelation « interface » ou « contrat » dépend de quel côté on regarde (du côté de ce qui utilise ou de ce qui implémente).

Et alors ? Dans quel but a-t-on besoin des interfaces ?

L’assembly ou tout simplement la couche qui expose l’interface (dans l’exemple le fabricant de PC) laisse donc libre voie aux couches ou classes externes qui veulent implémenter l’interface. En ce sens, cela permet :

1. de séparer les problématiques de définition et d’implémentation. Car la couche qui définit juste l’interface est sensée faire autre chose que décrire ce qu’un objet Ixxxx doit faire. Elle manipule par exemple ces objets pour les exposer à la couche d’utilisation…

2. d’avoir plusieurs implémentations différentes – voire des implémentations dans plusieurs couches diverses. C’est comme si on peut avoir beaucoup de fournisseurs de ports Usb, l’essentiel c’est que  » c’est un port USB », et que cela s’utilise bien avec un PC.

3. de faire abstraction des implémentations concrètes pour le code utilisateur. Quand un utilisateur branche quelque chose sur un port USB, il s’en fout pas mal de quel constructeur vient le port en question. En tout cas, c’est pas son problème de savoir comment cela fonctionne derrière.

Le framework .Net expose par exemple divers interfaces, à ne citer que les plus utilisés en pratique comme les IList, IEnumerable, IQueryable, IComparer, etc. Vous pouvez vous même définir un objet IList ou un objet IQueryable, mais à condition que vous respectez le contrat indiqué pour ces interfaces, i.e. que vous devez décrire toutes les méthodes/membres et propriétés imposés par ces interfaces. Une fois vous avez fourni des implémentations, le framework peut utiliser votre objet en tant que Ixxxx lorsqu’il a besoin, et votre objet Ixxxx est utilisable comme tel par un utilisateur de votre code. Voici un exemple beaucoup plus pratique :

Vous remarquez en tant que développeur que vous avez certains types d’objets en .Net, sur lesquels vous pouvez parcourir le contenu par un « foreach ». Si vous avez par exemple un objet List<String> (liste de string), vous pouvez faire un foreach sur cet objet pour parcourir tous les « string » qui sont à l’intérieur… Pourquoi vous pouvez faire appel à un foreach sur cet objet alors que sur d’autres objets, vous ne pouvez pas le faire. C’est parce que le type List<String> est un type qui implémente l’interface IEnumerable<String> (comme son nom l’indique, c’est un objet qu’on peut énumérer – donc qu’on peut parcourir ! Vous pouvez définir un objet IEnumerable mais ensuite vous devez décrire (implémenter) tout ce qu’un IEnumerable doit faire. Et une fois l’implémentation faite, votre objet IEnumerable peut s’utiliser avec un foreach (on peut l’énumérer). Ci-dessous, on a un exemple simple : une classe MyEnumerable qui implémente IEnumerable<String> (quelque chose dans laquelle on peut parcourir (foreach) et à chaque élément parcouru : on a un String).

Dans un code externe qui utilise notre objet MyEnumerable, on peut bien faire appel à un foreach !

Si on revient à notre petite caricature toute bête, le code qui implémente MyEnumerable est comme le fournisseur de port Usb. Il respecte le contrat en décrivant ce que fait un MyEnumerable. Tandis que la classe Utilisation (ci-dessus) est comme l’utilisateur de port Usb. Il s’en fout de comment MyEnumerable se débrouille pour qu’on puisse écrire un « foreach » avec, mais il l’utilise car c’est sensé être utilisé comme tel !