company_banner

Инструменты Domain Driven Design

    Синий кит — отличный пример того, как проектирование сложного проекта пошло не по плану. Кит внешне похож на рыбу, но он млекопитающее: кормит детенышей молоком, у него есть шерсть, а в плавниках до сих пор сохранились кости предплечья и кистей с пальцами, как у сухопутных. Он живет в океанах, но не может дышать под водой, поэтому регулярно поднимается на поверхность глотнуть воздуха, даже когда спит. Кит самое большое животное в мире, длиной с девятиэтажный дом, а массой как 75 автомобилей Volkswagen Touareg, но при этом не хищник, а питается планктоном.

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



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

    Что такое DDD и какие инструменты в нем есть, мы расскажем в статье на основе доклада Артема Малышева. Подход DDD в Python, инструменты, подводные камни, контрактное программирование и проектирование продукта вокруг решаемой проблемы, а не используемого фреймворка — все это под катом.

    Полная презентация доклада.

    Артем Малышев (proofit404) — независимый разработчик, пишет на Python 5 лет, активно помогал с Django Channels 1.0. Позже сфокусировался на архитектурных подходах: изучил, какого инструментария не хватает архитекторам на Python, и начал проект dry-python. Сооснователь компании Drylabs.

    Сложность


    Что такое программирование?
    Программирование — это постоянная борьба со сложностью, которую создают сами разработчики, когда пытаются решить проблемы.
    Сложность делится на два типа: привнесенная и естественная. Привнесенная тянется вместе с языками программирования, фреймворками, ОС, моделью асинхронности. Это техническая сложность, которая не относится к бизнесу. Естественная сложность скрыта в продукте и упрощает жизнь пользователям — за это люди и платят деньги.
    Хорошие инженеры должны уменьшать привнесенную сложность и увеличивать естественную, чтобы повышать полезность продукта.
    Но мы, программисты, сложные люди и обожаем добавлять в проекты техническую сложность. Например, мы не заморачивались над стандартами кодирования, не применяли линтеры, практики модульного дизайна и получили в проектах море кода в стиле if c==1.

    Как работать с таким кодом? Прочитать много файлов, понять переменные, условия и то, когда и как это все будет работать. Этот код тяжело держать в голове — абсолютно техническая привнесенная сложность.

    Еще один пример привнесенной сложности — мой любимый «callback hell».



    Когда мы пишем в рамках событийно-ориентированной архитектуры (EDA) и выбираем не самый хороший современный фреймворк, то получаем код, в котором непонятно, что и когда происходит. Читать такой код тяжело — это опять привнесенная сложность.

    Программисты не только обожают технические сложности, но еще и спорят, какая из них лучше:

    • AsyncIO или Gevent;
    • PostgreSQL или MongoDB;
    • Python или Go;
    • Emacs или Vim;
    • табы или пробелы;

    Правильный ответ хорошего программиста на все эти вопросы: «Без разницы!» Хорошие разработчики не спорят из-за сферических коней в вакууме, а решают проблемы бизнеса и работают над полезностью продукта. Некоторые из них уже давно создали набор практик, которые уменьшают привнесенную сложность и помогают больше думать о бизнесе.

    Один из них — Эрик Эванс. В 2004 году он написал книгу «Domain Driven Design» («Предметно-ориентированное проектирование»). Она «выстрелила» и дала импульс больше думать о бизнесе, а технические детали отодвинуть на второй план.



    Что такое DDD?


    Сначала решение проблемы, а потом инструменты. Прежде всего Эванс вкладывал в понятие DDD, что это не технология, а философия. В философии сначала нужно думать, как решить проблему, а уже потом, с помощью каких инструментов.

    Работайте над моделями вместе с экспертами в предметной области и разработчиками ПО. Мы должны общаться с людьми из бизнеса: искать общий язык, строить модель мира, в рамках которой наш продукт будет работать и решать проблемы.

    Пишите ПО, которое явно выражает модели. Самое важное отличие DDD от простой коллаборации в команде это то, что мы должны писать ПО в том же стиле, в котором говорим с экспертами предметной области. Вся терминология, подходы к обсуждению и принятию решений должны быть сохранены в исходном коде, чтобы даже не технический человек мог понять, что там происходит.

    Говорите с бизнесом на одном языке. DDD — это философия о том, как с экспертами из бизнеса говорить на одном языке в рамках определенной области и к этой области применять терминологию. У нас появляется общий язык или диалект в рамках связанного контекста, который мы считаем истиной. Мы создаем границы вокруг архитектурных решений.

    DDD не о технологиях.

    Сначала техническая часть, потом — DDD. Скульптор, который высекает статую из камня не читает мануал о том, как держать молоток и долото — он уже знает, как ими работать. Чтобы привнести DDD в ваш проект, освойте техническую часть: выучите до конца Django, прочитайте туториал и перестаньте спорить, что брать — PostgreSQL или MongoDB.

    Большинство шаблонов и паттернов проектирования — это технический шум. Большая часть паттернов, которые мы знаем и используем — технические. Они говорят, как переиспользовать код, как структурировать, но не говорят, как применять его для пользователей, бизнеса и моделировать внешний мир. Поэтому фабрики или абстрактные классы слабо привязаны к DDD.

    Первая «синяя» книга вышла почти 20 лет назад. Люди пытались писать в этом стиле, ходили по граблям, и поняли, что философия хорошая, но на практике непонятная. Поэтому появилась вторая книга — «красная», именно о том, как программистам мыслить и писать в DDD.


    «Красная» и «синяя» книги — это столпы, на которых стоит все DDD.

    Примечание. Красная и синяя книги — это уникальный источник информации о DDD, но они тяжелые. Книги непросто читать: в оригинале из-за сложного языка и терминов, а на русском из-за плохого перевода. Поэтому, начните изучение DDD с «зелёной» книги. Это упрощенный вариант первых двух с примерами попроще и общими описаниями. Но лучше так, чем если красная и синяя книга отобьют у вас желание изучать и применять DDD. Лучше читать в оригинале.

    В красной книге проскакивает идея, как лучше всего DDD привносить в проект, как структурировать работу вокруг этого подхода. Появляется новая терминология — «Model-Driven Design», в котором на первое место ставится наша модель внешнего мира.



    Единственное место, где выбираются технологии — «Smart UI». Это прослойка между внешним миром, пользователем и нами (отсылка к Роберту Мартину и его чистой архитектуре со слоями). Как видим, все идет к модели.

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

    Dry-python


    Чтобы заполнить нишу моделей, я начал проект dry-python, который вырос в набор библиотек высокоуровневых архитектурных решений для построения Model Driven Design. Каждая из библиотек пытается закрыть один круг в архитектуре и не мешает другим. Библиотеки можно использовать отдельно, а можно вместе, если войти во вкус.



    Последовательность повествования соответствует хронологии оптимального добавления DDD в проект — по слоям. Первый слой — сервисы, описание бизнес-сценариев (процессов) в нашей системе. За этот слой отвечает библиотека Stories.

    Stories


    Бизнес-сценарии делятся на три части:

    • спецификация — описание бизнес-процесса;
    • состояние, в котором может находиться бизнес-сценарий;
    • реализация каждого шага сценария.

    Эти части нельзя смешивать. Библиотека Stories разделяет эти части и проводит между ними четкую границу.

    Рассмотрим внедрение DDD и Stories на примере. Например, у нас есть проект на Django с мешаниной из Django-сигналов и непонятных «толстых» моделей. Добавим в него пустой пакет services. С помощью библиотеки Stories по частям перепишем эту мешанину в ясный и понятный набор сценариев в нашем проекте.

    Спецификация DSL. Библиотека позволяет писать спецификацию и предоставляет для этого DSL. Это способ пошагово описать действия пользователя. Например, чтобы купить subscription, я выполняю несколько шагов: найду заказ, уточню актуальность цены, проверю, может ли позволить себе это пользователь. Это высокоуровневое описание.

    Контракт. Ниже этого класса напишем контракт на состояние бизнес-сценария. Для этого обозначим область переменных, которые возникают в бизнес-процессе, и за каждой переменной закрепим набор валидаторов.

    Как только кто-нибудь попробует в рамках бизнес-процесса назначить какую-то переменную в эту область — будет отработан набор валидаторов. Мы будем уверены, что состояние процесса во время выполнения всегда рабочее. Но если нет, оно больно падает и громко об этом кричит.

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

    • что успешно отработал, и предложить поместить переменные в область (скоуп) для дальнейшего выполнения;
    • что он что-то проверил и понимает, что дальнейшее выполнение не имеет смысла.


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

    Запускаем Story. Как запустить Story на выполнение? Это бизнес-объект, который работает как метод: передаем на вход данные, он их валидирует, интерпретирует шаги. Выполняющаяся Story помнит историю исполнения, записывает состояние, которое происходило в ней в бизнес-процессе, и рассказывает нам, кто влиял на это состояние.

    Панель инструментов отладки. Если пишем на Django и используем панель отладки, можем посмотреть, какие бизнес-сценарии отрабатывались в каждом запросе и их состояния.

    Py.test. Если пишем в py.test, то для упавшего теста можем посмотреть, какие бизнес-сценарии выполнялись на каждой строке и что пошло не так. Это удобно — вместо ковыряния в коде, прочитаем спецификацию и поймем, что произошло.



    Sentry. Еще лучше, когда получаем ошибку 500. В обычной системе мы смиряемся с ней и начинаем вести расследование. В Sentry же, появится подробный отчет о том, что делал пользователь, чтобы добиться ошибки. Удобно и приятно, когда в 3 часа ночи такую информацию собрали за тебя.


    ELK. Сейчас мы активно работаем над плагином, который пишет это все в Elasticsearch в стек Kibana и строит грамотные индексы.



    Например, у нас есть контракт на состояние бизнес-процесса. Мы знаем, что там есть, например, relation ID отчета. Вместо архаичного исследования того, что там когда-то происходило, мы пишем запрос в Kibana. Он покажет все выполненные Story, которые относятся к определенному пользователю. Дальше мы изучаем состояние внутри наших бизнес-процессов и бизнес-сценариев. Мы не пишем ни одной строки кода логирования, но проект логируется именно на том уровне абстракции, на котором нам интересно смотреть.

    Но хочется чего-то более высокоуровневого, например, легких объектов. Такие объекты хранят в себе грамотные структуры данных и методы, которые относятся к принятию бизнес-решений, а не к работе с БД, например. Поэтому мы переходим к следующей части Model-Driven архитектуры — entities, agregates и value objects.



    Entities, agregates и value objects


    Как все это взаимосвязано? Например, пользователь сделал заказ продукта, и мы выставляем счет. Что здесь корень агрегации, а что — простой объект?



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

    С чего начать? Создадим в проекте пустой пакет, куда будем складывать наши агрегаты. Агрегаты лучше писать с чем-то декларативным, вроде dataclasses или attrs.

    Dataclasses. Если какой-то dataclass укажем агрегатом — напишем на него аннотацию с помощью NewType. В аннотации укажем явный референс, который выразим в системе типов. Если же dataclass — просто структура данных (entity), то сохраним внутри агрегата.

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



    Сразу же возникает проблема — репозитории. У меня есть база данных, с которой я работаю через Django, соседний микросервис, в который я отправляю запросы, есть JSON и экземпляр Django-модели. Получать данные и переносить их руками, просто чтобы вызвать или проверить метод красиво? Нет, конечно. В dry-python есть библиотека Mappers, которая позволяет сопоставлять высокоуровневые абстракции и доменные агрегаты с местами, где мы их храним.

    Mappers


    Добавляем еще один пакет к нашему проекту — репозиторий, в котором будем хранить наши mappers. Это то, как высокоуровневую бизнес логику будем переносить на реальный мир.

    Например, мы можем описать то, как мы сопоставляем какой-нибудь dataclass с Django-моделью.

    Django ORM. Сопоставляем модель заказа с описанием Django ORM — смотрим поля.

    Например, некоторые поля можем переписать через опциональный config. Произойдет следующее: mapper во время декларации будет сравнивать, как написан dataclass и модель. Например, аннотации intOrder dataclass есть поле cost с аннотацией int) в Django-модели соответствует integer field с опцией nullable="true". Здесь dataclass предложит добавить optional в dataclass, или убрать nullable из field.

    Через Mappers можно добавлять функции, которые что-то читают или пишут. Читающие — это функции, которые получают на вход агрегат и возвращают на него референс. Пишущие поступают наоборот — возвращают агрегаты. Под капотом может быть, например, запрос к базе через Django.

    Определения Swagger.Те же операции можно проводить и с микросервисами. Можно написать на них часть swagger-схемы и проверить, насколько swagger-схема конкретного сервиса соответствует вашим доменным моделям. Дальше вернувшийся запрос из библиотеки Request будет прозрачно транслирован в dataclass.

    Запросы GraphQL. GraphQL и микросервисы: схема типов интерфейсов GraphQL отлично валидируется против dataclass. Можно транслировать конкретные запросы GraphQL во внутренние структуры данных.

    Зачем вообще так заботиться о внутренней высокоуровневой модели данных внутри приложения? Для иллюстрации «зачем» расскажу «занимательную» историю.

    В одном нашем проекте веб-сокеты работали через сервис Pusher. Мы не заморачивались, обернули его в интерфейс, чтобы не вызывать напрямую. Этот интерфейс привязывали во всех Stories и были довольны.

    Но бизнес-требования изменились. Оказалось, что гарантий, которые предоставляет Pusher к веб сокетам, недостаточно. Например, нужна гарантированная доставка сообщений и история сообщений за последние 2 минуты. Поэтому мы решили переехать на сервис Ably Realtime. В нем же есть интерфейс — напишем адаптер и привяжем его везде, все будет здорово. На самом деле нет.

    Абстракции, которые использует Pusher (аргументы функций) попали в каждый бизнес-объект. Пришлось поправить порядка 100 Stories, и исправить формирование канала пользователей, в который мы что-то отправляем.

    Вернемся к тестам.

    Tests & mocks


    Как обычно тестируют такое поведение с внешними сервисами? Что-то мокаем, смотрим, как вызывается сторонняя библиотека, и все — мы уверены, что все хорошо. Но когда библиотека меняется, то форматы аргументов тоже меняются.

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

    Dependencies


    В такой модельной архитектуре появляется много лишних сущностей. Раньше мы брали какую-нибудь Django-функцию и писали ее: запрос, ответ, минимум телодвижений. Здесь надо инициализировать Mappers, положить в Stories и инициализировать, обработать строку запроса HTTP-запроса, посмотреть, какой ответ отдать. Все это выливается в 30-50 строк boilerplate кода вызова Stories внутри Django-view.

    С другой стороны у нас уже написаны интерфейсы и Mappers. Мы можем проверить их совместимость с конкретным бизнес-кейсом, например, с помощью библиотеки Dependencies. Как? Через паттерн Dependency injection все декларативно склеим с минимальным boilerplate.

    Здесь мы указываем задачу взять в пакете services класс, поместить в него три mappers, проинициализировать объект Stories и отдать нам. С таким подходом количество boilerplate в коде уменьшается колоссально.

    Карта рефакторинга


    Применяя все, о чем я говорил, мы разработали схему, по которой переписали большой проект с Django сигналов (неявного «callback hell») на Django по DDD.

    Первый шаг без DDD. Сначала у нас не было DDD — мы писали MVP. Когда заработали первые деньги, пригласили инвесторов, и убедили перейти на DDD.

    Stories без контрактов. Разбили проект на логичные бизнес-кейсы без контрактов данных.

    Контракты и агрегаты. Потом один за одним перетащили контракт данных на каждую модель, которые прослеживаются в нашей архитектуре.

    Mappers. Написали Mappers, чтобы избавиться от шаблонов работы с хранилищами данных.

    Внедрение зависимостей. Избавились от шаблонов склейки.

    Если ваш проект перерос MVP и в нем требуется срочно менять архитектуру, чтобы он не скатился в legacy — посмотрите в сторону DDD.

    Какие еще есть способы избежать legacy в Python-проектах, или как с ним бороться, если досталось тяжелое наследство, обсудим на Moscow Python Conf++ 27 марта. Кроме того в расписании конференции доклады о самых разных аспектах работы с Python и об альтернативных вариантах решения привычных задач. А за пределами выступлений у нас unconference, общение с коллегами из профессиональных сообществ, и консультации партнеров, например, как раз Drylabs.

    А если DDD интересует вас вне Python, то рекомендую обратить внимание на TechLead Confконференцию про процессы и практики разработки качественных IT-продуктов, на которой будет DDD радар. Конференция состоится 8 июня, Call for Papers открыт до 6 апреля.
    Конференции Олега Бунина (Онтико)
    Конференции Олега Бунина

    Комментарии 26

      –3

      Великолепнейший образчик животного земли, успешно развивающееся на протяжении 50 000 000 лет и какой-то 30ти-летний человечишка со своими глобальными мыслями об очередной нашей локальной фигнёй, о которой завтра забудут (при всём уважении).


      За китов вот сейчас было обидно, да...

        +1
        Справедливости ради, человек тоже спроектирован с дефектами. Чего только стоят все эти когнитивные искажения. А киты прекрасны, но правда же странный феномен :)
          0
          Справедливости ради, чтоб что-то объявить «дефектом» — нужно сначала выкатить (хотя бы теоретически) экземпляр без оного «дефекта» и обосновать, что у него и вправду всё значительно лучше.

          Это я не к тому, что в результатах эволюции нельзя ничего улучшить (можно), а о том, что не стоит бездумно пытаться квалифицировать эволюционные особенности.
            0
            Хммм, значит ли это, что я не могу, например, критиковать кривое приложение, пока не выкачу такое же, но лучше? Или я не могу говорить, что двигатель у новой модели авто дефективный, пока не создам свой? Или я не могу критиковать застройщика за кривые стены в квартире, пока сам не построю такой же дом, но лучше?..
              0
              Хммм, значит ли это

              Нет. Попробуйте прочитать верхний пост внимательнее.
                0
                Так вот же, прочитал: «Справедливости ради, чтоб что-то объявить «дефектом» — нужно сначала выкатить (хотя бы теоретически) экземпляр без оного «дефекта» и обосновать, что у него и вправду всё значительно лучше.»

                Нужно выкатить свой экземпляр, а уже потом можно что-то говорить. Верно? Вы же это имели ввиду?)
                  0
                  Ну если вы два раза не прочитали часть в скобках — то я здесь бессилен. «Выкатить» так же не подразумевает «сделать лично здесь и сейчас», но это как раз явно следует из части в скобках, которую вы не читаете.
                    0
                    Если часть в скобках так важна, почему она в скобках?) Фактически часть в скобках нивелирует всю часть, что не в скобах, потому что без скобочек смысл один, а со скобочками другой, и с отдельным дополнением его объясняющим. Верно?
                      0
                      Начали с претензий к смыслу, закончили синтаксисом. Вы не компилятор — вы вполне способны читать все буквы, даже если синтаксис не идеален.

                      Я не вижу смысла развивать обсуждения синтаксиса.
                        0
                        У меня нет претензий, я всего лишь интересуюсь и уточняю)
              –2

              Для меня странно слышать слово "дефект" от тех, кто без доступа к тому же киту и тому, из чего он состоит и как работает — вообще ничего не может.


              Это как поколение, которому полностью начхать на своих родителей, если они не умеют в айфончик пальцем тыкать.

                +1

                Акулы охотятся на китов в том числе не давая им всплыть, чтобы подышать. Это лучше?

                  0
                  Используют баг в системе?)
                    0

                    Вы правда не поняли, о чем я говорил?

              +2

              Пара замечаний по неудачному дизайна кита.


              1. Кит большой. Сжигает много пищи и кислорода.
              2. В воде содержание растворённого кислорода достигает 11 см³ на литр. В воздухе содержание кислорода равно 210 см³ на литр.
              3. Для получения достаточного количества кислорода из воды нужно прокачивать через жабры большие её количества. Например, непрерывно двигаясь (как акулы). И еще больше увеличивая потребление кислорода.
              4. Кит теплокровен — его подвижность не зависит от температуры. Большинство видов акул — нет. Для подогрева тела киту опять же нужны пища и кислород.
              5. Для того, чтобы получить достаточное количество еды, крупной рыбы уже недостаточно. Как и крупнейшие виды акул, киты питаются планктоном. И рады бы рыбкой, да где ж её взять в таких количествах?
              6. Киты были замечены на глубине до 3 километров. Акулы — до двух.

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

                –2
                Для получения достаточного количества кислорода из воды нужно прокачивать через жабры большие её количества. Например, непрерывно двигаясь (как акулы). И еще больше увеличивая потребление кислорода.

                где у кита жабры? Если это млекопитающее, то у него легкие (sic!)


                Кит теплокровен — его подвижность не зависит от температуры. Большинство видов акул — нет. Для подогрева тела киту опять же нужны пища и кислород.

                Не понял — где тут неудачный дизайн? Лучше же быть подвижным, чем нет? Не так ли ?

                  +1
                  где у кита жабры? Если это млекопитающее, то у него легкие (sic!)

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


                  При том, что пятиминутного изучения domain'а (предметной области) должно было бы, чтобы понять, что рыба размером с кита просто задохнется. А хищник такого размера — умрет голодной смертью.

                    0

                    Все, понял, спасибо за расширенный ответ

                      0

                      А нужен ли нам такой размер? Вообще какая цель у проекта?

                  0
                  Выглядит как overengineering, но интересно.

                  Не уверен, что для мелких и средних проектов такой подход будет выгодным. Для больших — может быть…

                  Пример с сигналами Django не лучший, не уверен, что ими хоть кто-то сейчас активно пользуется. Не назвал бы их ни удобными, ни безопасными.

                  В то же время, некоторые идеи вполне полезны сами по себе. Например, «константный» контекст и его наполнение, сам пришёл к чему-то подобному.

                  У подобного «основательного» подхода к разработке основные плюсы сосредоточены на этапе поддержки/сопровождения, на это и надо делать упор в рассказе. Добавить больше генерации чего-нибудь, рисования диаграм, автоматического рефакторинга.
                    0
                    Спасибо! Я это учту в дальнейшей разработке проекта.
                      +1

                      В текущем варианте — overengineering в чистом виде.


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


                      Сама реализация, ограничения, которые она накладывает на оптимизацию, технические проблемы, которые придется решать, полностью аналогичны тем, что встречаются при реализации GraphQL-сервера.


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


                      Более того — решить их на уровне библиотеки так, чтобы разработчик мог сконцентрироваться на бизнес-логике, в текущей, синхронной, версии Django не получится.

                      0

                      Существует ли реальный бизнес-проект, написанный с использованием DDD. Или переписанный? Потому что в теории и на крошечных примерах оно выглядит красиво, но на таких примерах можно в любой парадигме сделать красиво.

                        0

                        Так все правильно — все бизнес-проекты скатываются в легаси, потому что бизнес давит, что фичи нужны вчера, старая команда рассасывается кто куда и все… до DDD уже дело не доходит )

                          +1
                          DDD выглядит хорошо как раз таки на больших проектах и примерах.
                          На небольших это как раз overengineering как правильно подметили в комментарии выше.
                          +2
                          Единственная здравая мысль в статье — что DDD не про технические детали, а общение с бизнесом, а далее всё скатилось и пошла типичная подмена понятий.
                          DDD != архитектура, DDD не учит писать поддерживаемый с технической точки зрения код.

                          И техническая сложность никуда не пропадёт, если фокусироваться лишь на естественной сложности доменной области, к тому же на ней сфокусироваться вряд ли получится, пока есть проблемы с технической стороны.
                          А автор, именно что, пытается уменшать сложность техническую через DDD, ничего дельного из этого не выйдет.

                          Под видом DDD делать агрегаты и сущности data-классами(то есть анемичную модель) — серьёзно?

                          Здесь мы указываем задачу взять в пакете services класс, поместить в него три mappers, проинициализировать объект Stories и отдать нам.

                          Я правильно понимаю, что по мнению автора, это понятная для менеджеров без технической экспертизы фраза(единый язык)?

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

                          Самое читаемое