Есть ли пример модели с богатой долей?
Я ищу простой пример, чтобы проиллюстрировать преимущества использования модели с богатым доменом. В идеале мне бы хотелось, чтобы список до и после кода (который должен быть как можно короче).
Прежде чем вводить код, следует показать проблему, решаемую с использованием модели анемичного домена, и достаточно много процедурного кода уровня обслуживания, а список после кода должен показывать ту же проблему, которая решается с использованием богатого объектно-ориентированного домена модель.
В идеале список кодов должен быть в Java или Groovy, но что-то подобное (например, С#) будет делать.
Ответы
Ответ 1
Я дам вам простой пример реального производственного кода:
Person.groovy:
List addToGroup(Group group) {
Membership.link(this, group)
return groups()
}
Membership.groovy:
static Membership link(person, group) {
def m = Membership.findByPersonAndGroup(person, group)
if (!m) {
m = new Membership()
person?.addToMemberships(m)
group?.addToMemberships(m)
m.save()
}
return m
}
Всякий раз, когда я хочу связать человека с группой, я могу просто сделать person.addToGroup(group)
Процедурный код будет выглядеть примерно так: на вашем контроллере:
def m = Membership.findByPersonAndGroup(person, group)
if (!m) {
m = new Membership()
person?.addToMemberships(m)
group?.addToMemberships(m)
m.save()
}
На первый взгляд, вы можете сказать, что можете обернуть это в функцию, и вам хорошо идти.
Но преимущество богатого доменного дизайна IMHO в том, что оно ближе к тому, как вы думаете, таким образом, ближе к рационализации. В этом конкретном примере я просто хочу добавить человека в группу, и код будет читать именно это.
Это короткий пример, как вы просили, но легко расширить этот пример и увидеть, что вы можете создавать сложные взаимодействия с надлежащим моделированием домена.
Вы также можете увидеть Мартина Фаулера Транзакция Script vs Domain Model для краткого объяснения этих двух шаблонов, которые я считаю связанными с DDD.
Ответ 2
Возможно, эта презентация Джимми Богара содержит то, что вы просите
https://github.com/jbogard/presentations/tree/master/WickedDomainModels
Ответ 3
Я думаю, что никто не проводил такого сравнения, и если бы это было так, то это было бы мало. Domain Driven Design пытается решить сложность, и простой пример не содержит сложности.
Может быть Проект Driven Step by Step даст вам несколько ответов.
Ответ 4
Это точно не отвечает на ваш вопрос, но я вижу противоположность архитектуры, управляемой доменами, как дизайн, управляемый базой данных. В проекте, основанном на базе данных, сначала создается схема базы данных, а затем вы создаете свои классы с полным пониманием того, как выглядит схема. Преимущество состоит в том, что вы лучше понимаете, что происходит "под капотом", и минимизируйте влияние несоответствия импеданса. Однако недостатком является то, что схема базы данных, поскольку она реляционная, а не объектно-ориентированная, не очень хорошо переводит объекты (например, в реляционных базах данных нет понятия коллекции).
В доменном дизайне теоретически вы создаете свои объекты данных так же, как и любой другой класс, и рассматриваете базу данных как просто уровень сохранения. В терминах Layman база данных является только контейнером для хранения, и вам все равно, КАК хранятся объекты, только что они каким-то образом хранятся. Это устраняет несоответствие импеданса, и вам остается меньше беспокоиться. На практике, однако, вы все равно должны знать, как хранятся объекты, и могут возникнуть проблемы с производительностью, когда используемая вами ORM пытается выплеснуть сложный SQL-запрос.
Edit:
Вот пример того, какой дизайн, основанный на доменах, должен быть в принципе. Скажем, у вас есть класс Person, например (на С#):
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public ICollection<Person> Relatives { get; set; }
public Company Employer { get; set; }
}
Теперь, в реляционной базе данных, это, вероятно, переведет на 3 таблицы, таблицу Person, таблицу адресов и таблицу Company, с кучей отношений между ними. Однако это значительно отличается от того, как программист видит этот объект. Программист видит его как экземпляр объекта Person с 4 параметрами, один из которых - ICollection
. Это не очень хорошо сочетается с структурой таблицы базы данных, следовательно, "несоответствие импеданса" или в терминах Laymen, разница в макете между реляционной моделью и объектной моделью.
В доменном дизайне я должен это сделать:
Person person = new Person();
// set each property to something
Database.Save(person);
Теперь объект person сохраняется. Я могу получить его так:
Person databasePerson = Database.Get<Person>(idOfPerson);
И он вернет мой объект Person
, как и прежде, чем я его сохранил. Таким образом, я не беспокоюсь о том, как файл данных сохраняет его или беспокоится о несоответствии импеданса. Я просто сохраняю его и извлекаю его по мере необходимости.
Это все в теории. На практике вам, вероятно, придется вручную указать "сопоставление" или как классы узнают, какую таблицу/столбец в базе данных получить данные. Он может стать довольно сложным, когда вы пытаетесь сопоставить более сложные типы, такие как словари и другие ADT, а также когда вы пытаетесь извлечь данные из нескольких таблиц в один класс.