Re[7]: Anemic Domain Model vs Rich Domain Model
От: meowth  
Дата: 29.05.09 11:41
Оценка: +1
Здравствуйте, gandjustas и IB, Вы писали:

Нет, ребят, вы честно жжоте

Человек (Mike Chaliy) показывает вам на примере своего проекта, как оно работает -- что оно а)элегантно б)реально РАБОТАЕТ (это тоже важно) б)легко сопровождаемо в)не содержит тех проблем, которые вы пытаетесь отыскать в решении.

А вы по-прежнему продолжаете доказывать, что его решение плохое и полнится косяками и костылями -- не этими, так теми. Но при этом почему-то сами ставите ему вопрос, сами отвечаете, и в своем ответе находите недочеты, которые приписываете решению.
Re[7]: Anemic Domain Model vs Rich Domain Model
От: Mike Chaliy Украина http://chaliy.name
Дата: 29.05.09 11:48
Оценка:
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, Mike Chaliy, Вы писали:


MC>>Мы этим гордимся,

IB>Тем, что при изменении нужно поменять в четырех местах, а не в двух? Молодцы! =)
Нам надо менять тока в том месте где надо.
1) Поменлась бизнес логика поменяли в моделе
2) Поменялся публичный АПИ, поменяли в ДТО
3) Потребовалось перелаяутить хранилище, со скрипом но и это сделали.

MC>>у нас не бывает ситуаций когда поменял чето в доменной моделе а отвалиось гдето на ремо сервере.

IB>Легко у вас такая ситуация бывает — в модели поле удалили, а в DTO забыли, а у клиента на это поле была критичная логика завязана. В запросе пришел NULL — клиент лег.
Ну и кто дурак? У нас такого не быват. У нас публичный АПИ тестируеться.

MC>>С свременными ИДЕ и тулингом потдерживать такую синхронизацию очень дешево.

IB>Просто признайтесь, что вы любите двойную работу.


MC>>Уже говорили, выборки это не респонсибилити доменной модели, это респонсибилити репортинга.

IB>Для тебя это возможно будет новостью, но 95% задач современного приложения — это репортинг.
IB>Отсюда делаем вывод о применимости жирной модели.
Для меня это вообще не новость, у нас репортинг это инфраструктура к которой модель вообще не имеет отношения.
Обычно выбираеться из нескольких вариантов.
1) Для репортинга похожего по структуре на доменную модель, данные беруться из тех же маппингов что и доменная модель.
2) Для более сложного репортинга делаем свои маппинги.
3) Для совсем сложного пишем кастомный код.

Так как результатом репорта всерано являеться ДТО, то не изменение реализации, не изменение модели никак на результат не влияет, соотвевено клиенты живут себе долго и щасливо.

Если тебе хочеться сказать что типа ваша модель покрывает 5% кода приложения, а вот наша анемичная 95%(мне кажеться 40%), я с тобой вполне согласен. Для нас это не являеться камнем претконовения. Все ДТО у нас анемичны по определению.

MC>>Решение и для рич моделей и для анмемичных идентичное.

IB>Когда есть LINQ необходимость в промежуточных DTO отпадает, можно все по месту построить, для стройной модели, разумеется.
LINQ никто не отменял, с чего ты взял что мы не используем LINQ? У нас куча траверсинга на LINQ, репорты тож на LINQ...
А тут я живу и пишу...
Re[7]: Anemic Domain Model vs Rich Domain Model
От: Mike Chaliy Украина http://chaliy.name
Дата: 29.05.09 11:57
Оценка:
Здравствуйте, gandjustas, Вы писали:


MC>>Мы этим гордимся, у нас не бывает ситуаций когда поменял чето в доменной моделе а отвалиось гдето на ремо сервере. А все потому что DTO полностью развязаны. С свременными ИДЕ и тулингом потдерживать такую синхронизацию очень дешево.

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

G>>>Второе — достачно сложное создание произвольных выборок.

MC>>Уже говорили, выборки это не респонсибилити доменной модели, это респонсибилити репортинга.
G>
G>Почему такая хорошая DDD заставляет выделять отдельное понятие репортинга? (на деле — любое отображение информации)
Ым, потому что у нее респонсибилити другая... У репортинга своя, у модели другая...

G>Суть не в DTO, а в способах его получения.

И чем они отличаються? Если ты думаеш что мы пользуемся чем то секретным ты ошибаешся, все на виду...

MC>>Решение и для рич моделей и для анмемичных идентичное.

G>Ну покажи полное решение для такого случая в rich, учитывая что надо получать далеко не все все товары, там есть пейджинг, видимость, выборка по категории итп. Для каждого товара существует куча картинок и надо получить первую.


 (from p in Query() // Query возвращет IQueryable<Product>
        where p.Category.Contains("sdfsdf")
        select new ProductListItem(){
          Name = p.Name; 
          ImageUrl = p.Images.First().Url
        }).Take(10).ToList();


Чето типа того, писал прямо тут, могут быть ошибки.
В реальной реализации пейджинг, сортинг, фильтры находятсья в инфраструктуре.
А тут я живу и пишу...
Re[7]: Anemic Domain Model vs Rich Domain Model
От: Mike Chaliy Украина http://chaliy.name
Дата: 29.05.09 12:04
Оценка:
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, Mike Chaliy, Вы писали:


MC>>Так вот за счет того что у нас есть енкапсуляция, код бизнес процесов получаеться максимально читабельным.

IB>Код бизнес-процессов, за счет такой "енкапсуляции" получается малопредсказуемым и неочевидным.

И что там не очевидного? И что ты не можеш предсказать?

MC>>нет мелось ввиду то что имелось,

IB>Тогда ты непонятно с чем споришь..
MC>>В любом случае твой пример всеравно не читабельный.
IB>Он гораздо понятнее чем твой.. )

Сделал код более или мение читаебльным убрав необходимые фитчи, прикольно.

Так еще более читабельней... И респонсибилити ясна.

public CreateOrder(number){
}
А тут я живу и пишу...
Re[6]: Anemic Domain Model vs Rich Domain Model
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.05.09 12:21
Оценка:
Здравствуйте, Mike Chaliy, Вы писали:

MC>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, Mike Chaliy, Вы писали:


MC>>>Здравствуйте, gandjustas, Вы писали:


ЛИ>>>>>3) Если имеют место большие объёмы данных, то лучше вообще не связываться с Domain Model. К счастью, большинство транзакционных сценариев не предполагает большого количества объектов, а значит можно в полной мере использовать преимущества RDM;

G>>>>Еще раз? Какие премущества rich перед anemic? Бредятину типа "в ней больше ООП" не рассматриваем.
G>>>>Покажите пример кода, где по rich гораздо удобнее anemic.

MC>>>Вот можем начать с этого.


MC>>>Rich

MC>>>
MC>>>public void CreateOrder(number){
MC>>>  var order = _orderFactory.Create(number);

MC>>>  order.AddItem(product1, weight);
MC>>>  order.AddItem(product2, weight);

MC>>>  _orderRepository.Add(order);
MC>>>}
MC>>>

G>>Ага, еще код AddItem покажи, и валидации.
G>>Кстати в какой момент она выполняется?

MC>Зачем, ты же просил где лушче. Так вот за счет того что у нас есть енкапсуляция, код бизнес процесов получаеться максимально читабельным.


MC>>>Anemic

MC>>>
MC>>>public void CreateOrder(number){
MC>>>  validateOrderNumber(number);
MC>>>  var total = calcualteTotal(weight1, weight2);
MC>>>  validateIfTotalAcceptable(total);

MC>>>  var order = new Order(){Number = number, Total = total};
MC>>>  var item1 = new Item(){OrderId = order.Id, ProductId = product1.Id, Weight = weight1};
MC>>>  var item2 = new Item(){OrderId = order.Id, ProductId = product2.Id, Weight = weight2};

MC>>>  _orderDAL.InsertOrder(order);
MC>>>  _orderDAL.InsertOrderItem(item1);
MC>>>  _orderDAL.InsertOrderItem(item2);
MC>>>}
MC>>>


G>>Наверное имелось ввиду

G>>
G>>public void CreateOrder(number)
G>>{
G>>  var order = new Order(){Number = number, Total = calcualteTotal(weight1, weight2)};
G>>  var item1 = new Item(){Order = order, Product = product1, Weight = weight1};
G>>  var item2 = new Item(){Order = order, Product = product2, Weight = weight2};

G>>  _validationService.Validate(order);
G>>  _orderRepository.Add(order);
G>>}
G>>


MC>нет мелось ввиду то что имелось,

Тогда только могу констатировать факт что ты не умеешь рабоать со стройной моделью.

MC>1) ты отпарвил валидацию в конец, должно быть в начале, иначе возможны колизии, принцип фаил фаст знаеш? Обьяснить почему это проблема?

Ну попробуй объясни. У меня нету ни одной тяжелой операции, которая вызывается неявно. А наносекнуды, затраченные на создания объектов роли не играют.

MC>2) ты поубирал ИД поля. Но вы же с ИБ орете что вам надо Order — Item для одного отдела, TradingPeriod — Item для другого. Как же это вы свзянанные обьекты сможете представить для двух отделов. Как вы сможете собрать из этого ДТО для веб сервиса, если оно все в коде зареференшено.

Нивопрос.
var qForDep1 = _ordersRepository.With(o => o.Items);
var qForDep2 = from item in _itemsRepository
               group item by item.Year;

Модель данных одна, представлений — скольтко угодно.

MC>3) ты поубирал ИД поля. Это обозначает что у вас юзаеться ОРМ и тоже может юзаться лейзи лоад.

Естественно ОРМ, а LL вообще нету (EF) или отключаем (Linq2SQL)

MC>4) ты нарушил СРП в вашем понимании, обьекты теперь хранят не тока данные обьекта, но и ссылки на другие обьекты.

Ничего не нарушил. Объекты не меняются пока не изменилась модель данных.

G>>А вообще на лице денормализация. Надо бы еще объяснить зачем она нужна и почему бы не поддерживать целостность триггерами в БД, если денормализация нужна.

MC>Ты конкретней, ты где нашел денормализацию?
Хранение total в order.

MC>Ты про Тотал? Почитай про архитектуры финансовых систем. Там никогда агрегатные результаты не считаються динамически. Если один раз ордер продался по цене 20.00089 денег, то даже когда поменяеються требования к округлению он всеравно должно остаться 20.00089.

Там же вес, причем ту архитектура финансовых систем?

MC>Плюс номрализация Тотала не потдаеться юнит тестированию.

Это повод вносить денормализацию?

G>>Кстати, что здесь Order.Total? Почему мы total проверяем при сохранении, а не там где действительно надо (при отправке например)?


MC>Потому что это бизнес процес который считает тотал. И этот же бизнес процес должен сказать если там что-то не так.

Какой процесс? Там же создание заказа? Почему "создание заказа" считает Total, а не кто либо еще, кому оно надо?

MC>Отправка это вообще не контекстаная операция. Нафига мне валидировать тотал если он уже посчитан и дефакто валидный?

Потому что твой вариант таит больше проблем, чем ты можешь представить.
Нпапример пересчет тотала при добавлении\удалении\редактировании айтема.
Тебе понадобится поднять в память все айтемы для такой операции.
Очень дорогостоящее редактирование атема выйдет, если учесть что отправка ордера может и не произойти.


MC>В любом случае твой пример всеравно не читабельный. Попробуй его прочесть плаин текстом. Куча дублирования и мусора.

А ты не привел код AddItem.

Я кстати совершенно спокойно могу создать экстеншен метод AddItem и получить туже самую читаемоть что и у тебя.
Re[8]: Anemic Domain Model vs Rich Domain Model
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.05.09 12:30
Оценка:
Здравствуйте, meowth, Вы писали:

M>Здравствуйте, gandjustas и IB, Вы писали:


M>Нет, ребят, вы честно жжоте


M>Человек (Mike Chaliy) показывает вам на примере своего проекта, как оно работает -- что оно

Мы тут тоже все программированием занимаемся, если что

M>а)элегантно

Одинаково элегантно в любой модели. Anemic-Rich разницы не дает.

M>б)реально РАБОТАЕТ (это тоже важно)

Я свой кусок кода привел, который тоже реально работает.

M>б)легко сопровождаемо

На таком маленьком куске кода это незаметно будет. Anemic-Rich разницы не дает.

M>в)не содержит тех проблем, которые вы пытаетесь отыскать в решении.

На таком маленьком куске проблем тоже видно не будет. Хотя в том примере что Mike Chaliy привел проблемы таки есть, но они связаны с моделью опосредованно.
Re[9]: Anemic Domain Model vs Rich Domain Model
От: meowth  
Дата: 29.05.09 12:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, meowth, Вы писали:


M>>Здравствуйте, gandjustas и IB, Вы писали:


M>>Нет, ребят, вы честно жжоте


M>>Человек (Mike Chaliy) показывает вам на примере своего проекта, как оно работает -- что оно

G>Мы тут тоже все программированием занимаемся, если что

M>>а)элегантно

G>Одинаково элегантно в любой модели. Anemic-Rich разницы не дает.

M>>б)реально РАБОТАЕТ (это тоже важно)

G>Я свой кусок кода привел, который тоже реально работает.

M>>б)легко сопровождаемо

G>На таком маленьком куске кода это незаметно будет. Anemic-Rich разницы не дает.

M>>в)не содержит тех проблем, которые вы пытаетесь отыскать в решении.

G>На таком маленьком куске проблем тоже видно не будет. Хотя в том примере что Mike Chaliy привел проблемы таки есть, но они связаны с моделью опосредованно.

Весь цимес в том, что он не доказывает и не собирается, что ваша модель -- плоха. Он говорит "ну, пользуйтесь anemic, раз вам в ней нормально. Но только имейте в виду, что Rich -- не такая ужасная, как вы думаете, а ее недостатки можно обойти, а не признавать неисправимыми"
А вы -- непременно пытаетесь это сделать по отношению к его модели: Rich model == evil под любым соусом.

Ладно, лучше я не буду спорить, потому что мне ближе его подход (особенно в плане чистоты бизнес-скриптов), и я буду необъективен. Уже, скорее всего
Re[7]: Anemic Domain Model vs Rich Domain Model
От: Mike Chaliy Украина http://chaliy.name
Дата: 29.05.09 12:52
Оценка:
Здравствуйте, gandjustas, Вы писали:


MC>>1) ты отпарвил валидацию в конец, должно быть в начале, иначе возможны колизии, принцип фаил фаст знаеш? Обьяснить почему это проблема?

G>Ну попробуй объясни. У меня нету ни одной тяжелой операции, которая вызывается неявно. А наносекнуды, затраченные на создания объектов роли не играют.

http://en.wikipedia.org/wiki/Fail-fast
В общем случае обозначает что в начале метода должны быть гарантированы рабочие инварианты. Например number == null, а он используеться для генерации текстового представления Айтама. Упс. NullRefrenceException. Это тока иллюстрация. С точки зрения безопасности это хорошо описано в Writing Secure Code, Second Edition

MC>>2) ты поубирал ИД поля. Но вы же с ИБ орете что вам надо Order — Item для одного отдела, TradingPeriod — Item для другого. Как же это вы свзянанные обьекты сможете представить для двух отделов. Как вы сможете собрать из этого ДТО для веб сервиса, если оно все в коде зареференшено.

G>Нивопрос.
G>
G>var qForDep1 = _ordersRepository.With(o => o.Items);
G>var qForDep2 = from item in _itemsRepository
G>               group item by item.Year;
G>

G>Модель данных одна, представлений — скольтко угодно.
И что? Пусть будет без ИД, и хотя у тебя теперь не ПОКО, ну да ладно. Это все равно значительно не облечило чтение.
Ну и ты не боишся что всю БД выгрузиш в память .
А еще ты не боишся что каието рефернсы будут нулл?

MC>>4) ты нарушил СРП в вашем понимании, обьекты теперь хранят не тока данные обьекта, но и ссылки на другие обьекты.

G>Ничего не нарушил. Объекты не меняются пока не изменилась модель данных.
У вас меняющиеся понятие СРП, в прошлый раз было тока хранение данных.

MC>>Ты про Тотал? Почитай про архитектуры финансовых систем. Там никогда агрегатные результаты не считаються динамически. Если один раз ордер продался по цене 20.00089 денег, то даже когда поменяеються требования к округлению он всеравно должно остаться 20.00089.

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

MC>>Плюс номрализация Тотала не потдаеться юнит тестированию.

G>Это повод вносить денормализацию?
Да

G>>>Кстати, что здесь Order.Total? Почему мы total проверяем при сохранении, а не там где действительно надо (при отправке например)?


MC>>Потому что это бизнес процес который считает тотал. И этот же бизнес процес должен сказать если там что-то не так.

G>Какой процесс? Там же создание заказа? Почему "создание заказа" считает Total, а не кто либо еще, кому оно надо?
Потому что тотал должен быть сохранен единожды быв посчитан. Никто другой не должен самочинствовать и его считать. Кто-то другой может посчтиать какой-то свой тотал.

MC>>Отправка это вообще не контекстаная операция. Нафига мне валидировать тотал если он уже посчитан и дефакто валидный?

G>Потому что твой вариант таит больше проблем, чем ты можешь представить.
Конкретней, плз.
G>Нпапример пересчет тотала при добавлении\удалении\редактировании айтема.
Ессно у нас то рич модел, у нас не может получиться что тотал будет посчитан не правильно. И да пересчет тотала происходит при операциях с айтемами.

G>Тебе понадобится поднять в память все айтемы для такой операции.

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

MC>>В любом случае твой пример всеравно не читабельный. Попробуй его прочесть плаин текстом. Куча дублирования и мусора.

G>А ты не привел код AddItem.
Зачем он тебе нужен если речь идет о читабельности этого метода. Я еще раз повторю, AddItem это черный ящик который гарантированно правильно добавит айтем и правильно изменит состояние ордера.

G>Я кстати совершенно спокойно могу создать экстеншен метод AddItem и получить туже самую читаемоть что и у тебя.

Добавив экстеншен метод у тебя получиться то о чем говорит ИБ. Ты не знаеш что делает AddItem. В рич моделе это решаеться скрытием состояния, рутагрегатами, боундариес, иммутабле валью обьектами и тому подобным. В анемик вы вообще никак не защищены от сайдеффектов. AddItem у вас может полезть в какуюто левую проперти, полезть в БД и тому подобное. Вобщемто экстеншен метод это будет самы главный антиагрумент.

Ты еше можеш и партиал использовать.

Собсно это был тока пример иллюстрирующий проблему, у AddItem может быть логика...
А тут я живу и пишу...
Re[8]: Anemic Domain Model vs Rich Domain Model
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.05.09 12:59
Оценка:
Здравствуйте, Mike Chaliy, Вы писали:

MC>Здравствуйте, gandjustas, Вы писали:



MC>>>Мы этим гордимся, у нас не бывает ситуаций когда поменял чето в доменной моделе а отвалиось гдето на ремо сервере. А все потому что DTO полностью развязаны. С свременными ИДЕ и тулингом потдерживать такую синхронизацию очень дешево.

G>>
G>>Ведь гораздо легче вообще не иметь такой синхронизации.
MC>Гм, чем легче? Прототип набрасать да легче, а для потдерживаемого приложения вложения в эту синхронизацию не составляють и тысячных долей проекта....
Ты не понял, у меня готовые приложения без такого рода DTO работают. Вообще.
И поддерживаются отлично.

G>>>>Второе — достачно сложное создание произвольных выборок.

MC>>>Уже говорили, выборки это не респонсибилити доменной модели, это респонсибилити репортинга.
G>>
G>>Почему такая хорошая DDD заставляет выделять отдельное понятие репортинга? (на деле — любое отображение информации)
MC>Ым, потому что у нее респонсибилити другая... У репортинга своя, у модели другая...
Странно, я anemic использую, ни разу не доходило до создания отдельной инфраструктуры репортинга (отображения).
Что тогда DDDшными методами делается?

G>>Суть не в DTO, а в способах его получения.

MC>И чем они отличаються? Если ты думаеш что мы пользуемся чем то секретным ты ошибаешся, все на виду...
Код в студию.

MC>>>Решение и для рич моделей и для анмемичных идентичное.

G>>Ну покажи полное решение для такого случая в rich, учитывая что надо получать далеко не все все товары, там есть пейджинг, видимость, выборка по категории итп. Для каждого товара существует куча картинок и надо получить первую.


MC>
MC> (from p in Query() // Query возвращет IQueryable<Product>
MC>        where p.Category.Contains("sdfsdf")
MC>        select new ProductListItem(){
MC>          Name = p.Name; 
MC>          ImageUrl = p.Images.First().Url
MC>        }).Take(10).ToList();
MC>

Ух ты, прям как у меня.
Тогда зачем вообще DDD? Aggregation roots всякие.
Где же Ubiquitous Language и читаемый Domain Expretом код?
Кстати, а кто вызывает показанный выше код?

MC>Чето типа того, писал прямо тут, могут быть ошибки.

MC>В реальной реализации пейджинг, сортинг, фильтры находятсья в инфраструктуре.
В какой инфраструктуре. Давай полный пример.
На входе есть products:IQueryable<Product>, который возвращает все записи. Показать надо первые 10 видимых, из категории X.
Какие будут классы, как распределена логика?
Re[10]: Anemic Domain Model vs Rich Domain Model
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.05.09 13:03
Оценка:
Здравствуйте, meowth, Вы писали:

M>Здравствуйте, gandjustas, Вы писали:


G>>Здравствуйте, meowth, Вы писали:


M>>>Здравствуйте, gandjustas и IB, Вы писали:


M>>>Нет, ребят, вы честно жжоте


M>>>Человек (Mike Chaliy) показывает вам на примере своего проекта, как оно работает -- что оно

G>>Мы тут тоже все программированием занимаемся, если что

M>>>а)элегантно

G>>Одинаково элегантно в любой модели. Anemic-Rich разницы не дает.

M>>>б)реально РАБОТАЕТ (это тоже важно)

G>>Я свой кусок кода привел, который тоже реально работает.

M>>>б)легко сопровождаемо

G>>На таком маленьком куске кода это незаметно будет. Anemic-Rich разницы не дает.

M>>>в)не содержит тех проблем, которые вы пытаетесь отыскать в решении.

G>>На таком маленьком куске проблем тоже видно не будет. Хотя в том примере что Mike Chaliy привел проблемы таки есть, но они связаны с моделью опосредованно.

M>Весь цимес в том, что он не доказывает и не собирается, что ваша модель -- плоха. Он говорит "ну, пользуйтесь anemic, раз вам в ней нормально. Но только имейте в виду, что Rich -- не такая ужасная, как вы думаете, а ее недостатки можно обойти, а не признавать неисправимыми"

Тут есть некоторое отношение порядка, выражение для которого еще не придумано (и вряд ли будет придумиано когда-нибудь). Назовем его "лучше".
Так вот мы пытаемся показать что anemic лучше rich, а Mike Chaliy говорит что rich лучше anemic, причем неважно каким способом указывая недостатки одно из подходов или достоинства другого.
Re[9]: Anemic Domain Model vs Rich Domain Model
От: meowth  
Дата: 29.05.09 13:05
Оценка:
Здравствуйте, gandjustas, Вы писали:

MC>>
MC>> (from p in Query() // Query возвращет IQueryable<Product>
MC>>        where p.Category.Contains("sdfsdf")
MC>>        select new ProductListItem(){
MC>>          Name = p.Name; 
MC>>          ImageUrl = p.Images.First().Url
MC>>        }).Take(10).ToList();
MC>>


G>На входе есть products:IQueryable<Product>, который возвращает все записи. Показать надо первые 10 видимых, из категории X.

G>Какие будут классы, как распределена логика?

Сорри, что лезу, но имхо все написано же:
p.Category.Contains("sdfsdf")... // из категории X
.. .Take(10) ... // первые 10
Re[2]: Anemic Domain Model vs Rich Domain Model
От: GlebZ Россия  
Дата: 29.05.09 13:06
Оценка:
Здравствуйте, Лобанов Игорь, Вы писали:

ЛИ>Хотел бы подвергнуть сомнению все эти пункты:

ЛИ>1) Хорошо приготовленная RDM в этом смысле превосходит ADM, и Вы перечислили причины почему в той части, где говорите о преимуществах RDM;
Тут я бы проитерполировал сложность сопровождения в зависимости от количества сущностей. При большом количестве, RDM должен быть эффективней. Но RDM также приводит к более высоким требованиям по качеству архитектуры и качеству дизайна.

ЛИ>2) Переносимость бизнес-объектов между физическими звеньями (то есть за границы адресного пространства) -- довольно редкое требование, нет необходимости ориентироваться на него в общем случае. Использование бизнес-объектов RDM в разных слоях в пределах одного физического звена при адекватных инструментах никакой проблемы не составляет;

В паттернах Фаулера есть ключевое слово Enterprise о котором часто забывают. А это практически всегда означает, что клиенты как минимум хотят с кем-то, зачем-то интегрироваться. Поэтому переносимость нужна. А ежели объекты отчуждаемы, то это ващщее... Кроме того, даже на уровне потребления нельзя использовать голые классы. Иначе мы нарушаем изоляцию через фасад.
Насчет инструментов — я не возражал.

ЛИ>3) Если имеют место большие объёмы данных, то лучше вообще не связываться с Domain Model. К счастью, большинство транзакционных сценариев не предполагает большого количества объектов, а значит можно в полной мере использовать преимущества RDM;

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

ЛИ>4) Постоянная валидность бизнес-объектов и RDM -- совершенно не связанные между собой аспекты, в случае ADM точно так же можно наложить ограничение постоянной валидности.

В ADM это как раз сделать очень сложно.

ЛИ>К тому же современные средства валидации бизнес-объектов поддерживают несколько степеней валидности, в зависимости от контекста.

Без возражений. Только вопрос что имелось ввиду под средствами?

ЛИ>То, что Вы называете сглаживанием недостатков модели, я бы назвал просто правильным способом реализации RDM

Немножко добавлю. Я — разработчик NET. В случае реализации ADM, я собираю приложения не пользуясь излишним инструментарием(ну ессно это не касается отчетов, OLAP и другой специализации). Это позволяет уменьшать сложность вхождения в проект, углубляет понимание самих процессов происходящих в решении. Я могу на коленке, собрать приложение любой степени сложности. И второе, что хотелось бы повторить. Я хочу не отвлекаться на правильность дизайна OOP. В реальности, реализация правильного дизайна OOP — весьма сложная штукенция. Можно заделать грабли.

ЛИ>P.S. Совсем недавно я писал развёрнутую статью на эту тему у себя в блоге, если любопытно:

ЛИ>http://javatoday.ru/2009/03/rich-domain-model/
Что-то уж очень страшное. Или я ваще ничего не понял, или одно из двух. У постановки может быть большое кол-во графов. Ну например, есть иерархия подчинения, типа отдел с директором, подчиненные подразделения и т.д. А есть проектные группы, которым эта иерархия ваще по барабану, так как там 3 чела с одного подразделения, 2 чела с другого. И у этих двух иерархий, независимые связи и некоторая ортогональная логика. Зачем мешать все в одном объекте? Не проще ли выделить некоторую логику в раздельные сервисы? Band of Four здря книжки писали?
Re[11]: Anemic Domain Model vs Rich Domain Model
От: meowth  
Дата: 29.05.09 13:09
Оценка:
Здравствуйте, gandjustas, Вы писали:


M>>Весь цимес в том, что он не доказывает и не собирается, что ваша модель -- плоха. Он говорит "ну, пользуйтесь anemic, раз вам в ней нормально. Но только имейте в виду, что Rich -- не такая ужасная, как вы думаете, а ее недостатки можно обойти, а не признавать неисправимыми"

G>Тут есть некоторое отношение порядка, выражение для которого еще не придумано (и вряд ли будет придумиано когда-нибудь). Назовем его "лучше".
G>Так вот мы пытаемся показать что anemic лучше rich, а Mike Chaliy говорит что rich лучше anemic, причем неважно каким способом указывая недостатки одно из подходов или достоинства другого.

Покажите, где он говорит, что "лучше". Он говорит -- не хуже, потому что описанные вами ужос-нахи, которые неотвратимо настигнут всякого, осмелившегося поюзать rich, зачастую надуманны и оторваны от практики, а вы с эти спорите
причем где _вы_ говорите, что anemic лучше, я вижу -- например, в строчке выше; вы и не скрываете
Re[10]: Anemic Domain Model vs Rich Domain Model
От: GlebZ Россия  
Дата: 29.05.09 13:12
Оценка:
Здравствуйте, meowth, Вы писали:

M>А вы -- непременно пытаетесь это сделать по отношению к его модели: Rich model == evil под любым соусом.

Гы-гы. Собственно поэтому я и открыл этот флейм.
Re[15]: Anemic Domain Model vs Rich Domain Model
От: IB Австрия http://rsdn.ru
Дата: 29.05.09 13:16
Оценка: 15 (1)
Здравствуйте, GlebZ, Вы писали:

GZ>Ну наконец — то.

То есть, метрика таки есть. уже хорошо.

GZ>Ну и что тут обсуждать?

Сам не понимаю, я тебе про одно, а ты про другое.

GZ>Это аггрегируемая информация.

Да ну нет же.

GZ> Ибо на физическом уровне, доступ управляется набором идентификаторов связанных с объектом.

Так родительский идентификатор в объекте и так есть, тогда вообще ничего дополнительно делать не надо.

GZ> По каждому чиху просчитывать информацию? Гениальное решение.

По каждому чиху, вообще ничего делать не надо.

GZ>Ты читаешь что я пишу?

Похоже ты не читаешь, что я пишу.

GZ>Зачем????

За тем, что это важно, код понятнее и очевиднее.

GZ>Не проще ли на самом солнце кликнуть и не разбираться с проблемами бытия, орбит, и магнитных бурь.

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

IB>>Причем забыть и не передать, я не могу — компилятор поправит.

GZ>Не поправит. У тебя интерфейс не изменяется, а только дополняется.
Ты серьезно считаешь, что если я изменю сигнатуру метода с CanEdit(id), на CanEdit(id, id), мне компилятор ничего не скажет?!!

GZ>А вот зачем? Весь смысл Rich, это то что ты абстрагируешься от БД.

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

GZ>Нет. В Rich — все места связаны с методом объекта.

В Anemic тоже, только другого объекта. Вопрос не как, а по какому принципу.
В Rich — object cohesion, в Anemic — functional cohesion, и последнее — существенно лучше, с точки зрения поддрежки и изменения кода.

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

Нельзя, если типов больше одного, а вот в anemic как раз можно, вне зависимости от их количества.

GZ>Звиняюсь, coupling.

coupling как раз уменьшается.

GZ>То, что можно изменить полиморфно поведение в одном месте существенно увеличивает поддержку?

Во-первых не полиморфно, а во-вторых, существенно ухудшает, как только появляется дополнительный сценарий.

GZ>В Rich — строго наоборот. Объект решает как ему проверяться. Это большая разница.

Конечно, это один из основных косяков Rich, так как проверка зависит от контекста, значит объект должен знать обо всех контекстах.

GZ>С чего ты решил?

Со здравого смысла.
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[12]: Anemic Domain Model vs Rich Domain Model
От: IB Австрия http://rsdn.ru
Дата: 29.05.09 13:16
Оценка:
Здравствуйте, Mike Chaliy, Вы писали:

MC>Тебя интересует как работает Add это к ОРМ тулу твоего выбора.

Меня интересует, как это работает у тебя.

MC>Тебя интересует как работает Mapэто к мапперу твоего выбора.

И это тоже.

MC>И что там не к месту?

Определение твое не к месту.

MC> Именно реализация этого языка это и есть респонсибилити.

Тогда ты вообще не о тех объектах.

MC>Нарпимер для респонсибилити обьекта ордер это реализация языка по работе с оредорм.

Так данные-то где?
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[8]: Anemic Domain Model vs Rich Domain Model
От: IB Австрия http://rsdn.ru
Дата: 29.05.09 13:16
Оценка:
Здравствуйте, Mike Chaliy, Вы писали:

MC>Нам надо менять тока в том месте где надо.

Ну вот, а мы как раз про сценарий, когда везде надо. Как самый геморройный и самый часто встречающийся.

MC>Ну и кто дурак? У нас такого не быват. У нас публичный АПИ тестируеться.

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

MC>Для меня это вообще не новость, у нас репортинг это инфраструктура к которой модель вообще не имеет отношения.

А к чему же у вас тогда модель имеет отношение?

MC>Если тебе хочеться сказать что типа ваша модель покрывает 5% кода приложения, а вот наша анемичная 95%(мне кажеться 40%), я с тобой вполне согласен. Для нас это не являеться камнем претконовения. Все ДТО у нас анемичны по определению.

Отлично, так зачем вам тогда не DTO? Чтобы оставшиеся 5% выглядели красиво и правильно, по книжке?
Какую проблемы вы решаете, городя true domain model — чтобы ORM работал?

MC>LINQ никто не отменял, с чего ты взял что мы не используем LINQ? У нас куча траверсинга на LINQ, репорты тож на LINQ...

Ну правильно, у вас же там плоский DTO.
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[8]: Anemic Domain Model vs Rich Domain Model
От: IB Австрия http://rsdn.ru
Дата: 29.05.09 13:16
Оценка:
Здравствуйте, meowth, Вы писали:

M>Человек (Mike Chaliy) показывает вам на примере своего проекта, как оно работает

В том, то и дело, что не показывает.

M>-- что оно а)элегантно б)реально РАБОТАЕТ (это тоже важно) б)легко сопровождаемо в)не содержит тех проблем, которые вы пытаетесь отыскать в решении.

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

M> Но при этом почему-то сами ставите ему вопрос, сами отвечаете, и в своем ответе находите недочеты, которые приписываете решению.

Ну так он-то не отвечает, вот и приходится гадать.. =)
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[8]: Anemic Domain Model vs Rich Domain Model
От: IB Австрия http://rsdn.ru
Дата: 29.05.09 13:16
Оценка:
Здравствуйте, Mike Chaliy, Вы писали:

MC>И что там не очевидного? И что ты не можеш предсказать?

Совершенно непонятно, что валидируется, как и с привлечением каких контекстов, непонятно, что из себя представляет продукт и откуда берется, ect...


MC>Так еще более читабельней... И респонсибилити ясна.

MC>public CreateOrder(number){
MC>}
Ну вот примерно так твой код и выглядит...
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[9]: Anemic Domain Model vs Rich Domain Model
От: Mike Chaliy Украина http://chaliy.name
Дата: 29.05.09 13:24
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, Mike Chaliy, Вы писали:


MC>>Здравствуйте, gandjustas, Вы писали:



MC>>>>Мы этим гордимся, у нас не бывает ситуаций когда поменял чето в доменной моделе а отвалиось гдето на ремо сервере. А все потому что DTO полностью развязаны. С свременными ИДЕ и тулингом потдерживать такую синхронизацию очень дешево.

G>>>
G>>>Ведь гораздо легче вообще не иметь такой синхронизации.
MC>>Гм, чем легче? Прототип набрасать да легче, а для потдерживаемого приложения вложения в эту синхронизацию не составляють и тысячных долей проекта....
G>Ты не понял, у меня готовые приложения без такого рода DTO работают. Вообще.
G>И поддерживаются отлично.

Ну у меня тож есть приложения в которых уи на веб формах, логика-доступ к данным в одном слое, сотни класов менеджеров. И это все работает и потдерижвается. И что?

Ты же не можеш сравнить скорости добовления фитчеров. То что ты называеш рич моделью таковой не являеться. Соотвевенно у тебя просто нет опыта сравнить эти два подхода. Тебе с твоим подходом комфортней ок. У нас в команде рич модели это дефолтная архитектура. В тоже время рич модели не отменяют анемичных сущьностей. Всякие справочники, это просто инфа. Там нема логики. Для этого есть shared kernerl of value objects .

G>Странно, я anemic использую, ни разу не доходило до создания отдельной инфраструктуры репортинга (отображения).

G>Что тогда DDDшными методами делается?
Тока бизнес модели. Все построенно вокруг бизнес моделей. Если доменная область не позволяет построить рич модель, то естесвенный фалбек в анемичные модели. Соотвевенно иммутабилити обьектов, и соотвевенно возможность периспользовать сущьности в других слоях.
Рич модель идеальна когда стоимость реализации бизнес модели это самая большая часть бюджета. В ентрерпрайз приложениях это очень часто. Хотя уровень писателей ентерпрайз приложений обычно очень низок. А это приводит что люди думают в терминах хранилища данных. Что естевенно приводит к анемичным моделям, так как у таблиц нема поведения.

G>>>Суть не в DTO, а в способах его получения.

MC>>И чем они отличаються? Если ты думаеш что мы пользуемся чем то секретным ты ошибаешся, все на виду...
G>Код в студию.

 (from p in Query() // Query возвращет IQueryable<Product>
        where p.Category.Contains("sdfsdf")
        select new ProductListItem(){
          Name = p.Name; 
          ImageUrl = p.Images.First().Url
        }).Take(10).ToList();



MC>>>>Решение и для рич моделей и для анмемичных идентичное.

G>>>Ну покажи полное решение для такого случая в rich, учитывая что надо получать далеко не все все товары, там есть пейджинг, видимость, выборка по категории итп. Для каждого товара существует куча картинок и надо получить первую.

MC>>
MC>> (from p in Query() // Query возвращет IQueryable<Product>
MC>>        where p.Category.Contains("sdfsdf")
MC>>        select new ProductListItem(){
MC>>          Name = p.Name; 
MC>>          ImageUrl = p.Images.First().Url
MC>>        }).Take(10).ToList();
MC>>

G>Ух ты, прям как у меня.
G>Тогда зачем вообще DDD? Aggregation roots всякие.
Это репорт это не логика. DDD и всякие Aggregation roots нужны для постоения модели.

G>Где же Ubiquitous Language и читаемый Domain Expretом код?

В доменной модели.

G>Кстати, а кто вызывает показанный выше код?

Именно этот УИ. Метод MVC контроллера.

var query = new ListAllProductsQuery{};
var page = Get<IReportingService>().QueryPage(query);
return page.Results.Map(p => ProductListItemMapInstance.Map(p))


MC>>Чето типа того, писал прямо тут, могут быть ошибки.

MC>>В реальной реализации пейджинг, сортинг, фильтры находятсья в инфраструктуре.
G>В какой инфраструктуре. Давай полный пример.
G>На входе есть products:IQueryable<Product>, который возвращает все записи. Показать надо первые 10 видимых, из категории X.
G>Какие будут классы, как распределена логика?
Логики нет. Она тока в модели. Это по этому и денормализщация с тоталом.
Так настраиваеть query оьект. Это старая версия, щас более унифицированная версия...
var query = new ListAllProductsQuery
{
MaxResults = limit ?? 256
StartFrom = start,
SortFieldExpression = sort, // TODO Security hole, we should restrict select strings...
Direction = String.Equals(dir, "asc", StringComparison.OrdinalIgnoreCase)
? OrderDirection.Asc : OrderDirection.Desc
};

В ListAllProductsQuery доступна IQueryable НХибирнейта, весь пейджинг и фильтры там делаються там.
тож нужен пример?
IQueryable.Where().Take() и чето-там.
А тут я живу и пишу...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.