Question

Je fais des travaux de R & D, et en tant que tel h explorer les modèles de conception. J'ai récemment lu sur le modèle de spécification et a été renvoyé ce grand article.

je suis intrigué par la simplicité et la propreté du code, mais j'ai commencé à tirer des comparaisons à mettre en œuvre la même propreté en utilisant d'autres techniques.

Considérez le contrat d'interface suivante pour une couche de service:

public interface IFooDataService
{
   ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification);
   ICollection<Foo> GetFooByPredicate(Func<Foo,bool> predicate);
   ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs);
}

Alors, quelques points initiaux:

  • Les trois retour d'une collection d'objets Foo
  • Les trois prennent un seul argument
  • Méthode Spécification restreint l'accès aux exigences spécifiques
  • méthode de prédicats essentiellement aucune restriction
  • Rechercher args méthode limite l'accès aux exigences spécifiques

Maintenant, sur la mise en œuvre:

public ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification)
{
    return fooDataRepository
            .Find()
            .Where(f => specification.IsSatisfiedBy(f))
            .ToList();
}

public ICollection<Foo> GetFooByPredicate(Func<Foo, bool> predicate)
{
    return fooDataRepository
            .Find()
            .Where(predicate)
            .ToList();
}

public ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs)
{
    return fooDataRepository
            .Find()
            .WhereMeetsSearchCriteria(searchArgs)
            .ToList();
}

Points sur la mise en œuvre:

  • Tous les trois sont extrêmement simples dans la mise en œuvre (une ligne de code chaîné)
  • Spécification et recherche Args filtré de manière externe.
  • La méthode de recherche utilise simplement la méthode d'extension IEnumerable pour inspecter args

Alors, cela dit, dans quelles conditions voulez-vous utiliser l'une des techniques ci-dessus 3?

Mes pensées sur le modèle Spécification:

  • Nice en ce qu'elle isole les exigences d'affaires / domaine en composants réutilisables
  • Très facile à lire, fait parler de code anglais
  • Juste peu de code impliqués (interfaces, classes abstraites). Si je devais l'utiliser, je mettrais les abstractions dans un ensemble commun (donc je n'ai un tas de fichiers statiques dans ma solution).
  • Facile à modifier les exigences de la spécification que la modification, et non la couche de service.
  • testabilité suprême de la logique de domaine (spécifications)

Mes pensées sur les méthodes d'extension (Tubes et filtres):

  • 'Weighty' dans la logique, mais encore donner lieu à la même simplicité.
  • Isolate logique d'interrogation à partir de la couche de service des procédés statiques
  • nécessite encore « réflexion » de tri (inspection args de recherche fourni et la construction de la requête)
  • Permet à l'architecture de code (dépôt, couche de service) d'abord, sans y penser sur les exigences spécifiques de l'entreprise (ce qui est à portée de main dans certains scénarios)

Mes pensées sur prédicats Méthode:

  • peut-il être utilisé là où vous avez besoin d'un contrôle granulaire grossier sur les requêtes.
  • Bon pour les petits projets, où les spécifications peuvent être exagérez

Ma logique de pensée finale est que si vous travaillez sur une application métier complexe où les besoins d'affaires sont connus à l'avance, mais ils peuvent changer au fil du temps, alors j'utiliser modèle Spécification.

Mais pour une application qui est un « démarrage », à savoir les exigences évolueront au fil du temps et a une multitude de façons de récupérer des données sans validation complexe, j'utiliser les tuyaux et méthodes Filtres.

Que pensez-vous? Aucun d'entre vous rencontrez des problèmes avec l'une des méthodes ci-dessus? Toutes les recommandations?

A propos de lancer un nouveau projet de sorte que ces types de considérations sont critiques.

Merci pour l'aide.

EDIT de clarification sur le modèle spécification

Voici même utilisation du modèle de spécification.

Specification<Foo> someSpec; // Specification is an abstract class, implementing ISpecification<TEntity> members (And, Or, Not, IsSatisfiedBy).
someSpec = new AllFoosMustHaveABarSpecification(); // Simple class which inherits from Specification<Foo> class, overriding abstract method "IsSatisfiedBy" - which provides the actual business logic.    
ICollection<Foo> foos = fooDataService.GetFoosBySpecification(someSpec);
Était-ce utile?

La solution

De ma petite expérience:

  1. exigence de l'utilisateur toujours changer et je ne sais pas pourquoi mon patron permet toujours que les changements à venir. Donc +1 à la spécification
  2. programmeur ici est plus comme « ouvrier » que « travailleur du savoir ». Vous savez .. celui qui tape toute la journée. En utilisant spécification, je peux me assurer que tout le monde « types ». Ceci est soutenu par la nature de mon projet. Il a besoin de beaucoup de beaucoup différents la mise en œuvre dans le même but. Ne me demandez pas pourquoi.
  3. Utilisez un modèle de conception qui vous donne la plus haute modularité et la flexibilité et bien sûr testabilité. Voici une petite histoire.
    Dans un jour de beau, mon compagnon m'a dit qu'il a écrit une classe qui nous a permis de calculer 32 types de mode de calcul X. Et il déjà mis en œuvre tout cela. Hoho, qui était une telle programmation héroïque, je pense. Il a passé plusieurs semaines à faire que dans le milieu de la nuit. Il a cru qu'il était un bon programmeur donc il a insisté pour que tout le monde à utiliser son chef-d'œuvre.
    Nous, à ce moment-là, ne se soucient pas de tests unitaires nous avons donc utilisé son chef-d'œuvre. Ce qui est arrivé ensuite? Le code est écrasé tout le temps. Eh bien, à partir de ce moment-là j'ai réalisé l'importance de test et modularité unité sont.

Autres conseils

Eh bien, tout d'abord j'écrire la méthode prédicats, même si elle est seulement utilisé comme un détail de mise en œuvre privée pour les deux autres:

private ICollection<Foo> GetFoosBySpecification(Specification<Foo> spec) 
{ 
    return GetFooByPredicate(f => spec.IsSatisfiedBy(f));
} 

La fonction argument de recherche serait en une ligne similaire.

Au-delà de cela, je ne peux vraiment pas dire quoi que ce soit dans l'abstrait. Je dois en savoir plus sur la structure de données pour décider de la meilleure façon de les rechercher.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top