DDD функциональность многократного использования в сущности / совокупности - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть следующий дизайн в DDD

  • Post Объединение с

    • Тело : HTML сообщения
  • Баннер сущность с

    • Html: HTML баннера

Сущность Banner принадлежит агрегату Post, поэтому я хочу создать метод BodyWithBanners в Пост агрегат.

Смысл этого метода заключается в поиске в HTML Post.Body и вставке HTML Banner .

Пока все хорошо.

Однако я намерен повторно использовать эту функциональность в абстрактном виде: «Вставьте немного HTML внутрь другого HTML». Итак, я создаю другой класс для этого: BannerReplacer

Возникает проблема, как мне вызвать этот новый класс?

  • Просто создайте экземпляр в методе Post.BodyWithBanners (прерывание внедрения зависимости)
  • Передача BannerReplacer в конструктор агрегата Post (это может быть кошмар для создания Post экземпляров)
  • Передача BannerReplacer методу BodyWithBanners (который подразумевает, что клиент использует Post должен обрабатывать BannerReplacer )

Я выбрал на данный момент первый вариант, но мне не очень удобно с ним, я считаю, что должен быть лучший способ делать это.

1 Ответ

1 голос
/ 26 апреля 2020

На данный момент я выбрал первый вариант, но мне не очень удобно с ним, я считаю, что должен быть лучший способ сделать это.

Многое из время, первый вариант в порядке - так что вы должны практиковаться с ним комфортно. В основном это означает больше думать о том, для чего нужна инъекция зависимости, и иметь четкое представление о том, действуют ли здесь эти силы.

Если Баннер является сущностью, в смысле domain-driven-design, тогда это, вероятно, нечто аналогичное автомату в памяти. У него есть структура данных, которой он управляет, и некоторые функции для изменения этой структуры данных или ответов на интересные вопросы об этой структуре данных, но у него нет проблем ввода-вывода, базы данных, сети и т. Д. c.

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

Если он работает одинаково во всех контекстах, тогда ему не нужно настраиваемое поведение. Если вам не нужно настраивать поведение, то вам не нужно внедрять зависимости (поскольку все копии этой сущности будут использовать (копии) одинаковые зависимости.

Когда у вас есть конфигурируемое поведение, тогда анализу нужно будет рассмотреть область действия. Если вам нужно изменить это поведение с одного вызова на другой, то вызывающая сторона должна знать об этом. Если поведение меняется реже чем это, тогда вы можете начать изучать, имеет ли смысл «внедрение в конструктор».

Вы знаете, что намереваетесь использовать один BannerReplacer для данного вызова метода, поэтому вы можете сразу начать с метода, который выглядит как :

class Banner {
    void doTheThing(arg, bannerReplacer) {
        /* do the bannerReplacer thing */
    }
}

Обратите внимание, что эта подпись вообще не зависит от времени жизни bannerReplacer. В частности, BannerReplacer может иметь более длительное время жизни, чем Banner, или более короткое время жизни. Мы заботимся только о том, чтобы срок службы был больше, чем у метода doTheThing.

class Banner {
    void doTheThing(arg) {
        this.doTheThing(arg, new BannerReplacer())
    }

    // ...
}

Здесь вызывающей стороне вообще не нужно знать о BannerReplacer; мы будем использовать новую копию реализации по умолчанию каждый раз. Вызывающая сторона заботится о том, какая реализация используется самостоятельно.

class Banner {
    bannerReplacer = new BannerReplacer()

    void doTheThing(arg) {
        this.doTheThing(arg, this.bannerReplacer)
    }

    // ...
}

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

class Banner {
    Banner() {
        this(new BannerReplacer())
    }

    Banner(bannerReplacer) {
        this.bannerReplacer = bannerReplacer;
    }

    void doTheThing(arg) {
        this.doTheThing(arg, this.bannerReplacer)
    }

    // ...
}

Та же идея, что и раньше, но теперь мы разрешаем «внедрение» реализации по умолчанию, которая может пережить данный экземпляр Banner .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...