65 votes

Validation dans une conception axée sur le domaine

Comment traitez-vous avec validation sur des agrégats complexes dans un domain driven design? Avez-vous consolider vos règles de gestion/validation de la logique?

Je comprends l'argument de validation. Et je comprends validation de propriété qui peut être fixé sur les modèles eux-mêmes et de faire des choses comme pour vérifier qu'une adresse email ou un code postal valide ou qu'un prénom a une longueur minimale et maximale.

Mais qu'en est complexe de validation qui implique plusieurs modèles? Où avez-vous l'habitude de ces règles et méthodes au sein de votre architecture? Et quels modèles si tout utilisez-vous pour les mettre en œuvre?

65voto

Ben Scheirman Points 23590

Au lieu de s'appuyer sur IsValid(xx) des appels partout dans votre application, envisager de prendre quelques conseils de Greg Young:

Ne laissez jamais vos entités entrer dans un état non valide.

Ce que cela signifie essentiellement, c'est que la transition entre la pensée des entités comme des pur conteneurs de données et plus sur les objets à l'aide de comportements.

Prenons l'exemple d'une adresse de la personne:

 person.Address = "123 my street";
 person.City = "Houston";
 person.State = "TX";
 person.Zip = 12345;

Entre l'un quelconque de ces appels de votre entité n'est pas valide (parce que vous auriez des propriétés qui ne sont pas d'accord les uns avec les autres. Maintenant, considérez ceci:

person.ChangeAddress(.......);

tous les appels concernant le comportement de changement d'adresse sont maintenant une unité atomique. Votre entité n'est jamais non valide ici.

Si vous prenez cette idée de la modélisation de comportements plutôt que d'état, alors vous pouvez arriver à un modèle qui ne permet pas non valide entités.

Pour une bonne discussion, consulter cette infoq interview: http://www.infoq.com/interviews/greg-young-ddd

39voto

David Negron Points 971

J'aime Jimmy Bogard la solution à ce problème. Il a un post sur son blog intitulé "Entité de validation avec les visiteurs et les méthodes d'extension" , dans lequel il présente une approche très élégante à l'entité de validation qui suggèrent la mise en œuvre d'une catégorie distincte pour stocker le code de validation.

public interface IValidator<T>
{
    bool IsValid(T entity);
    IEnumerable<string> BrokenRules(T entity);
}

public class OrderPersistenceValidator : IValidator<Order>
{
    public bool IsValid(Order entity)
    {
        return BrokenRules(entity).Count() > 0;
    }

    public IEnumerable<string> BrokenRules(Order entity)
    {
        if (entity.Id < 0)
            yield return "Id cannot be less than 0.";

        if (string.IsNullOrEmpty(entity.Customer))
            yield return "Must include a customer.";

        yield break;
    }
}

6voto

J'utilise généralement une spécification de la classe, il fournit une méthode (c'est le C#, mais vous pouvez le traduire dans toutes les langues) :

bool IsVerifiedBy(TEntity candidate)

Cette méthode effectue une vérification complète du candidat et de ses relations. Vous pouvez utiliser des arguments dans la spécification de la classe pour en faire paramétrée, comme un niveau de contrôle...

Vous pouvez également ajouter une méthode pour savoir pourquoi le candidat n'a pas à vérifier les spécifications :

IEnumerable<string> BrokenRules(TEntity canditate)

Vous pouvez simplement décider de mettre en œuvre la première méthode comme ceci :

bool IsVerifiedBy(TEntity candidate)
{
  return BrokenRules(candidate).IsEmpty();
}

Pour les brisures de règles, j'ai devriez écrire un itérateur :

IEnumerable<string> BrokenRules(TEntity candidate)
{
  if (someComplexCondition)
      yield return "Message describing cleary what is wrong...";
  if (someOtherCondition) 
      yield return
   string.Format("The amount should not be {0} when the state is {1}",
        amount, state);
}

Pour la localisation, vous devez utiliser les ressources, et pourquoi pas, de passer d'une culture à l'BrokenRules méthode. Je place cette classes dans l'espace de noms de modèle avec un nom qui suggère leur utilisation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X