Archive for the 'Command Query Responsibility Segregation' Category

Build your own service bus – par ou commencer ?

Julien on nov 29th 2010

Quelle meilleure façon de réveiller ce blog que de parler de la dernière soirée Alt.net ? Soirée sur le thème de « Build your own service bus » et co-présentée par Romain Verdier et moi-même.

Comme faut pas pousser mémé, je me contenterai d’inclure les slides et je me concentrerai sur un point précis. D’autres personnes plus littéraires que moi auront probablement l'occasion de vous résumer la soirée ! :-)

 

Hey Julien, c’est marrant ton histoire, mais il est ou l’arrêt le plus proche pour monter dans ton bus?

Tout d’abord, il faut bien comprendre qu’un service bus n’est qu’un framework pour simplifier la communication dans un système distribué. Voici donc quelques idées à creuser pour assimiler les concepts…

 

1. Acquérir des notions de messaging

Je vous suggère notamment de regarder MSMQ (ou son pendant portable et open source : ActiveMQ) et RabbitMQ. Ce dernier à la particularité d’utiliser un broker (les queues sont donc distantes) tandis que MSMQ permet la communication point à point mais rend l’écriture de scénarios publish-subscribe plus complexe. Pourquoi ne pas développer un petit chat pour se faire la main ? Cet exercice vous forcera a explorer les différents modèles sur le PubSub ou encore à étudier un minimum la serialization (astuce : n’essayez pas de recoder un protocole de communication a base de commandes en texte comme le FTP, on peut faire plus sympa ! :-)) .

En bonus, je vous conseille vivement d’acheter ce livre pour noel :


Enterprise Integration Patterns
Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions

This book provides a consistent vocabulary and visual notation framework to describe large-scale integration solutions across many technologies. It also explores in detail the advantages and limitations of asynchronous messaging architectures. The authors present practical advice on designing code that connects an application to a messaging system, and provide extensive information to help you determine when to send a message, how to route it to the proper destination, and how to monitor the health of a messaging system. If you want to know how to manage, monitor, and maintain a messaging system once it is in use, get this book

 

2. Acquérir des notions d’architecture sur les systèmes distribués et la SOA

Comme expliqué plus haut, un service bus n’est qu’un framework. Avant de se lancer tête baissée, il faut comprendre les principes sous-jacents. Mon auteur préféré sur la question est Udi Dahan, l'homme derrière NServiceBus...
Udi étant un conférencier assez actif, il est facile de trouver nombre de ses présentations sur le net. En voici quelques une :

Et pour les plus curieux d'entre vous (disclaimer : on sort du cadre des service bus !) :

Enfin, si vous avez beaucoup de transport en commun, vous pouvez également trouver un paquet de podcasts :

 

3. Explorer les framework open sources

Et notamment leurs samples !

 

4. La méthode du Sioux !

Si vous ne connaissez rien a tout ça mais que vous déchirez quand même en développement, jetez un œil à notre dernière offre d'emploi et contactez-mois si ça vous intéresse ! On se fera un plaisir de partager avec vous tout ce qu'on sait ! :-)

Bon courage !

Filed in .NET, Alt.net, Command Query Responsibility Segregation, Rencontres Alt.net | One response so far

« Bounded contexts » et persistance

Julien on jan 18th 2010

Dans mon billet précédant, je faisais remarquer que la persistance pouvait être implémentée de différente façon au sein d'un même système dans le cadre d'une approche SOA/CQRS. Laissez moi clarifier ce que j'entends par cela (ou plutôt ce que j'ai appris du maitre, Udi Dahan !).

Il est possible de faire varier la persistance selon (au moins) 2 axes.

Tout d'abord, nous pouvons utiliser un ORM (Nhibernate, Entity Framework, etc) ou avoir une approche plus directe de type ado.net ou procédure stockée. L'idée ici est d'adapter la solution au contexte spécifique du cas d'utilisation.  Voici 2 exemples :

  • On souhaite mettre à jour l'ensemble des commande en cours d'un client pour changer le mode de livraison. Ce processus doit inspecter les commandes non traitées pour vérifier si le poids des colis est compatible avec le nouveau mode de livraison.
    => Ici, le processus de selection ést plus ou moins complexe ET le nombre de commandes en cours est probablement réduit. Un modèle objet est probablement adapté au traitement.
  • Notre système stocke des cours de bourse. Une société annonce un "split" (chaque action sera "coupée" en X de sorte que 1 action avant le split = X actions après le split. => Une société peut être amené à faire ce genre de choses quand elle estime qu'une action est devenue trop onéreuse). On souhaite appliquer le coefficient sur l'ensemble des cours stockés en base pour faciliter certains calculs. On a donc potentiellement des centaines ou des milliers de cours à mettre à jour.
    => Ici, utiliser un modèle objet n'a aucun sens. Une simple requête SQL du type "UPDATE quotes SET price = (price / X) WHERE ..." est clairement plus simple à mettre en œuvre et sera surtout beaucoup plus optimisée !

Peut importe la solution retenue, le plus important est d'assigner la responsabilité du schéma et la lecture/écriture à un seul et unique bounded context. Ce point est capital : il nous garantit de ne pas intégrer différents systèmes par l'intermédiaire d'un point central (la base de données relationnelles) qui sera :

  • difficile à faire évoluer, car couplé à l'ensemble du système
  • un point de défaillance unique
  • un goulot d'étranglement en terme de performances/montée en charge

Par conséquent, chaque bounded doit pouvoir faire évoluer sa persistance de façon transparente pour le reste du système, ce qui implique également que le support retenu peut être différent pour chaque cas (SQL, base objet, base de documents, fichier texte, etc).
Cependant, ce type de décisions sera fortement influencé par l'organisation interne du projet et la taille des équipes. Après tout, si chaque développeur choisit sa propre technologie, il sera difficile de coordoner le transfert de connaissance ou encore les backups. Il est donc tout à fait possible dans un premier temps de se limiter à un même support (ex : SQL Serveur) mais de séparer logiquement les bounded contexts en créeant des bases de données distinctes. Il faudra ensuite veiller à ce que les différents logins utilisé ait un accès limité à une seule et unique base.

Filed in Command Query Responsibility Segregation, Domain Driven Design | One response so far

« Command Query Responsibility Segregation » et « bounded contexts ».

Julien on jan 17th 2010

Je sors de mon sommeil pour aborder une question posée sur la mailing list française d'Alt.net qui me tient à coeur. Pour paraphraser, nous avons le cas d'un client qui devient privilégié sur un site de e-commerce, ce qui lui donne droit à une livraison expresse pour toutes ses commandes en cours. L'auteur de la question souhaite comprendre comment est réparti la logique (mise à jour du client / passage des commandes en cours à une livraison expresse) et pourquoi Udi Dahan considère que l'utilisation d'un modèle objet pour représenter le domaine est un détail d'implémentation dans le cadre d'une approche CQRS.

Voici mon interprétation après avoir assisté à la formation d'Udi sur le SOA :

Commençons par la répartition de la logique :

Dans cet exemple, notre commande "MakeCustomerPreferred" sera exécuté dans un bounded context (entendez "service") différent de celui qui gère les ventes en cours. "MakeCustomerPreferred" semble par exemple rattaché à un service de CRM ou de marketing. En conséquence, cette commande ne peut pas mettre à jour directement une entité du bounded context "ventes". Ce n'est pas sa responsabilité (pensez "loose coupling" !) et ce ne serait pas scalable. Une fois que "MakeCustomerPreferred" aura été exécuté, le message handler (l'unité qui va traiter une commande ou un évènement donné) pourra lever un évènement du type "CustomerBecamePreferred". Ce dernier pourra lui même être écouté par un autre bounded context, comme celui des ventes, qui pourra à son tours décider de mettre à jour son sous système en conséquence.

En ce qui concerne l'utilisation d'un modèle objet du domaine :

Quand on applique cette approche architecturale de façon globale, le choix d'utiliser un modèle objet ou une approche "transaction script" devient du cas par cas. Chaque message handler  étant indépendant, on est libre de choisir le meilleur outil pour chaque cas d'utilisation. Par exemple, si on ne fait que mettre à jour un champ d'une table : pas besoin d'ORM ! On pourrait tout à fait imaginer n'exécuter qu'une simple requête SQL de type UPDATE. Au contraire, si l'exécution d'une logique complexe fait parti du processus de mise à jour, alors il se peut qu'un modèle objet soit plus adéquat. (Et d'ailleurs, qui à dit que SQL était le système de persistance le plus adapté à notre cas d'utilisation? Tout dépend !)

Filed in Command Query Responsibility Segregation, Domain Driven Design | 5 responses so far