Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, AUDev, Вы писали:
AUD>>Я обычно руководствуюсь следующей идеей — часто добавляемые/изменяемые фичи должно быть легко добавлять/изменять. Но достигаю я это не за счет жесткого отделения от модели а за счет правильного следования SOLID принципам. Например следование OCP (Open/Closed Principle) (и набор известных конвенций) могут свести добавление нового куска бизнес логики к добавлению одного единственного класса (который легко тестируем как в изоляции так и интеграционно). G>Пример приведешь?
Пример OCP?
Ок, из недавнего.
Background: Разрабатывается приложение одной из частей которого является некая библиотека (список) документов определенных типов из различных источников (интранет, Sharepoint, локальный диск и прочее). Тип документа определяется расширением его файла.
Story: Как пользователь я должен иметь возможность просматривать документы Тип 1, Тип 2 и Тип 3 для последующего принятия решений.
Доп. информация: известно что пользователи могут в будущем захотеть просматривать документы других типов.
Разрабатывается и тестируется относительно стабильная часть модели которая помимо прочего инициирует показ документа, помимо всего остального в модели разрабатывается и тестируется специальный viewer который может отображать в соответствии со спецификой требований к приложению что угодно, только это что угодно должно быть в специальном формате. Я называю всю эту часть модели доменный фреймворк. То есть часть эта и к домену имеет прямое отношение а не к инфраструктуре, но и достаточно стабильна чтобы на нее навешивать более динамические части домена. Ayende называет это концептом.
Разрабатываются и тестируется заявленные изначально типы документов (фичи).
При появлении нового типа документа XXX который нужно отображать все что нужно изменить в системе это добавить и протестировать примерно следующее:
[Handles(".xxx")]
public class XxxDocument
{
...
}
Как видно имеет место простая конвенция базирующаяся на аттрибуте. Как вариант можно было бы обойтись и именем класса (но это несколько ограничит использование в случае когда один тип файла определяется несколькими расширениями).
AUD>>Если же речь идет о совсем динамической и специфической бизнес логике с требованием очень частого изменения, то ее уже можно рассмотреть как внешний по отношению к модели артефакт который добавляется изменяется самими юзерами (с помощью UI или если надо DSL в других формах). G>А если БЛ требует частого изменение, но не юзерами, а программистами?
Как я уже говорил, такую логику я структурирую так чтобы ее было просто изменить/добавить. Это "просто" на уровне коде выражается обычно следующим: SOLID, конвенции, AOP. При правильном использовании DDD к этому "просто" добавляется то, что само изменений проще найти в коде сложного домена используя общую терминологию и язык. Например не так давно мне нужно было добавить небольшую вещь в два приложения обслуживающие один и тот же домен — конфигурационную систему составных частей, встроенным приложений и телеметрических приборов подстанций электрической компании. Одно из приложений было совсем не DDD, другое тоже не совсем DDD, но близко. Пообщавшись с доменными экспертами я понял что добавить нужно новый тип точки-связки между одним из многих параметров встроенного приложения автоматического отключения уличного освещения и определенной подсекцией аналогового раздела конфигурационной минибазы телеметрического юнита (причем только когда приложение списывается с подстанции определенного типа). В DDD приложении я сделал это один за час-два (с тестами) потому что модель была структурирована близко к описанию полученному у экспертов. В анемичном приложении я только два дня искал место которое нужно менять, потом еще у двух программистов этого приложения уточнял что именно нужно менять и добавлять, и у еще одного просил верификацонное ревью и даже после этого я толком не понял как же все-таки там все структурировано — вроде база частично воспроизводит домен, вроде голые сущности именованы правильно, но модель отражает не домен, а множество пониманий и интерпретаций лида и каждого из команды программистов (из которых на проекте уже не было никого).
Re[7]: [DDD] Вносить ли бизнес-логику в модель предметной об
AUD>>>>>>Альтернатива отдельного существования модели данных и поведения как правило требует несколько иных подходов чем те что предполагает DDD. G>>>>>Конкретнее, как это выражается в коде? AUD>>>>В коде это как правило выражается в разнице между количеством вводимых доменных сервисов (сервисов манипулирующих entities). G>>>Всего-то? От чего столько шума тогда и куча приседаний DDD? AUD>>Все как обычно — простая идея, много нюансов (не только в коде выражающихся).
G>Много нюансов — значит идея не простая, а только пытается казаться простой.
Простота это понятие относительное. Например, Linq на твой взгляд это простая идея?
Re[8]: [DDD] Вносить ли бизнес-логику в модель предметной об
S>>Вот простая задача — есть склад, есть поставки, есть заказы, скидки и есть возвраты. при возврате товара надо вычислить 1 сумму возвращаемых денег с учетом всех возможных скидок и округлений 2 найти именно ту поставку с которой единица товара прибыла на склад
S>>Мой: S>>
S>>А что, мы не записываем никаких данных о поставках? Если записываем — в чём проблема найти соответствующую поставку по накладной?
G>+100500 G>В бухгалтерии как всегда рулит двойная запись, которая сохраняет вообще говоря все.
Кстати был похожий случай с возвратом товара.
Перед этим имели место множественные поставки товара по разным ценам.
Бухгалтеру нужно было оценить стоимость возврата, а он никак не мог взять на себя ответственность,так же как и сбыт.
При этом все ожидали какого-то чуда от программы, а просто выбрать поставку, по которой произошел возврат никто не решался.
Случай,если бы софт решал этот вопрос автоматом устраивал бы всех.Потому что на грозное: "Кто это сделал!!!" от руководства
следует ответ: "Так программа работает". И драть вроде бы некого,кроме программиста .
Re[6]: [DDD] Вносить ли бизнес-логику в модель предметной об
Здравствуйте, AUDev, Вы писали:
AUD>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, AUDev, Вы писали:
AUD>>>Я обычно руководствуюсь следующей идеей — часто добавляемые/изменяемые фичи должно быть легко добавлять/изменять. Но достигаю я это не за счет жесткого отделения от модели а за счет правильного следования SOLID принципам. Например следование OCP (Open/Closed Principle) (и набор известных конвенций) могут свести добавление нового куска бизнес логики к добавлению одного единственного класса (который легко тестируем как в изоляции так и интеграционно). G>>Пример приведешь?
AUD>Пример OCP? AUD>Ок, из недавнего.
AUD>Background: Разрабатывается приложение одной из частей которого является некая библиотека (список) документов определенных типов из различных источников (интранет, Sharepoint, локальный диск и прочее). Тип документа определяется расширением его файла. AUD>Story: Как пользователь я должен иметь возможность просматривать документы Тип 1, Тип 2 и Тип 3 для последующего принятия решений. AUD>Доп. информация: известно что пользователи могут в будущем захотеть просматривать документы других типов.
AUD>Разрабатывается и тестируется относительно стабильная часть модели которая помимо прочего инициирует показ документа, помимо всего остального в модели разрабатывается и тестируется специальный viewer который может отображать в соответствии со спецификой требований к приложению что угодно, только это что угодно должно быть в специальном формате. Я называю всю эту часть модели доменный фреймворк. То есть часть эта и к домену имеет прямое отношение а не к инфраструктуре, но и достаточно стабильна чтобы на нее навешивать более динамические части домена. Ayende называет это концептом. AUD>Разрабатываются и тестируется заявленные изначально типы документов (фичи).
AUD>При появлении нового типа документа XXX который нужно отображать все что нужно изменить в системе это добавить и протестировать примерно следующее:
AUD>
AUD>[Handles(".xxx")]
AUD>public class XxxDocument
AUD>{
AUD> ...
AUD>}
AUD>
AUD>Как видно имеет место простая конвенция базирующаяся на аттрибуте. Как вариант можно было бы обойтись и именем класса (но это несколько ограничит использование в случае когда один тип файла определяется несколькими расширениями).
Получилась чисто anemic модель: данные полностью отделены от алгоритмов обработки.
AUD>>>Если же речь идет о совсем динамической и специфической бизнес логике с требованием очень частого изменения, то ее уже можно рассмотреть как внешний по отношению к модели артефакт который добавляется изменяется самими юзерами (с помощью UI или если надо DSL в других формах). G>>А если БЛ требует частого изменение, но не юзерами, а программистами? AUD>Как я уже говорил, такую логику я структурирую так чтобы ее было просто изменить/добавить. Это "просто" на уровне коде выражается обычно следующим: SOLID, конвенции, AOP. При правильном использовании DDD к этому "просто" добавляется то, что само изменений проще найти в коде сложного домена используя общую терминологию и язык. Например не так давно мне нужно было добавить небольшую вещь в два приложения обслуживающие один и тот же домен — конфигурационную систему составных частей, встроенным приложений и телеметрических приборов подстанций электрической компании. Одно из приложений было совсем не DDD, другое тоже не совсем DDD, но близко. Пообщавшись с доменными экспертами я понял что добавить нужно новый тип точки-связки между одним из многих параметров встроенного приложения автоматического отключения уличного освещения и определенной подсекцией аналогового раздела конфигурационной минибазы телеметрического юнита (причем только когда приложение списывается с подстанции определенного типа). В DDD приложении я сделал это один за час-два (с тестами) потому что модель была структурирована близко к описанию полученному у экспертов. В анемичном приложении я только два дня искал место которое нужно менять, потом еще у двух программистов этого приложения уточнял что именно нужно менять и добавлять, и у еще одного просил верификацонное ревью и даже после этого я толком не понял как же все-таки там все структурировано — вроде база частично воспроизводит домен, вроде голые сущности именованы правильно, но модель отражает не домен, а множество пониманий и интерпретаций лида и каждого из команды программистов (из которых на проекте уже не было никого).
А в чем отличались DDD и неDDD приложения и в чем была сложность найти что нужно?
Re[8]: [DDD] Вносить ли бизнес-логику в модель предметной об
Здравствуйте, AUDev, Вы писали:
AUD>>>>>>>Альтернатива отдельного существования модели данных и поведения как правило требует несколько иных подходов чем те что предполагает DDD. G>>>>>>Конкретнее, как это выражается в коде? AUD>>>>>В коде это как правило выражается в разнице между количеством вводимых доменных сервисов (сервисов манипулирующих entities). G>>>>Всего-то? От чего столько шума тогда и куча приседаний DDD? AUD>>>Все как обычно — простая идея, много нюансов (не только в коде выражающихся).
G>>Много нюансов — значит идея не простая, а только пытается казаться простой. AUD>Простота это понятие относительное. Например, Linq на твой взгляд это простая идея?
По сравнению с чем?
Re[9]: [DDD] Вносить ли бизнес-логику в модель предметной об
S>>>Вот простая задача — есть склад, есть поставки, есть заказы, скидки и есть возвраты. при возврате товара надо вычислить 1 сумму возвращаемых денег с учетом всех возможных скидок и округлений 2 найти именно ту поставку с которой единица товара прибыла на склад
S>>>Мой: S>>>
S>>>А что, мы не записываем никаких данных о поставках? Если записываем — в чём проблема найти соответствующую поставку по накладной?
G>>+100500 G>>В бухгалтерии как всегда рулит двойная запись, которая сохраняет вообще говоря все. OV_>Кстати был похожий случай с возвратом товара. OV_>Перед этим имели место множественные поставки товара по разным ценам. OV_>Бухгалтеру нужно было оценить стоимость возврата, а он никак не мог взять на себя ответственность,так же как и сбыт. OV_>При этом все ожидали какого-то чуда от программы, а просто выбрать поставку, по которой произошел возврат никто не решался. OV_>Случай,если бы софт решал этот вопрос автоматом устраивал бы всех.Потому что на грозное: "Кто это сделал!!!" от руководства OV_> следует ответ: "Так программа работает". И драть вроде бы некого,кроме программиста .
По товару не смогли определить из какой он поставки? Номеров нету? Склад плохо работает\не автоматизирован?
Причем тут программисты?
Re[7]: [DDD] Вносить ли бизнес-логику в модель предметной об
AUD>>>>Я обычно руководствуюсь следующей идеей — часто добавляемые/изменяемые фичи должно быть легко добавлять/изменять. Но достигаю я это не за счет жесткого отделения от модели а за счет правильного следования SOLID принципам. Например следование OCP (Open/Closed Principle) (и набор известных конвенций) могут свести добавление нового куска бизнес логики к добавлению одного единственного класса (который легко тестируем как в изоляции так и интеграционно). G>>>Пример приведешь?
AUD>>Пример OCP? AUD>>Ок, из недавнего.
AUD>>Background: Разрабатывается приложение одной из частей которого является некая библиотека (список) документов определенных типов из различных источников (интранет, Sharepoint, локальный диск и прочее). Тип документа определяется расширением его файла. AUD>>Story: Как пользователь я должен иметь возможность просматривать документы Тип 1, Тип 2 и Тип 3 для последующего принятия решений. AUD>>Доп. информация: известно что пользователи могут в будущем захотеть просматривать документы других типов.
AUD>>Разрабатывается и тестируется относительно стабильная часть модели которая помимо прочего инициирует показ документа, помимо всего остального в модели разрабатывается и тестируется специальный viewer который может отображать в соответствии со спецификой требований к приложению что угодно, только это что угодно должно быть в специальном формате. Я называю всю эту часть модели доменный фреймворк. То есть часть эта и к домену имеет прямое отношение а не к инфраструктуре, но и достаточно стабильна чтобы на нее навешивать более динамические части домена. Ayende называет это концептом. AUD>>Разрабатываются и тестируется заявленные изначально типы документов (фичи).
AUD>>При появлении нового типа документа XXX который нужно отображать все что нужно изменить в системе это добавить и протестировать примерно следующее:
AUD>>
AUD>>[Handles(".xxx")]
AUD>>public class XxxDocument
AUD>>{
AUD>> ...
AUD>>}
AUD>>
AUD>>Как видно имеет место простая конвенция базирующаяся на аттрибуте. Как вариант можно было бы обойтись и именем класса (но это несколько ограничит использование в случае когда один тип файла определяется несколькими расширениями).
G>Получилась чисто anemic модель: данные полностью отделены от алгоритмов обработки.
А это кто как видит себе реализацию того что я описал, дело привычки видимо Я намеренно не давал деталей реализации.
В моей реализации данного примера, модель не anemic. Единственная ответственность типа XxxDocument это одному этому типу известным образом переводить себя в универсальный формат. Эту же модель с тем же успехом можно сделать анемичной. Пример приводился в качестве демонстрации использования OCP, а не DDD vs anemic, ни плюсов не минусов ни DDD ни anemic подхода пример не раскрывает и не ставилось такой цели изначально.
AUD>>>>Если же речь идет о совсем динамической и специфической бизнес логике с требованием очень частого изменения, то ее уже можно рассмотреть как внешний по отношению к модели артефакт который добавляется изменяется самими юзерами (с помощью UI или если надо DSL в других формах). G>>>А если БЛ требует частого изменение, но не юзерами, а программистами? AUD>>Как я уже говорил, такую логику я структурирую так чтобы ее было просто изменить/добавить. Это "просто" на уровне коде выражается обычно следующим: SOLID, конвенции, AOP. При правильном использовании DDD к этому "просто" добавляется то, что само изменений проще найти в коде сложного домена используя общую терминологию и язык. Например не так давно мне нужно было добавить небольшую вещь в два приложения обслуживающие один и тот же домен — конфигурационную систему составных частей, встроенным приложений и телеметрических приборов подстанций электрической компании. Одно из приложений было совсем не DDD, другое тоже не совсем DDD, но близко. Пообщавшись с доменными экспертами я понял что добавить нужно новый тип точки-связки между одним из многих параметров встроенного приложения автоматического отключения уличного освещения и определенной подсекцией аналогового раздела конфигурационной минибазы телеметрического юнита (причем только когда приложение списывается с подстанции определенного типа). В DDD приложении я сделал это один за час-два (с тестами) потому что модель была структурирована близко к описанию полученному у экспертов. В анемичном приложении я только два дня искал место которое нужно менять, потом еще у двух программистов этого приложения уточнял что именно нужно менять и добавлять, и у еще одного просил верификацонное ревью и даже после этого я толком не понял как же все-таки там все структурировано — вроде база частично воспроизводит домен, вроде голые сущности именованы правильно, но модель отражает не домен, а множество пониманий и интерпретаций лида и каждого из команды программистов (из которых на проекте уже не было никого).
G>А в чем отличались DDD и неDDD приложения и в чем была сложность найти что нужно?
Отличия в структуре модели, размещении логики, разбиении на классы; основная сложность поиска была в том что нужно было переводить задачу с языка пользователей на язык(и) программистов писавших части системы.
Re[8]: [DDD] Вносить ли бизнес-логику в модель предметной об
Здравствуйте, AUDev, Вы писали:
G>>Получилась чисто anemic модель: данные полностью отделены от алгоритмов обработки. AUD>А это кто как видит себе реализацию того что я описал, дело привычки видимо Я намеренно не давал деталей реализации. AUD>В моей реализации данного примера, модель не anemic. Единственная ответственность типа XxxDocument это одному этому типу известным образом переводить себя в универсальный формат. Эту же модель с тем же успехом можно сделать анемичной. Пример приводился в качестве демонстрации использования OCP, а не DDD vs anemic, ни плюсов не минусов ни DDD ни anemic подхода пример не раскрывает и не ставилось такой цели изначально.
Это я к тому что правильное использование SOLID ведет к anemic модели, а не к rich.
При этом DDD таки пропагандирует rich, а следовательно неверный подход к дизайну кода.
Re[9]: [DDD] Вносить ли бизнес-логику в модель предметной об
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, AUDev, Вы писали:
G>>>Получилась чисто anemic модель: данные полностью отделены от алгоритмов обработки. AUD>>А это кто как видит себе реализацию того что я описал, дело привычки видимо Я намеренно не давал деталей реализации. AUD>>В моей реализации данного примера, модель не anemic. Единственная ответственность типа XxxDocument это одному этому типу известным образом переводить себя в универсальный формат. Эту же модель с тем же успехом можно сделать анемичной. Пример приводился в качестве демонстрации использования OCP, а не DDD vs anemic, ни плюсов не минусов ни DDD ни anemic подхода пример не раскрывает и не ставилось такой цели изначально. G>Это я к тому что правильное использование SOLID ведет к anemic модели, а не к rich. G>При этом DDD таки пропагандирует rich, а следовательно неверный подход к дизайну кода.
Из того что пример демонстрирующий SOLID можно написать как в DDD так и в anemic не следует что использование SOLID ведет к anemic модели.
Re[10]: [DDD] Вносить ли бизнес-логику в модель предметной о
Здравствуйте, AUDev, Вы писали:
AUD>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, AUDev, Вы писали:
G>>>>Получилась чисто anemic модель: данные полностью отделены от алгоритмов обработки. AUD>>>А это кто как видит себе реализацию того что я описал, дело привычки видимо Я намеренно не давал деталей реализации. AUD>>>В моей реализации данного примера, модель не anemic. Единственная ответственность типа XxxDocument это одному этому типу известным образом переводить себя в универсальный формат. Эту же модель с тем же успехом можно сделать анемичной. Пример приводился в качестве демонстрации использования OCP, а не DDD vs anemic, ни плюсов не минусов ни DDD ни anemic подхода пример не раскрывает и не ставилось такой цели изначально. G>>Это я к тому что правильное использование SOLID ведет к anemic модели, а не к rich. G>>При этом DDD таки пропагандирует rich, а следовательно неверный подход к дизайну кода. AUD>Из того что пример демонстрирующий SOLID можно написать как в DDD так и в anemic не следует что использование SOLID ведет к anemic модели.
Да ну? Что-то не верится.
Возмем ту же задачу, но более абстрактно. Есть некоторые сущности, в зависимости от атрибута(ов) надо к ним применять разные методы обработки.
Если сделать базовый класс, а от него наследоваться, то мы нарушаем OCP, так как для добавление нового функционала (метода в базовом классе) придется менять всех наследников, а если добавлять методы в наследников, а не в базовый класс, то нарушается LSP. Хороший способ — отвязать данные от логики. Логику можно собирать в классы с двумя методами: первый предикат, определяющий можно ли метод применять к сущности, второй — сама обработка. Кроме того есть полезный бонус: предикаты сами могут быть объектами, которые можно запускать прямо в БД и вычитывать оттуда только те данные, которые потом можно будет обработать.
Re[11]: [DDD] Вносить ли бизнес-логику в модель предметной о
AUD>>Из того что пример демонстрирующий SOLID можно написать как в DDD так и в anemic не следует что использование SOLID ведет к anemic модели.
G>Да ну? Что-то не верится. G>Возмем ту же задачу, но более абстрактно. Есть некоторые сущности, в зависимости от атрибута(ов) надо к ним применять разные методы обработки.
Слишком абстрактно. Абстрактно без конкретики я могу утверждать что ту же задачу можно спроектировать так, что разбиение на сущности будет таким что просто будут различные сущности каждая с единственной ответственностью, никаких внешних методов обработки итд.
G>Если сделать базовый класс, а от него наследоваться, то мы нарушаем OCP, так как для добавление нового функционала (метода в базовом классе) придется менять всех наследников, а если добавлять методы в наследников, а не в базовый класс, то нарушается LSP.
Если для новой фичи в базовый класс требуется добавление нового функционала, то еще до нарушения OCP нарушается SRP ибо базовый класс спроектирован плохо так как нам приходится добавлять в него дополнительную ответственность.
G>Хороший способ — отвязать данные от логики. Логику можно собирать в классы с двумя методами: первый предикат, определяющий можно ли метод применять к сущности, второй — сама обработка.
Это как? Если на примере который я приводил и с пояснением что и где нужно будет менять если нужно добавить новый тип документа. БД кстати в примере нет, данные берутся из других разнородных источников.
G>Кроме того есть полезный бонус: предикаты сами могут быть объектами, которые можно запускать прямо в БД и вычитывать оттуда только те данные, которые потом можно будет обработать.
Для этого есть паттерн спецификация.
Re[12]: [DDD] Вносить ли бизнес-логику в модель предметной о
Здравствуйте, AUDev, Вы писали:
AUD>>>Из того что пример демонстрирующий SOLID можно написать как в DDD так и в anemic не следует что использование SOLID ведет к anemic модели.
G>>Да ну? Что-то не верится. G>>Возмем ту же задачу, но более абстрактно. Есть некоторые сущности, в зависимости от атрибута(ов) надо к ним применять разные методы обработки. AUD>Слишком абстрактно. Абстрактно без конкретики я могу утверждать что ту же задачу можно спроектировать так, что разбиение на сущности будет таким что просто будут различные сущности каждая с единственной ответственностью, никаких внешних методов обработки итд.
Например как? Упрешься в этот самый Expression Problem, который я описываю. Суть в том что в ООП можно добиться одного из двух: расширяемости данных или расширяемости методов обработки, но не вместе. Или придется ослаблять типизацию, что тоже не айс.
G>>Хороший способ — отвязать данные от логики. Логику можно собирать в классы с двумя методами: первый предикат, определяющий можно ли метод применять к сущности, второй — сама обработка. AUD>Это как?
Класс данных документа отдельно, классы обработки отдельно.
G>>Кроме того есть полезный бонус: предикаты сами могут быть объектами, которые можно запускать прямо в БД и вычитывать оттуда только те данные, которые потом можно будет обработать. AUD>Для этого есть паттерн спецификация.
Спецификация и есть anemic.
Re[2]: [DDD] Вносить ли бизнес-логику в модель предметной об