Разница между проверкой объекта и проверкой постоянства в DDD? - PullRequest
3 голосов
/ 10 января 2012

Прямо сейчас у меня есть сущность домена с именем StyleBundle. Это StyleBundle занимает список стилей:

public class StyleBundle
{
    public StyleBundle(List<Style> styles)
    {
        this.Styles = styles;
    }

    public IEnumerable<Style> Styles { get; private set;}
}

Итак, в моем оригинальном дизайне никогда не следует создавать StyleBundle с пустым списком стилей. Это правило, которое эксперты по доменам в основном считают хорошим.

Я написал это с помощью выражения guard в конструкторе:

if (styles.Count() == 0)
   throw new Exception("You must have at least one Style in a StyleBundle.");

, который убедился, что я не могу создать StyleBundle в недопустимом состоянии. Я думал, что здесь имеет смысл исключение, потому что StyleBundle, созданный без хотя бы одного стиля, был исключительным в системе.

Конечно, изменения произошли в течение остальной части проекта, и теперь у пользователя должна быть возможность создавать StyleBundle без стилей, но им нельзя разрешать PERSIST StyleBundle без стилей.

Так что теперь я смотрю на свое охранное предложение и понимаю, что больше не могу выбросить исключение из конструктора.

В дальнейшем у меня есть слой Service / Application, с которым взаимодействуют мои программные компоненты при работе с StyleBundles. В моем слое обслуживания у меня есть класс StyleBundleService, и этот класс предоставляет базовую функциональность пользовательскому интерфейсу ... среди них "CreateStyleBundle".

Похоже, мне нужно будет проверить мою Service Layer, чтобы увидеть, есть ли у StyleBundle какие-либо стили, прежде чем он будет сохранен в базе данных, но что-то в этом решении мне кажется "неправильным".

Кто-нибудь сталкивался с подобной вещью? В основном, различие между состоянием объекта, действительного, когда «новый» вверх, и состоянием того же объекта, когда дело доходит до постоянства?

Спасибо! Mike

Ответы [ 4 ]

6 голосов
/ 10 января 2012

Я бы добавил IsValid метод к вашей сущности.Это позволит проверить, находится ли сущность в настоящее время в допустимом состоянии (в вашем случае проверьте, есть ли стили).

Этот метод можно вызвать из вашего Repository, чтобы проверить, может ли сущность сохраняться.Вы можете добавить дополнительные правила к методу IsValid для конкретных объектов и реализовать что-то вроде набора ошибок проверки, если вы хотите создать значимое исключение.

1 голос
/ 11 января 2012

Существует несколько стратегий:

Некоторые разработчики предпочитают создавать в самой сущности 2 метода: один называется IsValid(), который проверяет сущность в терминах бизнес-правил (общая проверка), а другой - IsValidForPersistence(), который проверяет сущность на постоянство.

Относительно IsValid() Вместо этого я предпочитаю не разрешать недопустимое состояние в первую очередь путем проверки всех входных данных и поддерживать инварианты, которые я использую фабрикой или компоновщиком.

Вы можете проверить ссылку http://www.codethinked.com/thoughts-on-domain-validation-part-1 для некоторых мыслей.

1 голос
/ 10 января 2012

Расширение того, что сказал Ваутер, плюс удобные методы BeforeSaving и BeforeDeleting:

public interface IDomainObject<T>
{
    bool IsValid();
}

public interface IEntity<T> : IDomainObject<T>
{

}

public interface IAggregateRoot<T> : IEntity<T>
{
    void BeforeSaving();
    void BeforeDeleting();
}


public interface IAggregateRoot { //or simply IEntity depending on the model
   bool IsValid();
}

public class StyleBundle : IAggregateRoot<T> {
   return styles.Count() > 0
}

public class StyleBundleRepository : Repository<StyleBundle> {
}

public abstract class Repository<T> : IRepository<T> where T : class, IAggregateRoot<T> {

   public T Save(T t)
   {
      t.BeforeSaving(); //for all AggregateRoots, maybe logging what the aggregate was like before the changes

      if(!t.IsValid())
         throw Exeception("Entity invalid");

      EntityStore.Current.SaveChanges();         

      // "AfterSaving" here, i.e.: log how the entity looks after the update

   }
}

Редактировать: я лично не использую идею IsValid, я использую полный класс EntityValidationErrors, где я могу сообщить клиентучто было не так, прежде чем пытаться сохранить, вещи, которые не должны быть нулевыми, не должны быть пустыми (например, ваши стили и т. д.)

0 голосов
/ 08 апреля 2015

Я знаю, этому вопросу уже три года, но мне нравится отвечать на текущий ответ. Мы говорим о данных домена. Следовательно, не может быть допустимого StyleBundle с 0 объектами. Я полагаю, у вас где-то есть редактор внешнего интерфейса, где вы создаете «новый» StyleBundle и должны добавить хотя бы один стиль, прежде чем нажать кнопку «Сохранить».

На данный момент в интерфейсе у вас не будет доменного объекта. У вас может быть объект передачи данных, который будет отправлен командой «CreateNewStyleBundle».

На мой взгляд, доменный объект должен быть агностическим для персистентности и всегда должен быть в допустимом состоянии. Если вам нужно вызвать метод IsValid, вы обойдете саму идею наличия доменных объектов.

Это просто мое скромное мнение.

...