Ответы пользователя по тегу Предметно-ориентированное проектирование
  • Чем отличается контекст от домен в ddd?

    @ddd329
    Приветствую!
    Например, в реальном мире существует некий бизнес, который принимает заказы и соответственно занимается их доставкой. Так вот этот бизнес и является Предметной Областью, которая содержит в себе некую проблему, которую нужно решить. При решении проблем предметной области при помощи разработки программного продукта, в коде мы эту область моделируем и получается Модель Предметной Области, которая выражает способ решения проблемы. Получается в реальном мире есть Предметная Область (Domain), а в программном коде есть Модель Предметной Области (обычно тоже Domain).
    Предметная область может быть очень большой или структура бизнеса состоит из нескольких отделов, и поэтому эту область могут разбивать на подобласти(sub-domain). Так вот эти самые подобласти в программном коде реализуются посредством Ограниченных Контекстов (Bounded Context), каждый из которых содержит свою маленькую Модель Предметной Области.

    Теперь непосредственно к самому вопросу: "Чем отличается контекст от домен в ddd?" - если у вас предметная область не разделена на подобласти, то в реальном мире Предметная область (Domain), будет иметь отражение в программном коде в виде одной Модели Предметной Области (Domain), что равно одному Ограниченному Контексту (Bounded Context).
    А если предметная область разделена на Подобласти Предметной Области, то в коде будет отражаться в виде нескольких Ограниченных Контекстов.

    Судя по вашей структуре папок, могу сказать, что ваша предметная область состоит из двух подобластей: Заказ и Доставка, и в программном коде реализуются посредством двух Ограниченных Контекстов: Заказ (Order) и Доставка (Delivery), где каждый содержит свою маленькую Модель Предметной Области (Domain), которая размещена в у вас в папке domain.

    Папки Order и Delivery можно было переименовать в OrderBoundexContext и DeliveryBoundexContext, тогда может быть и не возникла путаница.

    В рамках примера такой структуры кода, папка `Delivery` является доменом или контекстом?
    - является поддоменом/подобластью и одновременно ограниченным контекстом в коде, которая содержит свою модель. Аналогично и для Order.
    Ответ написан
    Комментировать
  • Как использовать DDD подход к реализации каталога?

    @ddd329
    Модель предметной области по DDD, это чисто для организации бизнес-логики, и такие понятия как Агрегат, Сущность, Объект-значение служит исключительно этим целям.
    Для отображения данных в графическом интерфейсе можно, а то и нужно создавать вторую модель для чтения.
    Т.е. по итогу должно получиться две модели, во многом они будут себя дублировать в простых областях.
    Ответ написан
    Комментировать
  • Как спроектировать проверку?

    @ddd329
    Привет! Ну если вопрос касается проектирования, то тут сразу бросается в глаза понятие Service. В предметной области его желательно не использовать, т.к. данный термин очень перегруженный и имеет много понятий в программировании. Я видел в одном проекте его заменили на Product, но ладно не суть...
    Паттерн "Спецификация" я думаю тут не особо уместен. Можно сделать так, что каждый Сотрудник содержит в себе поле со списком Документов, и для того чтобы выяснить может ли сотрудник оказывать услугу, то можно примерно так:
    if (employee.СanProvideService(service)) ...
    Ответ написан
    Комментировать
  • Как правильно обрабатывать входящие данные?

    @ddd329
    Когда твои данные дойдут до ApplicationLayer, то служба этого уровня, должна достать агрегат из репозитория, и над этим агрегатом произвести действия на основе входящих данных. Например, если отредактировали фамилию пользователя, то:
    1. var user = userRepository.GetById(777);
    2. user.LastName = inputData.LastName;
    3. userRepository.Save(user);

    В таком духе...
    Ответ написан
    Комментировать
  • Как загружать вложенные сущности в ddd?

    @ddd329
    У меня есть сущности и репозитории к ним.

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

    Загружать вложенные сущности нельзя, потому как:
    1. Сущность не может обращаться к репозиторию, она может иметь только ссылки на другие сущности и на объекты-значения;
    2. Грузить надо сразу целый граф безо всякой отложенной загрузки.
    Проблема такой загрузки в том что в случае создания списка сущностей, каждая из них должна загрузить свои данные, когда можно было бы 1 запросом загрузить данные сразу для всех.

    Вот как раз для этого агрегаты и нужны
    Ответ написан
  • Бывает ли разделенная модель в ddd?

    @ddd329
    В DDD это нормально определить одно и тоже понятие в разных моделях. В любой книге по DDD написано про ограниченные контексты, как раз для этого они и придуманы
    Ответ написан
    Комментировать
  • DDD, aggregate root, entity, repository?

    @ddd329
    Ну тогда АГРЕГАТ будет состоять из одной СУЩНОСТИ - City
    Ответ написан
  • Как следует организовать работу с entity?

    @ddd329
    Сущности и агрегаты нужны для реализации бизнес-логики, чтобы ты не смог в базу данных записать недостоверную и/или противоречивую информацию, и все!
    На экране ты отображаешь не сущности и агрегаты, а скорее информацию о них... Когда ты думаешь о выводе данных на экран, то не должен даже мыслить агрегатами, потому как агрегаты являются единицами изменения, а не порция для отображения.
    Поэтому можешь обращаться на прямую в БД с запросом выдать тебе информацию, или создать отдельную Модель Чтения, и через ORM читать данные.

    Создавать сущность LocalizedDisease не имеет смысла, так как не реализует новое поведение. Вообще сущность это в идеале только поведение, и не важно какие у него данные, то есть принцип здесь - "Говори а не спрашивай"
    Ответ написан
    Комментировать
  • Как правильно валидировать атрибуты сущности?

    @ddd329
    Привет!

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


    На самом деле с точки зрения DDD как раз-то противоречий никаких нет. Модель предметной области существует сама по себе, и не делает никаких предположений о своих клиентах, которыми могут быть графические интерфейсы настольных и веб-приложений, и не только...

    Как быть если ошибка в нескольких атрибутах сущности?


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

    Дублировать валидацию на клиенте и сервере не хочется


    Дублировать валидацию можно, если она общеизвестная, например ФИО или email-адрес, зачем перепадать эти значения на сервер, когда в браузере можно выполнить их полноценную валидацию, что повысит время отклика UI. А если логика специфичная, что чаще и бывает, то бизнес-правила должны "лежать" на уровне домена, и не выше.

    В общем, мне известно два варианта создания сущностей: используя только публичный конструктор, или используя фабрику(factory). Если я вас правильно понял, то у вас имеется форма с полями для заполнения их значениями, которые являются атрибутами какой-то сущности?
    Здесь могут быть два сценария, первый: когда сущность, а точнее АГРЕГАТ, извлекается из репозитория с целью редактирования, то здесь все так, как вы описали выше: неверное значение атрибута - выбрасываем исключение.
    И второй сценарий - создание сущности. Нигде нельзя получить доступ к невалидной сущности, созданной с помощью оператора new DomainObject() кроме как фабрики. Поэтому создавайте фабрику, которая позволяет строить вашу сущность, а точнее АГРЕГАТ, по шагам. Для этого примените паттерн проектирования СТРОИТЕЛЬ (Builder). В конце вызовите метод Build(), который и вернет вам валидный АГРЕГАТ.
    Что качается промежуточных результатов "строительства", то для их получения используйте паттерн проектирования СНИМОК (Memento), например вот так: var snapshot = domainObjectFactory.GetSnapshot();, где snapshot обычная DTO-ошка, которая содержит значения атрибутов сущностей и списки ошибок, валидность и т.д. Ну а дальше смотрите сами как быть, если вы на клиента передаете ViewModel-s, то используя snapshot создавайте модели представления и дальше их на UI пользователя.
    Ответ написан
    Комментировать
  • DDD, Aggregate root без ORM, как сохранять?

    @ddd329
    Без ORM, есть простые шаблоны. Твой репозиторий имеет метод Save, не важно обновил или создал новый АГРЕГАТ, все это передаешь методу Save, т.е. один метод вместо двух - Add и Delete. Допустим, ты обновляешь АГРЕГАТ, который состоит из трех сущностей, а в базе существуют три таблицы, т.е. каждая сущность маппиться на свою таблицу. Та сущнсость которая представляет корень АГРЕГАТА, будет использовать оператор UPDATE в SQL запросе, а дочерние сущности надо удалить (DELETE FROM..) и вставить заново(INSERT INTO). Все это делается в одной транзации базы данных, никакой вам Unit Of Work не нужен...

    Попробуйте...
    Ответ написан
    Комментировать
  • Всегда ли объект должен валидным?

    @ddd329 Автор вопроса
    Да, вопрос как раз об Entity и ValueObject'ы.

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

    Может сделать так: вынести класс Document в отдельную сборку Domain, выставить у свойства RegNumber модификатор доступа internal, чтобы клиентский код, например Presenter, не смог на прямую устанавливать значения. Ввести доменную службу DocumentService и в нем реализовать логику присвоения регистрационного номера, здесь как раз будет и парсинг строки, и проверка всех частей номера в базе данных обращение к которой будет осуществляться через репозиторий?
    Ответ написан