Здравствуйте, Tissot, Вы писали:
T>То есть иди на фик.
Ну я так и думал, что сказать нечего.
T>Какой такой недостаток есть в LINQ2SQL-е, что он не позволяет построить domain model?
T>>и почему с его помощью нельзя построить domain model?
IB>Можно, но не нужно, <...>
Принципиально не читаешь, что тебе пишут? Еще раз — позволяет, но в этом нет необходимости.
Здравствуйте, Sinclair, Вы писали:
T>>Откуда CustomerManager и как он может помешать изменить Customer-а напрямую? S>Как откуда? Это и есть класс, в котором сосредоточены методы управления кастомерами.
Все равно вопросы остаются. Не совсем понятно где располагать методы, манипулирующие несколькими типами сущностей.
Например, если чуть изменить тот пример с резервированием:
пусть в случае отсутствия на складе нужного количества товара, товар резервируется частично и информация о зарезервированном кол-ве сохраняется в заказе. То есть, если мы хотели заказать 50 стульев, а на складе оказалось только 20, то 20 и зарезервируется, а после того, как на склад довезут товар, можно будет до-зарезервировать оставшиеся 30 стульев.
В такой формулировке операция резервирования меняет как остатки на складе, так и строки заказа.
В DDD для такого сценария был бы заведен ReservationService, в котором и был бы расположен весь код и по списанию остатков, и по обновлению заказа.
А куда вы его поместите?
S>Помешать он сам конечно не может, в том смысле, что у админа-злодея всегда есть шанс полезть в базу напрямую.
Ну, от злодея-админа ничего не спасет, так что лучше такой вариант не рассматривать.
S>А вот запретить из прикладного кода вызовы апдейт-стейтментов можно в том числе и при помощи FxCop. S>Это если не хватает культуры программирования. S>Нужно просто отделить случайные ошибки от преднамеренных действий.
В том-то и вопрос, как избежать случайных ошибок.
S>>>А если подумать головой, то окажется, что зип-код нужен только в тот момент, когда выполняется отгрузка товара. Если кастомер хочет заказать и заплатить, то нет никакой причины требовать от него валидность ненужного сейчас зип-кода. T>>Ну это скорее аргумент в пользу изменени логики валидации — она должна запускаться только при определенном статусе заказа. S>Это приведет к тому, что в приложении вообще не будет повторно используемого кода. Потому что в логику валидации зашито слишком много подробностей про окружение. А всего-то надо было применить регекс в нужный момент.
Не совсем верно выразился. В описанном случае отсутствие zip-кода или его невалидность вообще не должно учитываться при валидации кастомера. Это действительно, скорее пред-условие для осуществления отгрузки.
Здравствуйте, Tissot, Вы писали:
T>В DDD для такого сценария был бы заведен ReservationService, в котором и был бы расположен весь код и по списанию остатков, и по обновлению заказа. T>А куда вы его поместите?
В этом подходе точно так же будет ReservationService. Как раз в rich domain model непонятно, где располагать такой метод — в заказе, в складе, или еще где.
А так у нас есть некий сервис, которому для работы нужны заказы (с определенным поведением), и склад.
T>В том-то и вопрос, как избежать случайных ошибок.
Очень трудно сделать случайную ишибку, если есть определенные договоренности.
T>Не совсем верно выразился. В описанном случае отсутствие zip-кода или его невалидность вообще не должно учитываться при валидации кастомера. Это действительно, скорее пред-условие для осуществления отгрузки.
Я просто веду к тому, что в реальной жизни инвариантов, которые можно безопасно захардкодить в класс ентити, практически не встречается. В развитых системах те же предусловия на операции вообще задаются путем конфигурирования workflow, без какой-либо перекомпиляции.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали: T>Это не кастомер, это способ хранения информации о кастомере.
Правильно.
T>Ближе к телу. Что за атрибуты?
Например "ID следующего кастомера, которого нужно обрабатывать, если обработка этого не удалась".
Это в случае представления приоритета кастомеров на основе односвязного списка. Или "Customer Priority". Или "Customer Access Control List".
Кастомер может оказаться разрезанным на несколько entity. А может оказаться наоборот. Контактный телефон может оказаться атрибутом кастомера; может оказаться атрибутом сущности "представитель кастомера", может оказаться отдельной сущностью, которая связана с первыми двумя отношением "многие-ко-многим".
При этом, что характерно, сама предметная область никак не меняется от этих страшных манипуляций. Какая из этих моделей domain model? Та, которая ближе к "предметной области"? Предметная область бесконечно сложна. К примеру,
S>>Этакие "артефакты модели". Задача "максимально приблизиться к предметной области" звучит хорошо, но работает плохо. Мне больше нравится задача "придумать максимально простую модель предметной области, которая покрывает максимальное количество пользовательских сценариев".
T>Такой моделью как раз и является domain model
Боюсь тебя разочаровать, но "максимальная близость к предметной области", которую ты постулировал как основной признак domain model, здесь может получиться только случайно.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
T>>Ближе к телу. Что за атрибуты? S>Например "ID следующего кастомера, которого нужно обрабатывать, если обработка этого не удалась". S>Это в случае представления приоритета кастомеров на основе односвязного списка.
Зачем это ID делать атрибутом Customer-а?
S>Или "Customer Priority".
Вполне себе атрибут предметной области.
S>Или "Customer Access Control List".
Внешняя по отношению к кастомеру сущность. По крайней мере у нас.
S>Кастомер может оказаться разрезанным на несколько entity. А может оказаться наоборот. Контактный телефон может оказаться атрибутом кастомера; может оказаться атрибутом сущности "представитель кастомера", может оказаться отдельной сущностью, которая связана с первыми двумя отношением "многие-ко-многим". S>При этом, что характерно, сама предметная область никак не меняется от этих страшных манипуляций. Какая из этих моделей domain model?
Это вообще вопрос маппинга на хранилище. У нас не проекте как раз недавно такой рефакторинг делался. Объектная модель не поменялась. Почти
S>Та, которая ближе к "предметной области"? Предметная область бесконечно сложна. К примеру,
В программе не интересна "вся" сложность кастомера. Интересно лишь то, что ... хм, интересно. Собственно как раз это и отквочено ниже.
S>>>Этакие "артефакты модели". Задача "максимально приблизиться к предметной области" звучит хорошо, но работает плохо. Мне больше нравится задача "придумать максимально простую модель предметной области, которая покрывает максимальное количество пользовательских сценариев".
T>>Такой моделью как раз и является domain model S>Боюсь тебя разочаровать, но "максимальная близость к предметной области", которую ты постулировал как основной признак domain model, здесь может получиться только случайно.
Здравствуйте, Sinclair, Вы писали:
T>>В DDD для такого сценария был бы заведен ReservationService, в котором и был бы расположен весь код и по списанию остатков, и по обновлению заказа. T>>А куда вы его поместите? S>В этом подходе точно так же будет ReservationService.
То есть задача манипулирования заказами начинает расползаться на большее кол-во сервисов, не только на ЗаказМнеджер?
S>Как раз в rich domain model непонятно, где располагать такой метод — в заказе, в складе, или еще где.
rich model не отрицает наличие сервисов.
S>А так у нас есть некий сервис, которому для работы нужны заказы (с определенным поведением), и склад.
с поведением?
T>>В том-то и вопрос, как избежать случайных ошибок. S>Очень трудно сделать случайную ишибку, если есть определенные договоренности.
ой, не факт. на договоренности надейся, а сам не плошай.
T>>Не совсем верно выразился. В описанном случае отсутствие zip-кода или его невалидность вообще не должно учитываться при валидации кастомера. Это действительно, скорее пред-условие для осуществления отгрузки. S>Я просто веду к тому, что в реальной жизни инвариантов, которые можно безопасно захардкодить в класс ентити, практически не встречается.
Да есть инварианты, просто с zip-кодом вариант не не совсем удачный. С тем же заказчиком изначально заключается договор и в нем обговорены многие данные о заказчике. Так что они вполне могут проверяться в самой сущности.
T>>>Во-вторых, добавляя новое поведение, надо его просто добавлять, а не менять старое
IB>>А это тут причем? При изменении требований новое поведение должно добавляться без изменения старого, это для тебя новость?
T>
T>Код должен быть поменян, а данные — нет.
T>(с) IB
T>
Поставил минус и в кусты. Ты (IB) уж расскажи, как могут сосуществовать "Код должен быть поменян" с "новое поведение должно добавляться без изменения старого"?
Интересно же.
Здравствуйте, Tissot, Вы писали:
T>Зачем это ID делать атрибутом Customer-а?
А чьим?
S>>Или "Customer Access Control List". T>Внешняя по отношению к кастомеру сущность. По крайней мере у нас.
И какому объекту предметной области она соответствует?
T>Это вообще вопрос маппинга на хранилище. У нас не проекте как раз недавно такой рефакторинг делался. Объектная модель не поменялась. Почти
Это вопрос выбора сущностей для моделирования.
T>В программе не интересна "вся" сложность кастомера. Интересно лишь то, что ... хм, интересно. Собственно как раз это и отквочено ниже.
Вот и оказывается, что в модель попадает не всё, что было в "предметной области", и попадает то, чего там отродясь не было.
T>Ну это как вести метрику "близость".
Как ни вводи — всегда останется возможность привести контрпримеры.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
T>>Зачем это ID делать атрибутом Customer-а? S>А чьим?
"ID следующего кастомера, которого нужно обрабатывать, если обработка этого не удалась"
Зачем это ID в кастомере? Просто передавай в метод обработки список кастомеров.
S>>>Или "Customer Access Control List". T>>Внешняя по отношению к кастомеру сущность. По крайней мере у нас. S>И какому объекту предметной области она соответствует?
Мне кажется ты слишком узко трактуешь понятие "предметная область". Это не обязательно что-то, что существует в предметном мире. Это вполне может быть и концепцией. Например, если говорят о ресурсах, доступных кастомеру, то понятие "доступ" к ресурсу существует в предметной области. А ACL — это не более чем набор этих "доступов".
T>>Это вообще вопрос маппинга на хранилище. У нас не проекте как раз недавно такой рефакторинг делался. Объектная модель не поменялась. Почти S>Это вопрос выбора сущностей для моделирования.
Опять 25. Если для тебе данные — это сущность, то да, если для тебя (меня) сущность — это сущность domain model, то нет.
T>>В программе не интересна "вся" сложность кастомера. Интересно лишь то, что ... хм, интересно. Собственно как раз это и отквочено ниже. S>Вот и оказывается, что в модель попадает не всё, что было в "предметной области", и попадает то, чего там отродясь не было.
Нет, не попадает. Если в предметной области этого не было, то зачем откуда оно в сущностях? Они же (сущности) — результат анализа предметной области.
T>>Ну это как вести метрику "близость". S>Как ни вводи — всегда останется возможность привести контрпримеры.
Возможно. Я вроде и не говорил, что доменная модель — это конец истории. Все когда-нить уйдет. Но вот придет ли на смену ей тот подход о котором вы говорите —
Время покажет.
Здравствуйте, Tissot, Вы писали:
T>Поставил минус и в кусты.
Ты же сам отказался со мной дискутировать, так чего бисер метать?
T>Ты (IB) уж расскажи, как могут сосуществовать "Код должен быть поменян" с "новое поведение должно добавляться без изменения старого"?
Про OCP принцип слышал? Поинт в том, что при добавлении новго функционала, та часть исходников, которая реализует старый и все еще актуальный функционал даже трогаться не должна, а не только не меняться. Меняется и трогается только то, что нужно изменить. Необходимость менять данные возникает гораздо реже, чем логику, которая навернута поверх этих данных. Таким образом, выделяя данные в отдельную сущность мы защищаем их от лишних изменений, трогая только тот код, который должен поменяться.
Здравствуйте, gandjustas, Вы писали:
G>
G>Ну вообще ваша "domain model по фаулеру" наиболее близка к предметной области по вашей метрике. Это же оченивдно.
Здравствуйте, Tissot, Вы писали:
T>То есть задача манипулирования заказами начинает расползаться на большее кол-во сервисов, не только на ЗаказМнеджер?
Всё зависит от конкретной задачи. Не забываем про Single Responsibbility Principle.
То есть наш xxxService должен делать всё, что относится к соответствующей ответственности. Речь не идет о тупом механическом выносе всех методов из класса Xxx в класс XxxManager.
T>rich model не отрицает наличие сервисов.
Ну, ты только что боролся за то, чтобы методы включать в entity. Опять напомню, что ReservationService не соответствует вообще ничему в предметной области; таким образом, мы уходим от твоей "максимально близкой к предметной области модели".
T>с поведением?
Ага. В простом случае достаточно прямой манипуляции данными; в более сложном ReservationService будет делегировать построение запросов для модификации позиций заказа и остатков на складах соответствующим сервисам.
T>ой, не факт. на договоренности надейся, а сам не плошай.
Опять же, для плохих танцоров есть FxCop.
T>Да есть инварианты, просто с zip-кодом вариант не не совсем удачный. С тем же заказчиком изначально заключается договор и в нем обговорены многие данные о заказчике. Так что они вполне могут проверяться в самой сущности. Какие например? Договор заключается с каждым отдельным заказчиком. Надеюсь, ты не предполагаешь каждый раз писать новый класс сущности для него?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали: T>Поставил минус и в кусты. Ты (IB) уж расскажи, как могут сосуществовать "Код должен быть поменян" с "новое поведение должно добавляться без изменения старого"? T>Интересно же.
Это просто два разных сценария. В одном на существующих данных применяются новые методы, а старые вообще выбрасываются из рассмотрения. Это — замена функциональности.
Она типична, например, когда мы берем накопленные за годы данные и передаём их третьим лицам для data mining.
Дата майнингу совершенно неинтересна валидация, workflow, и прочие приколы, которыми мы пользовались в исходном OLTP приложении. Более того, для него крайне вредно иметь всякие такие штуки типа "адрес кастомера вычисляется полиморфно в зависимости от его типа и параметров", потому что вместе с данными придется тащить вот это "полиморфное поведение". Которое, в частности, может вообще не заработать на той платформе, где датамайнинг собрались выполнять.
В другом случае речь идет о расширении функциональности существующей системы.
И в нём важна возможность произвести это расширение с минимальными потерями. Зашивание логики в data objects чревато неконтролируемым расползанием изменений.
Вот мы по соседству обсуждали валидацию зипкодов. Буквально за два дня у нас код валидации изменился не то четыре, не то пять раз — в зависимости от вторичных подробностей. Это признак того, что с самого начала было сделано что-то неправильно. Если поддержка еще одной страны требует внесения изменений в классы кастомера, заказа, и еще хрен знает чего, то как-то становится жалко потраченных на разработку усилий.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, IB, Вы писали:
T>>Поставил минус и в кусты. IB>Ты же сам отказался со мной дискутировать, так чего бисер метать?
Опять хамишь. Ты что, без этого совсем не можешь?
T>>Ты (IB) уж расскажи, как могут сосуществовать "Код должен быть поменян" с "новое поведение должно добавляться без изменения старого"? IB>Про OCP принцип слышал?
Слышал конечно (зевок). Я же тебе же отвечал, что я не со школьной скамьи сюда пришел.
IB>Поинт в том, что при добавлении новго функционала, та часть исходников, которая реализует старый и все еще актуальный функционал даже трогаться не должна, а не только не меняться. Меняется и трогается только то, что нужно изменить.
Слушай, у меня от твоих слов мозг начинает плавиться. Зачем ты тогда писал
добавляя новое поведение, надо его просто добавлять, а не менять старое
, если какая-то часть исходников все-таки трогается.
IB>Необходимость менять данные возникает гораздо реже, чем логику, которая навернута поверх этих данных. Таким образом, выделяя данные в отдельную сущность мы защищаем их от лишних изменений, трогая только тот код, который должен поменяться.
Тут имхо, идет смешение понятий.
То, о чем ты говоришь — это защита схемы данных (контракт), а не самих данных. Данные как раз мы не защищаем, а наоборот выставляем напоказ.
Здравствуйте, Tissot, Вы писали: T>Зачем это ID в кастомере? Просто передавай в метод обработки список кастомеров.
Откуда возьмется "список"?
T>Мне кажется ты слишком узко трактуешь понятие "предметная область". Это не обязательно что-то, что существует в предметном мире. Это вполне может быть и концепцией. Например, если говорят о ресурсах, доступных кастомеру, то понятие "доступ" к ресурсу существует в предметной области.
Об этом я и говорю. Вот эта "предметная область" — нифига не "предметная область". Это "модель предметной области", которая сделана по некоторым соображениям.
Имхо, Фаулер говорил именно о предметной области, а не об артефактах, вызванных моделированием.
T>Опять 25. Если для тебе данные — это сущность, то да, если для тебя (меня) сущность — это сущность domain model, то нет.
А ты попробуй всё-таки понять, что такое "domain model". Что именно там domain?
T>Нет, не попадает. Если в предметной области этого не было, то зачем откуда оно в сущностях? Они же (сущности) — результат анализа предметной области.
Как артефакт анализа. Простейшая штука — ID. В предметной области никаких суррогатных ключей нету. В данных почему-то появляются.
В предметной области нет никаких понятий типа "доступа", они появляются только после моделирования. Этакие "сущности второго порядка".
В развитом приложении, к примеру, правила валидации сами становятся "сущностями", хотя никакому объекту в предметной области они не соответствуют.
В итоге, применение ООП для моделирования "реального мира" в большинстве случаев совершенно бесполезно.
Вообще, напомню, что ООП появилось как попытка разработать удачную абстракцию для оконно-ориентированного GUI. Именно поэтому в ранних книгах по ООП так много примеров на тему pWindow->draw() или pFigure->draw().
Прошли годы, и оказалось, что даже для этих задач ООП в таком виде малопригодно.
Что окна удобнее собирать из готовых примитивов как агрегаты, а не наследовать друг от друга.
Что и геометрические фигуры не надо наследовать друг от друга, а достаточно иметь ровно один класс VectorPath, который рисуется ровно одним образом, а бытность его квадратом или треугольником — всего лишь предикат, а не имманентное свойство.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
T>>То есть задача манипулирования заказами начинает расползаться на большее кол-во сервисов, не только на ЗаказМнеджер? S>Всё зависит от конкретной задачи. Не забываем про Single Responsibbility Principle.
Ответственности тоже можно порезать по-разному. Можно — по модифицирующим сущностям (CustomerManager, OrderManager), можно и по бизнес — сценариям (ReservationService).
S>То есть наш xxxService должен делать всё, что относится к соответствующей ответственности. Речь не идет о тупом механическом выносе всех методов из класса Xxx в класс XxxManager.
Не, я пытаюсь понять как ты предлагаешь это сделать.
T>>rich model не отрицает наличие сервисов. S>Ну, ты только что боролся за то, чтобы методы включать в entity.
Нет, я боролся за то, чтобы те сделать контракт сущности таковым, чтобы нельзя было нарушить инварианты. Если метод работы с сущностью не нарушает инвариантов, то его можно поместить и вовне класса, например в виде extension-метода, если мы используем C#. Если область действия метода шире чем данный экземпляр класса, то ему не место в классе, нужно завести отельный сервис, в котором и реализовывать необходимый функционал.
S>Опять напомню, что ReservationService не соответствует вообще ничему в предметной области; таким образом, мы уходим от твоей "максимально близкой к предметной области модели".
Дык, ReservationService и не является частью domain model. Это бизнес-операция.
T>>с поведением? S>Ага. В простом случае достаточно прямой манипуляции данными; в более сложном ReservationService будет делегировать построение запросов для модификации позиций заказа и остатков на складах соответствующим сервисам.
T>>ой, не факт. на договоренности надейся, а сам не плошай. S>Опять же, для плохих танцоров есть FxCop.
Ну так как его использовать, если функциональность изменения остатков на складе уже переползла из соответствующего менеджера в ReservationService?
T>>Да есть инварианты, просто с zip-кодом вариант не не совсем удачный. С тем же заказчиком изначально заключается договор и в нем обговорены многие данные о заказчике. Так что они вполне могут проверяться в самой сущности. S> Какие например? Договор заключается с каждым отдельным заказчиком. Надеюсь, ты не предполагаешь каждый раз писать новый класс сущности для него?
Из того, что "Договор заключается с каждым отдельным заказчиком" не следует, что договоры с заказчиками не имеют ничего общего. Первое что приходит в голову — это название заказчика и SLA. Кроме того, каждый заказчик регистрируется в бухгалтерской системе, в которой он получает свой номер. Этот номер — второй претендент на проверку.
Здравствуйте, Sinclair, Вы писали:
T>>Поставил минус и в кусты. Ты (IB) уж расскажи, как могут сосуществовать "Код должен быть поменян" с "новое поведение должно добавляться без изменения старого"? T>>Интересно же. S>Это просто два разных сценария. В одном на существующих данных применяются новые методы, а старые вообще выбрасываются из рассмотрения. Это — замена функциональности.
S>В другом случае речь идет о расширении функциональности существующей системы.
Ладно, будем считать, что IB именно это и имел в виду, хотя из его слов это было совсем не ясно.
S>И в нём важна возможность произвести это расширение с минимальными потерями. Зашивание логики в data objects чревато неконтролируемым расползанием изменений.
Нет dataobjects в domain model, потому и такого явления как "зашивание логики в data objects", а следовательно нет и "расползанием изменений". domain model рулит!
S>Вот мы по соседству обсуждали валидацию зипкодов. Буквально за два дня у нас код валидации изменился не то четыре, не то пять раз — в зависимости от вторичных подробностей. Это признак того, что с самого начала было сделано что-то неправильно.
Правильно, не был проведен анализ.
S>Если поддержка еще одной страны требует внесения изменений в классы кастомера, заказа, и еще хрен знает чего, то как-то становится жалко потраченных на разработку усилий.
И какой вывод? Отказаться от валидации совсем? Дык это не решение, т.к. если на этапе анализа было решено, что валидация нужна, то и моем и в твоем случае ее делать придется.
Здравствуйте, Tissot, Вы писали: T>Ответственности тоже можно порезать по-разному. Можно — по модифицирующим сущностям (CustomerManager, OrderManager), можно и по бизнес — сценариям (ReservationService).
Первый способ — неправильный; второй — правильный.
T>Нет, я боролся за то, чтобы те сделать контракт сущности таковым, чтобы нельзя было нарушить инварианты. Если метод работы с сущностью не нарушает инвариантов, то его можно поместить и вовне класса, например в виде extension-метода, если мы используем C#. Если область действия метода шире чем данный экземпляр класса, то ему не место в классе, нужно завести отельный сервис, в котором и реализовывать необходимый функционал.
Всё правильно. Повторюсь: при анализе предметной области тех инвариантов, о которых ты говоришь, возникает пренебрежимо мало.
Даже самые очевидные штуки, типа "остатки на складе не могут быть меньше нуля" в реальной жизни оказываются неверными (например, из-за того, что оприходование товара выполняется с опозданием).
T>Дык, ReservationService и не является частью domain model. Это бизнес-операция.
Ну вот очень странно получается — важное поведение не попадает в модель. Это получается какая-то плохая модель, некачественная. Непонятно, почему одно поведение входит в модель, а другое — нет.
В анемичной модели всё просто: "сущности" моделируют только статическую часть предметной области, у них нет никакого поведения. А всё поведение сосредоточено во всяких ...Manager, ...Service, ...Strategy, ...Policy.
T>Ну так как его использовать, если функциональность изменения остатков на складе уже переползла из соответствующего менеджера в ReservationService?
Очень просто — в данном сценарии ReservationService и стал "соответствующим менеджером"
T>Из того, что "Договор заключается с каждым отдельным заказчиком" не следует, что договоры с заказчиками не имеют ничего общего. Первое что приходит в голову — это название заказчика и SLA. Кроме того, каждый заказчик регистрируется в бухгалтерской системе, в которой он получает свой номер. Этот номер — второй претендент на проверку.
На проверку чего?
Намекну: бухгалтерская система может быть завтра заменена, без изменения бизнеса.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tissot, Вы писали:
T>Нет dataobjects в domain model, потому и такого явления как "зашивание логики в data objects", а следовательно нет и "расползанием изменений". domain model рулит!
Ну щас прямо. То, что было бы в анемичной модели банальной структурой "кастомер", то бишь дата обжектом, в твоей "domain model" обрастает какими-то методами, валидацией там, и так далее. В итоге изменения таки расползаются.
T>Правильно, не был проведен анализ.
Почему это? Представь себе реальную жизнь — бизнес эволюционирует, требования, которых не было в Release 1, появляются в Release 2.
Как бы ты ни пыхтел в Release 1, всех требований ты предсказать не можешь
T>И какой вывод? Отказаться от валидации совсем? Дык это не решение, т.к. если на этапе анализа было решено, что валидация нужна, то и моем и в твоем случае ее делать придется.
Только в моём случае не придется менять класс Customer при изменении требований к валидации.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.