Дизайн, управляемый доменом — модель домена и объект Hibernate

Являются ли Hibernate Entity такими же, как модели предметной области?

См. следующий пример.

Метод 1. Модель предметной области и объект относятся к одному классу. Модель предметной области "является" сущностью

@Entity
@Table(name = "agent")
class Agent
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "agent_number", unique = true, nullable = false)
    private String agentNumber;

    @Column(name = "agent_name", nullable = false)
    private String agentName;

    // Busines logic methods
}

Способ 2. Домен и объект — разные функции. Модель предметной области "имеет" сущность

class Agent
{
    // Hibernate entity for this domain model
    private AgentEntity agentEntity;

    // Getters and setters to set the agentEntity attributes

    // Business logic
}

Из приведенных выше 2 методов, какой из них является правильным способом реализации DDD? Я считаю, что метод 2 является правильным, потому что вы, по сути, контролируете доступ к конфиденциальному объекту, а вложенный объект (модель предметной области) имеет всю бизнес-логику/операции в модели предметной области. Но мои коллеги по работе предполагают, что они по сути одинаковы. И согласно им цель Hibernate Entity — представлять модель предметной области в данной системе. Моделирование сущности как модели предметной области на самом деле упрощает дизайн. Это связано с тем, что репозиторий использует Entity для выполнения операций CRUD. Поэтому, если модель «имеет» сущность, то для сохранения сущности репозиторий должен быть внедрен в модель предметной области. Это сделает конструкцию излишне сложной.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
14
0
4 262
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Поскольку в данном случае вы упомянули технологию Hibernate, это означает, что вы говорите о реализация. Проект, управляемый предметной областью, касается как абстрактного, например. Модель и Реализация.

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

Этот статья говорит о проблеме, с которой вы столкнулись.

Вы спросили, совпадает ли Модель домена с Спящий объект. Ответ НЕТ.

Спящий объект — это специфика технологии, в данном случае это объект, являющийся частью структуры ORM. Спящий объект и Объект DDD, как определено DDD, являются разными вещами, поскольку Объект DDD является абстрактной вещью, если определяет идею (шаблон) и дает рекомендации о том, что это за идея и что она представляет. Спящий объект — это объект Java, который создается, отслеживается, сохраняется, отбрасывается и собранный мусор.

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

Вы используете Спящие объекты или любой другой тип технологии, такой как Сущность Framework (это то же самое, объект в программе OO) реализовать Модель домена. Один и тот же Модель домена может быть реализован на разных языках с использованием разных технологий. Эти реализации будут различаться в зависимости от того, что предоставляет технология.

Например, если вы пишете серверную часть NodeJs с MongoDB и хотите использовать ORM для реализации Модель домена, вы застрянете с использованием Шаблон активной записи (вероятно, Mongoose), потому что это единственные, которые люди реализовали (по крайней мере, я мог не нашел никаких других фреймворков, которые не являются Active Record, если вы их найдете, пожалуйста, дайте мне знать). Реализация DDD таким образом может быть очень сложной (и может быть действительно отстойной).

В книга DDD Эрик Эванс рассказывает о том, как технологии могут помочь вам реализовать Модель или могут бороться с вами на всем пути. Когда он борется с вами или не предоставляет хороших механизмов, вы просто знаете, как это обойти.

Иногда у ORM есть требования, и вы не хотите выставлять эти вещи в свой другой код, поэтому вы можете использовать Wrapper, как в вашем Способ 2. Некоторые из них включают в себя такие вещи, как общедоступный метод get set, общедоступные конструкторы и т. д. Большинство из них используют отражение и могут иметь приватные вещи, но все же есть много проблем, таких как наличие приватного конструктора без параметров для удовлетворения фреймворка, и ваш код становится грязным с большим количеством вещи, которые не связаны с вашей моделью, но существуют, потому что они нужны вашей структуре (ВАУ!). Это тоже может привести к ошибкам. Легче совершить ошибку, имея конструктор по умолчанию, вместо хороших конструкторов с параметрами или статическими фабричными методами. Эта оболочка может представлять более чистую модель предметной области без наличия Необходимое зло, который несут фреймворки, чтобы вы могли их использовать.

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

Ответ принят как подходящий

Are Hibernate Entity is same as the domain models?

Не на самом деле нет. На практике грань между ними может быть очень размытой.

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

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

Другими словами, репозиторий выполняет (в некотором смысле) две функции; один знает, как получить данные из «агрегата» и сохранить, другой знает, как считывать данные из хранилища и строить из них агрегат.

ORM — это один из способов получить данные из внешней реляционной базы данных в локальную память.

Таким образом, ваша история загрузки может выглядеть так:

Use an identifier to load data from the database into a hibernate entity
copy the data from the hibernate entity into an aggregate
return the aggregate

И магазин может выглядеть

Copy data from the aggregate into a hibernate entity
Save the hibernate entity.

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

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

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

Domain and Entity are different functions. Domain model "has-an" entity

Ваши коллеги правы: они равнозначны по большинству важных аспектов. Модель домена зависит от ваших объектов гибернации.

Ни один из них не соответствует тому, что описал Эванс в своей книге.

Оба они похожи на то, что сделали многие команды на практике. Помещение логики домена непосредственно в объект гибернации, насколько я могу судить, является распространенным подходом.

Если бы вы действительно разделяли их, то ваш репозиторий выглядел бы примерно так:

Agent AgentRepository::find(id) {
    AgentEntity e = entityManager.find(id)
    Agent a = domainFactory.create( /* args extracted from e */ )
    return a
}

void AgentRepository::store(Agent a)
    AgentEntity e = entityManager.find(id)
    copy(a, e)
}

// I think this is equivalent
void AgentRepository::store(Agent a)
    AgentEntity e = entityManager.find(id)
    entityManager.detach(e)
    copy(a, e)
    entityManager.merge(e)
}

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

Стоит ли хлопот дополнительная степень разделения? Это зависит. Существует сильный когнитивный диссонанс между объектно-ориентированными шаблонами, используемыми для описания моделей предметной области, и средами выполнения лица без гражданства.

Спасибо за ваш ответ. При использовании Java Hibernate репозиторий использует Entity для операций CRUD. Поэтому, если мне нужно реализовать метод 2, модель предметной области должна иметь зависимость от репозитория, введенную для сохранения объекта, потому что модель предметной области «имеет» сущность в методе 2. Когда внедрение компонентов зависимости в модель предметной области сделает дизайн очень некрасиво на мой взгляд. Пожалуйста, поправьте меня, если я ошибаюсь.

Vino 19.04.2019 14:23

Другие вопросы по теме