Archive

Archive for the ‘Pattern’ 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

Inversion de contrôle et injection de dépendance, ça se mange ?

mars 13, 2013 4 commentaires

Inversion de contrôle (IoC) et injection de dépendance (DI), ça se mange ?

Et bien non 😀

Ce post ne prétend pas être un vrai cours sur l’Inversion de contrôle (ou IoC). Pour y aller plus loin, je vous conseille de visiter le site de Windsor Castle ( http://www.castleproject.org/), ou celui de Unity (http://unity.codeplex.com/), ou d’autres pour les autres technos OO comme Java…

Néanmoins, pour ceux qui débutent, ce post peut servir, du moins pour avoir en tête ce que IoC et DI veulent dire. A priori, ces deux termes signifient pratiquement la même chose, mais à mon avis; parler de IoC ou de DI, dépend de l’angle prise pour observer le système mis en place.

IoC, pourquoi ?

Dans la plupart des architectures logicielles, au début de la tendance vers la conception orientée-objets; les différentes couches se dépendent de façon hiérarchique. Par exemple, dans une application simple et classique de gestion qui interagit avec une base de données, on a généralement le type de dépendance suivant : la couche présentation dépend de la couche métier, et puis la couche métier dépend de la couche d’accès aux données, … Ceci peut être schématisé comme suit (remarquez les sens des flèches : couche x => couche y (couche  x dépend de y)

Architecture_simple

 

 

Un peu plus tard, les architectes et développeurs se sont rendus très vite que si la couche métier dépend de la couche d’accès aux données, on est sujet à trois problèmes (et peut-être d’autres) :

1. le métier ne peut pas évoluer tout seul, car il dépend de la couche d’accès aux données. Autrement dit, la couche de données connaît toutes les évolutions du métier, ce qui n’est pas souhaitable car dans ce cas, pourquoi on les sépare en deux couches distinctes ?

2. le métier n’est pas testable « unitairement », car pour pouvoir l’exécuter, il faut que la couche de données existe et tourne avec lui.

3. si on veut changer de couche d’accès aux données, la couche métier doit s’adapter à la nouvelle couche. Alors que comme son nom l’indique, c’est une couche « Métier », c’est elle qui doit diriger tout dans l’architecture…

Il faut alors inverser la dépendance entre ces deux couches, et faire en sorte que le métier soit le centre. Autant que possible, il faut que les autres couches dépendent du métier, et non l’inverse. C’est à partir de cette idée comme quoi l’architecture soit focalisée au métier, qu’est venu – à mon avis – le terme : Domain Driven Design (conception orientée domaine (sous-entendu métier)) => c’est lé métier qui dirige tout, et tout (ou presque tout) doit dépendre du métier. Lorsqu’ on inverse la dépendance entre les couches pour que le métier soit le centre, on fait techniquement une « Inversion de contrôle » (IoC). Dans le schéma ci-dessus, imaginez juste que la flèche qui monte du métier vers la couche de données se dirige dans le sens inverse.

Comment on fait pratiquement ? La réponse sera sujet à un autre poste (pour que nous nous embrouillions pas dans du code mais juste dans l’explication)…

 

Si Inversion de contrôle, alors Injection de dépendance !

Maintenant, comme la couche métier est le centre de l’architecture, la couche présentation ainsi que la couche de données, et d’autres (…) dépendent donc du métier. Mais lorsqu’on écrira nos premiers codes de CRUD (ou pour commencer juste une requête) : on constatera rapidement que la couche présentation ne pourra pas s’exécuter car il ne dépend que de la couche « métier » (ce qui est bien 🙂 ), et comme cette couche métier ne dépend plus de la couche d’accès aux données; cette couche de données n’est plus accessible à la présentation (même d’une façon indirecte). Ce qui veut dire simplement que la couche présentation ne peut plus manipuler les données, même à travers la couche métier. Ce qui est insensé dans une application de gestion !

Il faut alors permettre à la couche présentation d’avoir une visibilité des couches environnantes au métier pour qu’au final, cette couche (la plus basse) puisse exploiter « indirectement » les autres couches, entre autres celle qui accède aux données. Autrement dit, il faut « injecter » à la couche d’utilisation (ici la présentation) les dépendances aux autres couches qui dépendent du métier, d’où le terme « Injection de dépendance« . C’est pourquoi je disais plus haut : l’appellation IoC ou DI dépend de l’angle d’où on regarde l’architecture… Dans la pratique, afin de pouvoir réaliser cette injection de dépendance, on fait appel à des outils tiers comme Windsor Castle ou Microsoft Unity dans le cas des technologies .Net.

architecture_IoC

 

Et pour les vrais débutants en POO, ne vous aventurez pas dans les IoC ni les DI, qu’après avoir maîtrisé l’utilisation (et donc l’utilité ou l’inutilité) des interfaces.

Catégories :Pattern