В каком слое должны быть обновлены объекты Specification Pattern?

Итак, я просмотрел несколько сообщений о шаблоне спецификации здесь и еще не нашел ответа на этот.

У меня вопрос в том, где именно в n-слойной архитектуре мне следует "обновить" спецификации?

  1. Я мог бы поместить их на свой уровень обслуживания (также известный как уровень приложения, который иногда называют ... в основном, что-то, с чем может разговаривать код программной части .aspx), но я чувствую, что делая это, я позволяю бизнес-правилам просачиваться из Домен. Если доступ к объектам домена осуществляется другим способом (помимо уровня обслуживания), объекты домена не могут применять свои собственные бизнес-правила.

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

  3. Я мог бы внедрить спецификацию посредством внедрения метода (иногда называемого «двойная отправка» ???), и явно сделать так, чтобы этот метод инкапсулировал внедренную спецификацию, чтобы обеспечить соблюдение своего бизнес-правила.

  4. Создайте класс «Службы домена», который будет принимать Спецификацию (и) через внедрение конструктора, а затем позволить Уровню Службы использовать Службу Домена для координации объекта Домен. Мне это кажется нормальным, поскольку правило, обеспечиваемое Спецификацией, все еще находится в «Домене», а класс Службы Домена можно назвать очень похожим на объект Домена, который он координирует. Дело в том, что я чувствую, что пишу МНОГО классов и кода только для того, чтобы «правильно» реализовать шаблон Спецификации.

Добавьте к этому, что рассматриваемая спецификация требует репозитория, чтобы определить, "удовлетворено" оно или нет.

Это потенциально могло вызвать проблемы с производительностью, особенно. если я использую инъекцию конструктора, b / c потребляющий код может вызвать свойство, которое, возможно, является оболочкой спецификации, и это, в свою очередь, вызывает базу данных.

Итак, есть идеи / мысли / ссылки на статьи?

Где лучше всего обновляться и использовать спецификации?


person Michael McCarthy    schedule 22.11.2011    source источник


Ответы (2)


Краткий ответ:

Вы используете спецификации в основном на уровне обслуживания, так что там.

Длинный ответ: Прежде всего, здесь два вопроса:

Где должны жить ваши спецификации и где они должны быть обновлены?

Как и интерфейсы вашего репозитория, ваши спецификации должны находиться на уровне домена, поскольку они, в конце концов, специфичны для домена. Есть вопрос по SO, в котором обсуждается это на интерфейсах репозитория.

Но где они должны быть новенькими? Что ж, я использую LinqSpecs в своих репозиториях и в основном когда-либо использую три метода в моем репозитории:

public interface ILinqSpecsRepository<T>
{
    IEnumerable<T> FindAll(Specification<T> specification);
    IEnumerable<T> FindAll<TRelated>(Specification<T> specification, Expression<Func<T, TRelated>> fetchExpression);
    T FindOne(Specification<T> specification);
}

Остальные мои запросы построены на моем уровне обслуживания. Благодаря этому репозитории не будут перегружены такими методами, как GetUserByEmail, GetUserById, GetUserByStatus и т. Д. В моем сервисе я обновляю свои спецификации и передаю их методам FindAll или FindOne моего репозитория. Например:

public User GetUserByEmail(string email)
{
    var withEmail = new UserByEmail(email); // the specification
    return userRepository.FindOne(withEmail);
}

и вот спецификация:

public class UserByEmail : Specification<User>
{
    private readonly string email;

    public UserByEmail(string email)
    {
        this.email = email;
    }

    #region Overrides of Specification<User>

    public override Expression<Func<User, bool>> IsSatisfiedBy()
    {
        return x => x.Email == email;
    }

    #endregion
}

Итак, чтобы ответить на ваш вопрос, спецификации обновлены на уровне обслуживания (в моей книге).

Я чувствую, что единственное, что следует вводить в классы модели, - это «услуги».

ИМО, вы не должны ничего вводить в объекты домена.

Добавьте к этому, что рассматриваемая спецификация требует репозитория, чтобы определить, "удовлетворено" оно или нет.

Это запах кода. Я бы просмотрел ваш код там. Спецификация определенно не должна требовать репозитория.

person autonomatt    schedule 23.11.2011
comment
Не слишком уверен, является ли введение репозитория в спецификацию запахом кода или нет. Проверьте это обсуждение StackOverflow: ссылка. Сходства между Спецификацией и Доменной службой могут быть очень похожими, особенно если правило, которое вы пытаетесь применить / доказать, в первую очередь полагается на получение информации через репозиторий. - person Michael McCarthy; 07.01.2012
comment
Вы передаете спецификацию в репозиторий, например через FindOne (спецификация) или FindAll (спецификация). Если вы добавляете репозиторий в спецификацию, вы рискуете создать циклическую ссылку, что может привести к проблемам. - person autonomatt; 30.01.2012
comment
К вашему сведению, я добавляю свои спецификации в сервисы, когда они мне нужны. - person Worthy7; 11.05.2018

Спецификация - это проверка реализации бизнес-правила. Он должен существовать в точке на уровне домена.

Трудно указать, как вы это делаете, поскольку каждая кодовая база отличается, но любая бизнес-логика, на мой взгляд, должна находиться на уровне домена и нигде больше. Эта бизнес-логика должна быть полностью тестируемой и слабо связана с пользовательским интерфейсом, базой данных, внешними службами и другими зависимостями, не относящимися к домену. Так что я определенно исключил бы пункты 1, 2 и 3 выше.

4 - вариант, по крайней мере, спецификация будет жить на уровне вашего домена. Однако обновление спецификаций снова зависит от реализации. Обычно мы используем внедрение зависимостей, поэтому обновление почти всех наших объектов выполняется через контейнер IOC и соответствующий код начальной загрузки (т.е. мы обычно подключаем приложение плавно). Однако мы никогда бы не связали бизнес-логику напрямую, например, с Классы модели пользовательского интерфейса и тому подобное. Обычно у нас есть контуры / границы между такими вещами, как пользовательский интерфейс и домен. Обычно мы определяем контракты службы домена, которые затем могут использоваться внешними уровнями, такими как пользовательский интерфейс и т. Д.

Наконец, я предполагаю, что система, над которой вы работаете, по крайней мере в некоторой степени сложна. Если это очень простая система, то дизайн, ориентированный на предметную область, как концепция, вероятно, будет чрезмерным. Однако, на мой взгляд, некоторые концепции, такие как тестируемость, читаемость, SoC и т. Д., Должны соблюдаться независимо от кодовой базы.

person bstack    schedule 23.11.2011