Published by

Il y a 13 ans -

Temps de lecture 9 minutes

Le pattern Specification pour la gestion de vos règles métier

Souvent lorsque l’on parle de gérer les règles métiers, on pense à moteur de règle, pas forcement …

Le design pattern Specification est une solution de gestion de vos règles métiers.

Ce pattern a été formalisé par Eric Evans, père du DDD, et Martin Fowler que l’on ne présente plus.

Ce pattern est simple mais très puissant. Il permet de :

  • marquer et identifier les règles métiers,
  • les centraliser,
  • les réutiliser,
  • communiquer entre développeurs et fonctionnels sur ces règles métiers.

Cette solution a récemment été mise en place sur un gros site d’eCommerce en France. Je partage ici avec vous mon retour d’expérience, donc laissez vous convaincre !

Allo Houston ? On a un problème

Prenons un exemple simple mais significatif, un site d’eCommerce de fruits et légumes.

Supposons que l’on parte d’un besoin simple, exprimé par Ted, notre expert fonctionnel : « En tant qu’internaute, je veux ajouter des produits (donc des fruits ou/et légumes) à mon panier ».

Bob, Le valeureux développeur, n’hésite pas un seul instant et réalise la besogne de la manière suivante :

Collection panier = new Set();

panier.add(new FraiseDePlougastel(5, Unite.BARQUETTE));
panier.add(new PommeDeTerreBinch(2, Unite.KILO));

Le développeur se dit « Trop facile pour que se soit ça … », réfléchit,  » Je sais, on peut pas ajouter à l’infini ! On doit de se limiter à une valeur réaliste, par exemple 10 Kilogrammes de produit par panier »

Bob aime le travail bien fait et décide de refactorer son code de la manière suivante afin de s’adapter au mieux à une solution réaliste :

public class Panier {
   private static final double LIMITE_DE_POIDS = 10.0;

   private Collection contenu = new Set();

   public double getPoidsEnKilo() {
     ...
   }

   public void ajouter(Produit produit) {
     // TODO Bob : gerer pre condition suivant besoin de Ted
     if (getPoidsEnKilo() + produit.getPoidsEnKilo() < LIMITE_DE_POIDS) {
         contenu.add(produit);
     }
   }
}

Une fois le refactoring effectué, Bob s'empresse de remonter le problème à son expert fonctionnel préféré. Ted, ne niant pas la faille, indique à Bob qu'il va revoir son besoin. Mais que pour cela il a besoin d'un peu de réflexion.

Le temps de la réflexion pris, Ted revient vers Bob avec un besoin affiné :

"En tant qu'internaute habitant en Ile de France, je veux ajouter jusqu'à 100 kilos de produit à mon panier"
"En tant qu'internaute de France métropolitaine, je veux ajouter jusqu'à 25 kilos de produit à mon panier"
"En tant qu'internaute des DOM/TOM, je veux ajouter jusqu'à 10 kilos de produit supportant le transport en avion à mon panier"

Bob, devenu tout blanc : "Ça va être compliqué à implémenter"
Ted : "Oui, mais j'ai un super transporteur en ile de france, commercialement je ne peux pas m'en passer"
Ted, pour rassurer Bob : "T'inquiètes pas dans 3 mois, on changera tout ca, on aura de nouveaux transporteurs"
Bob : "Ah, mais on sera déjà en production ..."

Les affaires se compliquent pour le pauvre Bob, comment va t'on pouvoir l'aider?

Description du problème à résoudre

Tout d'abord, une application "n'est qu'une" succession d'évaluations de règles métiers qui sont structurées et hiérarchisées.
Ces règles sont de complexité et de durée de vie très variable.

En discutant avec des référents fonctionnels, j'ai pu sentir une certaine frustration sur la gestion des règles métiers. Cette frustration se ressent encore plus sur les micros règles que l'on change fréquemment.
En effet, ils aimeraient avoir une forte visibilité sur ces règles métiers : "est ce que la documentation décrit correctement le code?". De plus, ils aimeraient avoir une plus grande réactivité sur l'évolution de ces règles.

Sans formalisme pour gérer toutes ces règles mouvantes, il y a une probabilité importante pour que l'on introduise une dette technique dans l'application :

  • règles perdues et dissimulées dans le code,
  • implémentation de règles dupliquées,
  • règles difficilement modifiables.

Tout le monde a autour de lui un exemple d'abandon de code. C'est un cercle vicieux. En effet, moins on connait un code et moins on va essayer de le modifier ; moins on va essayer de le modifier et moins on connaîtra le code ... (bouclez ! on se retrouve à la réécriture complète de ce code).
Pour les règles métiers qui mettent en avant une stratégie commerciale cela n'est pas acceptable.
Il faut avoir une grande réactivité et une très bonne gestion du changement. Il faut donc une excellente connaissance de l'implémentation de la part des développeurs et des fonctionnels.

Description de la solution

Ainsi, idéalement un expert fonctionnel aimerait :

  • définir une règle métier,
  • composer plusieurs règles métiers,
  • avoir l'état exact d'implémentation des règles métiers tel que développé dans le code source (aux valeurs près !), et
  • activer/désactiver une règle rapidement, souvent sans redémarrage des serveurs d'application.

Pour faciliter la maintenance d'un tel modèle, la solution suivante peut être mise en place : l'utilisation du Pattern Specification.

L'implémentation d'une règle métier suit le contrat d'utilisation suivant :

public interface Specification {
    public boolean isSatisfiedBy(T candidate);

    public Specification or(Specification specification);
    public Specification and(Specification specification);
    public Specification not();
}

une méthode issatisfiedby détermine si la règle métier est respectée. les trois autres méthodes, or, and et not permettent de combiner les règles métiers entre elles.

Il y a trois classes utilitaires permettant d'implémenter les opérateurs :

  • AndSpecification
  • OrSpecification
  • NotSpecification

Par exemple la classe AndSpecification :

public class AndSpecification extends AbstractCompositeSpecification {

    @Override
    public boolean isSatisfiedBy(final T candidate) {
        boolean result = true;

        for (Specification specification : this.specifications) {
            result &= specification.isSatisfiedBy(candidate);
        }
        return result;
    }

    public AndSpecification(Specification... specifications) {
        super(specifications);
    }
}

Les règles métiers étendent la classe LeafSpecification :

public abstract class LeafSpecification extends AbstractCompositeSpecification {
    public abstract boolean isSatisfiedBy(T candidate);
}

Exemples de règles

La règle RegleProduitsDuPanierSontDeSaison permet de déterminer si tous les produits du panier sont de saison.

public class RegleProduitsDuPanierSontDeSaison extends LeafSpecification{
    public boolean isSatisfiedBy(Panier panier) {
	for (Produit produit : panier.getProduits()) {
	    if (!Mois.estDeSaison(produit.getMoisDeSaison())) {
		return false;
	    }
	}
	return true;
    }
}

La règle RegleProduitsDuPanierSontOranges permet de déterminer si tous les produits du panier sont oranges.

public class RegleProduitsDuPanierSontOranges extends LeafSpecification {
    public boolean isSatisfiedBy(Panier panier) {
	for (Produit produit : panier.getProduits()) {
	    if ( ! (produit instanceof Abricot
		    || produit instanceof Carotte
		    || produit instanceof Citrouille
		    || produit instanceof Mandarine
		    || produit instanceof Orange)) {
		return false;
	    }
	}
	return true;
    }
}

La règle ReglePromoJAimeLesProduitsOranges se repose sur la composition des deux règles précédentes. Si les deux règles précédentes sont respectées alors la commande du client sera éligible à la promotion J'aime les produits oranges !

public class ReglePromoJAimeLesProduitsOranges extends LeafSpecification {
    RegleProduitsDuPanierSontOranges regleProduitsDuPanierSontOranges = new RegleProduitsDuPanierSontOranges();
    RegleProduitsDuPanierSontDeSaison regleProduitsDuPanierSontDeSaison = new RegleProduitsDuPanierSontDeSaison();

    public boolean isSatisfiedBy(Panier panier) {
	return regleProduitsDuPanierSontDeSaison.and(regleProduitsDuPanierSontOranges).isSatisfiedBy(panier);
    }
}

Documentation

La solution est fiable, si et seulement si les développeurs et les fonctionnels connaissent précisément l'implémentation de ces règles.
Il faut donc une solution rigoureuse. La solution ne sera rigoureuse que si le développeur est rigoureux dans sa documentation : une modification dans le code implique une modification dans la documentation. Les règles métiers sont volontairement limitées à un nombre de traitements restreints afin d'alléger ce travail de documentation. Par la même occasion, la documentation sera moins longue et donc plus abordable pour un humain.

Voici un exemple de patron de documentation pour une règle métier :

Nom Nom de la classe qui correspond à la classe en Java (donc sans d'accent, sans espace, et qui ne commence pas par un chiffre)
Cas d'utilisation Où on utilise cette règle
Dépendance Il est possible de combiner les règles. Une règle peut être simplement une combinaison d'autres règles
Données en entrée Quelles sont les données analysées
Description & algorithme métier Décrire le plus précisément possible la règle métier (à la valeur près)
Configurabilité Indiquer si la règle est modifiable, activable, desactivable à chaud

Les règles métiers ont intérêt à être classées par package, un package par domaine fonctionnel.

Retour d'expérience

Cette solution a été mise en place sur un projet d'eCommerce à des fins de maintenance et de réactivité aux demandes d'évolution. Après 6 mois, l'équipe est satisfaite du résultat voire même un peu bluffée.

En effet, les équipes fonctionnels avaient émis un besoin fort de pouvoir gérer les règles.

Pour cela, l'équipe technique a entrepris une étude. Cette étude avait une double fonction :

  • spécifier le besoin, et
  • comparer les différentes solutions pour répondre à ce besoin.

Lors de l'étude, différents moteurs de règle Drools, Jess, Java Rules Engine, Groovy Rules, etc., ont été comparés. Aucune solution, hormis Drools, ne nous semblait fiable. Drools était quant à lui trop complexe pour notre besoin.
La solution pattern est intéressante car conceptuellement et techniquement très simple.

Si les développeurs et les fonctionnels jouent le jeu de la documentation, alors on a une vraie maitrise des règles métiers. Ce dernier point reste le plus risqué mais cela ne dépend que des acteurs du projet.

De plus, cette solution nous a permis de gagner du temps :

  • Le développement du code du pattern Specification est rapide (quelques jours) par rapport à l'intégration et de la mise en place de bonnes pratiques sur un framework. Par exemple avec Drools, il faut plusieurs mois pour avoir une bonne maitrise technique.
  • Cout de formation des autres développeurs très peu élévé toujours par rapport à Drools.
  • Le temps et les efforts de développement et documentation sont peu élévés, on ne fait que du Java sans artifice et un peu de documentation.

Conclusion

Le pattern Specification est une alternative sérieuse au choix d'un moteur de règle. En effet, bien souvent l'utilisation de ce dernier est une solution démesurée par rapport à la complexité du besoin exprimé. Elle est moins risquée technologiquement (pas de formation, pas d'inconnue technique), moins couteuse et plus simple.

En agrémentant avec un peu de code utilitaire, il est facilement possible de rendre plus fonctionnelle notre modeste solution de gestion de règles métiers :

  • rechargement de règle à chaud,
  • activation et désactivation des règles à chaud,
  • monitoring et log des règles métiers.

Published by

Commentaire

25 réponses pour " Le pattern Specification pour la gestion de vos règles métier "

  1. Published by , Il y a 13 ans

    Bon article sur un pattern intéressant – et que l’on applique parfois sans le savoir. Ne va pas assez loin sur le rechargement à chaud mais bon, pas de souci particulier.
    Drools n’est pas si compliqué que cela, en tout cas ce sont des gens qui le maîtrisent bien qui m’ont dit ça. Une belle solution, mais ajouter encore un outil? A chacun de juger selon ses besoins et ses contraintes.

    Autre solution, que j’ai vu appliquée : au lieu d’avoir des des gens qui veulent n’importe quoi et qui oublient d’un jour sur l’autre ce qu’ils voulaient – Et oui…. ça peut amener à ça aussi, de donner la main sur les règles métier à des gens pas totalement férus de logique… – avoir une cellule archi/développement stable qui est garante des règles métier.

    Autre solution, le dsl. Sorte de sur-mesure de la gestion des règles métier. La création d’objets qui obéissent à un pattern aidera tout de même pas mal à la création d’un dsl. On le voit, dans le code présenté ici en exemple

    Bonne année, les xebia boys!

  2. Published by , Il y a 13 ans

    Juste pour pinailler, il semble bien que la règle RegleProduitsDuPanierSontOranges qui « permet de déterminer si tous les produits du panier sont oranges », ne détermine plutôt que la couleur du premier produit du panier.

  3. Published by , Il y a 13 ans

    Très bon article et très bonne idée de pattern. Le résultat fait assez DSL.

  4. Published by , Il y a 13 ans

    Le pattern Specification semble le mix des patterns Command et Composite.

    Je suis curieux de savoir pourquoi Drools semblait trop complexe…

    Sinon, à mi-chemin, comme mentionné dans un commentaire précédent, l’usage d’un DSL semble effectivement une option.

  5. Published by , Il y a 13 ans

    Nous utilisons ce pattern depuis plusieurs années pour vérifier les « invariants » d’une classe. C’est simple et efficace.
    Nos classes métier encapsulent bien sûr tous ces « invariants » (qui sont une partie des règles métier), et exposent uniquement la méthode estCoherent() au reste du monde. Ainsi on peut à tout moment vérifier la cohérence d’un objet ou d’un aggregat (Aggregate). Vive le DDD!!!

    Par contre, comment remonter -simplement- la bonne information en cas d’échec d’une des spécifications? Ceci est encore plus important si vous enchaînez plusieurs spécifications. C’est, à ce jour, la seule limite que nous avons trouvée à ce pattern…

    Au final, le plus important est de ce concentrer sur votre modèle Objet (anémique ou riche?). Le pattern Specification convient à un certain type de « règles métier », mais peut-être pas pour toutes (attention au marteau…).

    Merci pour vos articles et bonne année 2010!

  6. Published by , Il y a 13 ans

    Pattern très simple, souple pour vérifier des règles métiers ou les invariants d’un objet.

    Cependant je voudrais aller plus loin et retourner la ou les raisons de l’échec de l’application d’une règle métier afin que l’utilisateur sache où corriger son erreur. J’ai fait en sorte que la spécification retourne une paire contenant le boolean classique et la raison de l’échec si false.
    Là, j’ai un problème…
    En effet les combinaisons de spécifications peuvent être complexes, et par conséquent la raison de l’échec est difficilement exprimable. Peut être est-ce normal; ou alors je m’y prends mal.

    Quelqu’un aurait une idée?

  7. Published by , Il y a 13 ans

    Moi ça me fait penser au pattern décorateur (un café crème, un café crème sucré, un café sucré…), avec des règles de composition mieux précisées, et un test d’accord.

    Je trouve ça pas mal, peut être faudrait-il y adjoindre un contexte d’opération ? Les règles sont souvent intitulées xxxDuPanierYyy, cela ne serait pas mieux que de formaliser ce DuPanier, histoire de ne pas appliquer des règles DuPanier à des objets DeLivraison, par exemple ?

    Moi aussi j’ai beaucoup lorgné du coté de drools, toujours pour conclure avec grand regret que c’était trop compliqué pour moi. Si quelqu’un peut me démontrer que je me suis trompé, j’en serais fort content. J’en suis arrivé à penser qu’on pouvait peut être traiter les règles par un jeu de routes à la mode Camel, mais j’en suis aux supputations des considérations.

  8. Published by , Il y a 13 ans

    Bonjour, merci pour vos commentaires

    – gestion de règle à chaud –

    @Ga.K

    Concernant la gestion de règle à chaud c’est assez simple, en fait notre solution finale combine une solution Java avec ce pattern et du Groovy, pour sa syntaxe puissante. De plus on utilise le module Spring pour le support dynamique de langage : http://static.springsource.org/spring/docs/2.0.x/reference/dynamic-language.html.
    Donc la modification de certaines règles se résume à un redéploiement des fichiers Groovy, après Spring fait le reste ;). Après il faut trouver un bon compris entre développement en Java et Groovy.

  9. Published by , Il y a 13 ans

    – Drools –

    Petite exclusivité, la semaine prochaine, il y aura un prochain article sur Drools ;). Selon moi ce pattern peut rapidement être mis en place avec un cout et temps minimum dans les équipes de développement, contrairement à Drools. Drools est un framework assez complexe mais pas insurmontable. Ce framework a de nombreux avantages, mais les fonctionnalités doivent bien être maitrisées afin de se lancer (DSL, table de décision via fichier Excel, IHM, langage MVEL (drools), … ).

    Drools demande de former les développeurs et de faire idéalement un prototype. Cependant Drools est relativement facilement intégrable dans un projet existant. On peut envisager d’intégrer en douceur Drools c’est à dire algorithme par algorithme.

  10. Published by , Il y a 13 ans

    @ym

    Merci tu as détecté un bug :). J’ai corrigé mais je suis par forcement satisfait du résultat :

    public class RegleProduitsDuPanierSontOranges extends LeafSpecification {
    public boolean isSatisfiedBy(Panier panier) {
    for (Produit produit : panier.getProduits()) {
    if ( ! (produit instanceof Abricot
    || produit instanceof Carotte
    || produit instanceof Citrouille
    || produit instanceof Mandarine
    || produit instanceof Orange)) {
    return false;
    }
    }
    return true;
    }
    }

    Je ne voulais pas en parler dans l’article mais on peut aussi utiliser une sorte de pattern visiteur, par exemple un parcours en « et » sur les produits d’un panier.

    Par exemple la classe qui s’occupe du parcours :

    public abstract class ParcoursEnEtSurProduitsDuPanier extends LeafSpecification {
    abstract protected boolean isProduitSatisfiedBy(Produit produit);
    public boolean isSatisfiedBy(Panier panier) {
    for (Produit produit : panier.getProduits()) {
    if ( ! isProduitSatisfiedBy(produit)) {
    return false;
    }
    }
    return true;
    }
    }

    La classe qui implémente la règle sur un produit :


    public class RegleProduitEstOrange extends ParcoursEnEtSurProduitsDuPanier {
    protected boolean isProduitSatisfiedBy(Produit produit) {
    if (produit instanceof Abricot
    || produit instanceof Carotte
    || produit instanceof Citrouille
    || produit instanceof Mandarine
    || produit instanceof Orange) {
    return true;
    }
    return false;
    }
    }

    Voila je pense que c’est un peu plus lisible.

  11. Published by , Il y a 13 ans

    Le pattern me semble plutôt intéressant. Il permet de formaliser les règles et de les isoler.
    Par contre je ne suis pas sûr de comprendre tout : Dans l’exemple cité, hormis le fait de savoir si le client est en France métropolitaine, en Ile de France ou pas, il faut aussi gérer les conséquence des ces règles càd la limite de poids de 10 kg de 100kg ou de 25kg.

    Le pattern semble gérer le « SI » mais pas le « ALORS » contrairement à ce que ferait un Drools. Comment gérer de façon propre et isolé ces « constantes » de poids qui finalement risque de changer plus rapidement que les règles définissant si le client et de France métropolitaine ou pas ?

  12. Published by , Il y a 13 ans

    Ca n’existerait pas déjà sous le nom de Closures et Predicates tout ça ? hmm ?

    Merci pour le travail de rédaction.

  13. Published by , Il y a 13 ans

    – Contexte –

    @Dun, pour gérer un contexte il y a deux possibilités. 1 – soit tu gardes le modèle de l’article avec les règles qui prennent en argument des objets du modèle. Tu géres le « ALORS » en dehors des règles.
    2 – Sinon tu peux te rapprocher d’un modèle à la Drools. Tu as des règles fines qui utilisent les objets du domaine. Tu as un (ou des) règle de plus haut niveau qui eux utilisent un objet contexte. Dans cet objet contexte on peut injecter un service à appeler dans le « ALORS »,
    @Herve A. ce contexte peut aussi servir avoir une trace de l’information ou un état d’exécution.

    Par exemple je prends un cas concret. Prenons un algorithme métier pour l’éligibilité des moyens de livraison en fonction du panier. Il faut donc créer un objet contexte à cet algorithme qui va contenir les données d’entrée (le panier, ou autre) et les données de sortis, les moyens de livraison et le prix associé. On a donc maintenant des règles qui sont capables de calculer un resultat plus évolué que « oui » / « non ».

  14. Published by , Il y a 13 ans

    Bonjour,
    Merci pour cet article très intéressant qui permet de mettre un nom et une spécification sur une conception que nous utilisons souvent sans le savoir.

    J’aurai une petite question à vous posez.
    Ce pattern – comme de nombreux autres – s’applique sur la couche métier de nos architectures.
    Comment peut-on l’utiliser au niveau de la couche de persistance ?

    Au sein de mon entreprise, nous avons des règles métier qui vont surement évoluées dans le temps.
    Ces règles nous permettent de savoir quelles données nous devons remonter de la base de données vers la présentation utilisateur.
    Par exemple, nous avons une contrainte sur l’appartenance à un pays. Nous effectuons donc une requête SQL en ajoutant une condition sur une jointure.
    Sachant que nous utilisons cette condition sur l’ensemble des requêtes, si les règles métiers changent, nous devrons repasser sur l’ensemble de ces requêtes pour ajouter/enlever des conditions.
    On retrouve le pourquoi du comment du pattern Specification au niveau métier.

    Il est possible d’implémenter ce pattern pour l’accès aux données persistantes. Le soucis, c’est que chaque règle supplémentaire a un cout important car il s’agit d’un aller/retour vers la base de données. 3 milles produits x 4 règles, on explose le compteur rapidement avec 200 demandes simultanées.

    Avez-vous une solution implémentation du pattern Specification pour l’accès aux données ?

    Cordialement,
    Thomas Tourlourat – Armetiz.info

  15. Published by , Il y a 13 ans

    Bonjour,

    Dîtes moi si je me trompe mais n’y a-t-il pas une erreur dans votre diagramme de classe ? J’ai lu le PDF de Mr Fowler et il se trouve qu’une LeafSpecification n’est pas censée être une CompositeSpecification (cf. p12) Idem pour la NotSpecification.

    Cordialement,

    Mickaël.

  16. Published by , Il y a 13 ans

    Bonjour Mickaël,

    Je n’ose pas dire que Martin Fowler à tord et que j’ai raison ;). Voici mon explication :

    Il n’y a pas d’erreur dans mon diagramme de classe. J’ai sciemment fait hériter ma classe « LeafSpecification » de la classe parente « …CompositeSpecification ».

    Pour la simple est bonne raison que je voulais faire un DSL de toutes mes règles métiers (NB : ce n’est pas une obligation).

    Ainsi avec n’importe quelle règle métier je peux faire :

    regle1.and(regle2.or(regle3. … ))).and(…).or(…);

    J’aurais pû me contenter d’utiliser les opérateurs java mais on perd rapidement en lisibilité du code (surtout quand on veut gérer des règles prioritaires par rapport aux autres grâce au parenthèsage).

    En d’autres mots, je me suis permis d’apporter un petit gravion dans l’immense édifice qu’à réaliser maître Martin Fowler B-).

    Nicolas LC (Xebia)

  17. Published by , Il y a 12 ans

    Bonjour,

    Je démarre la mise en place de pattern pour l’implémentation de règles de gestion. Ce tuto m’a bien éclairé. J’ai néanmoins une question sur le contenu de la classe composite. Pourquoi contient elle un constructeur alors qu’elle est abstraite ?

    Pouvez vous publier son contenu ? (car j’ai un doute sur mon implémentation, actuellement ma classe composite implémente les méthodes and(), or().. de la manière suivante :

    public Specification and(Specification specification) {
    return new AndSpecification(this, specification);
    }

    Mais je n’ai pas de constructeur :)

    Merci !!

  18. Published by , Il y a 12 ans

    Merci Nico.

    Alors t ou maintenant ? (coachC si tu te rappel …)

  19. Published by , Il y a 9 ans

    Vous pourriez au minimum partager des sources quelque part !

    Cordialement,

  20. Published by , Il y a 6 ans

    Bonjour,

    J’ai beaucoup aimé votre article, et bien qu’ancien il est toujours d’actualité. L’ayant implémenté récemment, je l’ai modifié pour pouvoir créer mes spécification via des lambdas. Pour voir le code c’est ici : https://github.com/loicmathieu/dojo/tree/master/src/main/java/fr/loicmathieu/dojo/pattern/lambdaspec

    J’ai écrit un petit un petit article qui explique l’ajout des lambda au pattern :
    http://www.loicmathieu.fr/wordpress/index.php/informatique/le-pattern-de-specification-et-les-lambdas/

    Je me pose toujours la question de savoir si, malgès l’attractivité des lambdas ici pour la consision qu’elles apportent, ce n’est pas un anti-pattern pour le risque de lisibilité (si sur plusieurs ligne) et la non-réutilisabilité.

    Cordialement,
    Loïc

  21. Published by , Il y a 6 ans

    @Loïc La création d’une règle via les lambdas casse effectivement les principes de réutilisation et de centralisation. Puisse que chacun peut créer sa règle à la volée et qu’elle deviennent en quelques sortes des classes anonymes.

    Mais c’est quand même un bel exercice. ;)

  22. Published by , Il y a 5 ans

    J’ai un ptit problème avec ce pattern mais peut être que je le comprends mal, pour moi entre l’exemple de la class Panier et sa méthode ajouter et le pattern c’est pas la même chose, dans le premier cas on empêche l’entité de devenir invalide alors que dans le second avec isSatisfiedBy on teste si l’entité est toujours valide ce qui veut dire que je peux me retrouver avec une entité invalide et ça ça me dérange.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.