Re[2]: роль ООП при работе с данными
От: Кэр  
Дата: 26.11.08 16:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Да мы вообще положили прибор всей командой на следующие, простите, технологии:

А>Linq, EF, SilverLight, WPF, WWF, ADO.NET Services, CardSpaces.

Мои искренние соболезнования.

А>Всё что для счастья надо это CLR, ADO.NET, WebServices, WinForms, WebForms, руки из плеч...

А>и со временем будет Framework для своей предметной области...

Скорее будет уродец, но свой заботливо выпестованный, а потому очень любимый. То что вы отмахиваетесь от Linq, EF, Silverligh, WPF — скорее всего говорит о том, что уродец уже есть.
Re[2]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.11.08 17:30
Оценка: +1
Здравствуйте, Аноним, Вы писали:

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


QL>>Заинтересовала статья: http://blogs.gotdotnet.ru/personal/bezzus/PermaLink.aspx?guid=7a6a69bd-bedf-425f-b09c-123b4a41f686


А>Да мы вообще положили прибор всей командой на следующие, простите, технологии:

А>Linq, EF, SilverLight, WPF, WWF, ADO.NET Services, CardSpaces.
Молодцы, а объективные причины есть? или только незнание\страх ?

А>Всё что для счастья надо это CLR, ADO.NET, WebServices, WinForms, WebForms, руки из плеч...

А почему тогда на ассемблере не пишете?

А>и со временем будет Framework для своей предметной области...

Каждый разработчик должен хоть раз в жизни изобрести велосипед.
Re[23]: роль ООП при работе с данными
От: Воронков Василий Россия  
Дата: 26.11.08 18:17
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Жаль. Лично я надеялся что мы обсуждаем суть статьи: преимущества\недостатки Anemic Domain + Service а так же слабо связанные Domain данные в классах. А не всё шелуху вокруг типа EF, Hibernate, ООП и Фаулера.


Ну мои первоначальные посты действительно были не об этом. Я не против в общем-то обсудить и данный вопрос, хотя, честно говоря, не буду слишком хорошо чувствовать себя в шкуре чистого апологета жирной модели. Фактически здесь не существует silver bullet, а вот мнения конкретно о жирной модели, как показывает дискуссия, по каким-то причином сильно заниженные. Могу попробовать ее защитить

ВВ>>Ну вот у меня складывается ощущение, что отменяет. Опять-таки если рассматривать этот вопрос в том же ключе, что и Фаулер — то это тогда не будет анемичная модель. Хотите сервисы поверх доменной модели? Ради бога. Но не лишайте классы поведения.

B>Дело в том что их приходится лишать поведения по ряду причин. Одна из них банальна. Я не могу реюзать сущности Domain Model, когда их поведение вдруг требует работы с БД.

Вот это и неправильно как раз. Я схемку внизу не случайно приводил. У тебя есть отдельный лаер с доменной моделью, там же содержится бизнес-логика. Над ним логика аппликейшина, в которой БЛ быть не должно. Строго под ним — собственно слой доступа к данным. Называть его можешь как хочешь — инфраструктура как у Эванса, репозиторий как у Фаулера — неважно.

Итогом: Поведение сущности — это никак не логика доступа к данным, она отделена от сущности.

ВВ>>Последнее — это как раз то, где у нас может быть этот самый репозитори.

ВВ>>Самый смысл то, что домен — это собственно бизнес. Типичная бизнес-логика. Инфрраструктура уже детали собственно сохранения, загрузки и проч. Каким образом организовать между ними взаимосвязь вопрос второстепенный. Можно, как я предлагал, на уровне Infrastructure реализовать шаблоны для персистенции и далее параметризовывать наши классы этими шаблонами. Это все детали. Никакой жесткой зависимости тут нет.
B>Весь этот абзац чудесно ложится как на Rich так и на Anemic, так что я вообще не понял к чем это.

Ну не совсем. Здесь имеется в виду то, что бизнес-логика является непосредственной частью доменной модели. Она не в "сервисах".
Представим, что у нас есть сущности Перевозка и Груз.

Представим, что у нас есть некий метод — на данный момент даже неважно где он определен — БронироватьПеревозку:

БронироватьПеревозку(Перевозка, Груз)
(
)


Опять-таки неважно что там конкретно содержится. Закроем пока на это глаза. Там может и никакого дата-аксеса не быть, не в этом дело.
Далее — на самом деле Груз не во всякую ведь Перевозку влезет. Т.е. нужно учитывать, что данная конкретная Перевозка способна вместить Груз. А ведь там еще и другой Груз может быть. А в требованиях у
нас — тут самое интересное — также указано, что допустим, предположим, 10% перегруз.
Теперь сущности выглядят так (упрощенно):

Перевозка
(
    Вместительность;
)

Груз
(
    Размер;
)


Соответственно, в тот самый метод БронироватьПеревозку, который пока непонятно где, мы вставляем логику, которая проверяет есть ли, проще говоря, еще место (с учетом допустимого перегруза) для нашего Груза или уже места нет, и эта конкретная Перевозка нам не подходит. Этот метод может быть частью класса Перевозка, частью какого-нибудь сервиса DHL — неважно.
Что плохого в этом подходе?
Фактически у нас есть важное бизнес-правило, и оно смешано с каким-то другим кодом. А что ним надо делать? Куда его "засунуть"? Тут проблема даже не в том, что модификация этого правила на что-то там может повлиять и пр.
Сам код внутри этого БронироватьПеревозку — на кого он расчитан? Бизнес-модель по нашей модели уже не построишь — упс. Программер — ну для этого это пару ифоф каких-то непонятных, что-то там на 1.1 помножается — не факт, что он вообще это соотнесет с каким-то правилом.

Проблема тут в том, что это правило никак не отражено в нашей модели. Бизнес-правила это не отдельный BusinessRuleService — они должны читаться по модели. И они должны быть такими же сущностями, как и все остальное. Таким образом мы добавляем еще одну сущность:

ПравилоПерегрузки
(
  ПерегрузкаДопустима(Перевозка, Груз);
)


И да, да, это будет "класс", прям внутри которого, "по живому" будет описано наше бизнес-правило.
Класс, естестественно, должен быть полиморфным — или через интерфейс, или через виртуальность. Захотим поменять правила перегрузки и разрешить, допустим, 20% перегруз — это коснется только сущности ПравилоПерегрузки.
В итоге имеем то, что Перевозка, скажем, условно параметризуется правилом:

Перевозка[ПравилоПерегрузки]
(
  Вместительность;
  
  Бронировать(Груз);
)


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

В жирной — хотя какая "жирная" — в ООП — модели у нас будут Операторы, совершающие действия над Грузом, которые контролируются через Бизнес-Правила, представленные в виде отдельных сущностей (что и правильно — ведь не Оператор же правила работы с грузом устанавливает). Сама по себе модель будет содержать структуру рабочего процесса.

А что окажется в случае с сервисами?

ВВ>>Кстати, не доводилось ознакомиться с Domen Driven Design Эванса? Там мне кажется интересно проясняется этот вопрос.

B>Нет не читал. Можешь тезисно сюда? Кроме отсылок к ООП?

Ну я это и делаю потихоньку
Полное название: Domain-Driven Design: Tackling Complexity in the Heart of Software, Eric Evans с предисловием Фаулера, которое я уже цитировал
Ссылку приводить не буду, вроде не поощряется, но через гугл находится на раз-два.

На самом деле к отсылкам к ООП стоит тоже относиться... ну менее критично как бы Они не тождественны "отсылкам на". Просто те же товарищи вроде Фаулера на самом деле имеют в виду, что вот у нас есть обширная практика использования ООП, мы все знаем, какие преимущества дает ООП и какие проблемы оно позволяет решить — вот и здесь, здесь ровно то же самое.

ВВ>>Тот факт, что классы должны обладать поведением наверное не стоит сводить к тому, что все возможные действия с этим классом надо пихать непосредственно в сам класс, не находишь?

B>Вот так мы и приходим к надобности Service layer, так как для многих операций у нас банально отсутствует класс предметной области. В связи с чем мы и выдумываем сущность Application/Service как то чье поведение мы описываем.

Я неоднократно оговариваюсь, что на самом деле анемичная модель иногда действительно уместнее. При моем безграничном уважении к тов. Фаулеру, на к-м основано, можно, сказать мое понимание ООП.
Да, есть сценарии, детерминированные теми же стейт-лесс сетевыми протоколами, когда стейт-лесс же сервис окажется тупо более "в кассу" чем все остальное. Но есть бесспорно и другие сценарии. И даже другие сетевые протоколы

ВВ>>Ведь мы же меняем сервис, в котором содержится логика и для других сущностей тоже. Кто гарантирует, что он не написан так, что мы затронет логику "соседних" сущностей?

B>Это всего лишь вопрос к организации сервисов, а никак не аргумент против Anemic Model.

В том-то и суть — что в рамках любой концепции это всегда вопрос правильной организации иерархии классов. Это тупиковая ветка обсуждения на самом деле. Любая критика в сторону ОО-модели может также отметаться как "это лишь вопрос организации классов".

B>>>Практика показала что достаточно удобно.

ВВ>>"Практика показала". Это неопровержимый аргумент. Прочитай начало записи в блоге, которая приводится по первой ссылке
B>Точно такой же аргумент как "сделай ООП и будет ещё удобнее". Повторяю, в другом топике IB привет ряд аргументов в пользу сервисов\anemic, с которыми я абсолютно согласен.

К сожалению, других аргументов я не видел. А те которые видел показались не совсем, скажем так, правильными. Да и честно после Фаулера и Ко как-то совсем странно воспринмается такая трактовка ООП-модели.

B>Но никто нигде больше мне не привел аргумента против, который бы мне стразу открыл мне глаза и показал ошибочность использования Anemic в моем проекте. Всё опять сводится к обсуждению того что ООП это круто. Ну не приходится мне выстраивать сложную иерахию из бизнес процессов. Ненадо они никому в отличие от данных. Отсюда и такая радикальная разница в организации данных от организации логики. Это исключительно про Domain, а не про данные и логику вообще.


ВВ>>Отчасти неверно? Верно или нет,

B>Да. Опечатался. То что методы не связаны в сервисе это не верно.

Методы-действия связаны в сервисах не так как в ОО-модели. Не через сущности, которые осуществляют эти действия.

ВВ>>На настоящий момент мне кажется, что избавление от ООП в Домен Моделе фактически приводит к избавлению от Домен Модели. Возможно, я не прав, но низводя классы до храналищ данных, мы фактически нивелируем саму концепцию класса. Они у нас в сущности мало чем отличаются от "словарей" со свойствами.

B>И что? Пока что никто не обосновал почему это плохо.
ВВ>>Зачем тогда вообще классы? Берите дата-сет, имеющий "реляционную" структуру.
B>За пределами Domain Model существует огромное количество другого кода уровня приложения, котрый использует ООП более чем активно. Но разговор пока только про Domain, достаточно не большую часть приложения в целом. Но важную. Датасеты не типизированы, для чего их сюда приплетать. Они никак не решат проблем с Rich Model.

Мне кажется датасеты — вообще некая концепция просто-контейнера-данных — является как бы следующим шагом в анемичной модели. Фактически логическим ее развитием.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[24]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.11.08 18:52
Оценка: 2 (2)
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ну не совсем. Здесь имеется в виду то, что бизнес-логика является непосредственной частью доменной модели. Она не в "сервисах".

ВВ>Представим, что у нас есть сущности Перевозка и Груз.

ВВ>Представим, что у нас есть некий метод — на данный момент даже неважно где он определен — БронироватьПеревозку:


ВВ>
ВВ>БронироватьПеревозку(Перевозка, Груз)
ВВ>(
ВВ>)
ВВ>


ВВ>Опять-таки неважно что там конкретно содержится. Закроем пока на это глаза. Там может и никакого дата-аксеса не быть, не в этом дело.

ВВ>Далее — на самом деле Груз не во всякую ведь Перевозку влезет. Т.е. нужно учитывать, что данная конкретная Перевозка способна вместить Груз. А ведь там еще и другой Груз может быть. А в требованиях у
ВВ>нас — тут самое интересное — также указано, что допустим, предположим, 10% перегруз.
ВВ>Теперь сущности выглядят так (упрощенно):

ВВ>
ВВ>Перевозка
ВВ>(
ВВ>    Вместительность;
ВВ>)

ВВ>Груз
ВВ>(
ВВ>    Размер;
ВВ>)
ВВ>


ВВ>Соответственно, в тот самый метод БронироватьПеревозку, который пока непонятно где, мы вставляем логику, которая проверяет есть ли, проще говоря, еще место (с учетом допустимого перегруза) для нашего Груза или уже места нет, и эта конкретная Перевозка нам не подходит. Этот метод может быть частью класса Перевозка, частью какого-нибудь сервиса DHL — неважно.

Вроде все правильно.

ВВ>Что плохого в этом подходе?

ВВ>Фактически у нас есть важное бизнес-правило, и оно смешано с каким-то другим кодом. А что ним надо делать? Куда его "засунуть"? Тут проблема даже не в том, что модификация этого правила на что-то там может повлиять и пр.
ВВ>Сам код внутри этого БронироватьПеревозку — на кого он расчитан? Бизнес-модель по нашей модели уже не построишь — упс. Программер — ну для этого это пару ифоф каких-то непонятных, что-то там на 1.1 помножается — не факт, что он вообще это соотнесет с каким-то правилом.
Достаточно выделить метод с нормальным названием, который впоследствии можно сделать инжектируемым в сервис.


ВВ>Проблема тут в том, что это правило никак не отражено в нашей модели. Бизнес-правила это не отдельный BusinessRuleService — они должны читаться по модели. И они должны быть такими же сущностями, как и все остальное.

А что есть модель и почему бизнес-правила должны читаться по модели?

ВВ>Таким образом мы добавляем еще одну сущность:



ВВ>
ВВ>ПравилоПерегрузки
ВВ>(
ВВ>  ПерегрузкаДопустима(Перевозка, Груз);
ВВ>)
ВВ>


ВВ>И да, да, это будет "класс", прям внутри которого, "по живому" будет описано наше бизнес-правило.

ВВ>Класс, естестественно, должен быть полиморфным — или через интерфейс, или через виртуальность. Захотим поменять правила перегрузки и разрешить, допустим, 20% перегруз — это коснется только сущности ПравилоПерегрузки.
Тоже верно.

ВВ>В итоге имеем то, что Перевозка, скажем, условно параметризуется правилом:

ВВ>
ВВ>Перевозка[ПравилоПерегрузки]
ВВ>(
ВВ>  Вместительность;
  
ВВ>  Бронировать(Груз);
ВВ>)
ВВ>

А почему сервис бронирования перевозки нельзя также параметризовать правилом перегрузки?

Например так:
СервисПеревозок
{
    СервисПеревозок(ПравилоПерегрузки)
    (...)

    БронироватьПеревозку(Перевозка, Груз)
    (
        ...
        если ПравилоПерегрузки.ПерегрузкаДопустима(Перевозка, Груз) то
        ...
    )
}


Такой код дает:
1)Меньшую связность — Перевозка не должна занать ни о Грузе, ни о ПравилеПерегрузки
2)Возможность свободно менять правило перегрузки и сервис бронирования без перекомпиляции (через IoC)
3)Не скрывает важные детали. В вашем случае Перевозка.Бронировать(Груз) вызывает может вызывать запросы к базе, обращения к удаленным сервисам или запуск workflow.
Re[24]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.11.08 19:15
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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

Действительно у груза может быть разное состояние\статус, которое выражается одним полем объекта.

ВВ>причем всякий раз за действия с грузом отвечает разный оператор, действия, которые можно совершать над грузом, зависят от состояния Груза.

Действительно мы можем создать workflow, в котором задаем различные этапы взаимодействия Оператора с Грузом.
Отделяя при этом workflow от Оператора и Груза мы уменьшаем связывание и позволяем менять workflow без перекомпиляции.


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

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

ВВ>Таким образом, у нас нет какого-то единого процесса перевозки Груза, есть взаимосвязанные, детерминированные бизнес-правилами действия отдельных операторов.

У нас нет какого-то единого процесса, у нас есть набор процессов (workflow), определяемый темиже бизнес-правилами в сервисах.
То есть сервисы с правилами инжектируются в workflow.


ВВ>В жирной — хотя какая "жирная" — в ООП — модели у нас будут Операторы, совершающие действия над Грузом, которые контролируются через Бизнес-Правила, представленные в виде отдельных сущностей (что и правильно — ведь не Оператор же правила работы с грузом устанавливает). Сама по себе модель будет содержать структуру рабочего процесса.

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

ВВ>А что окажется в случае с сервисами?

См выше.

Кроме того, используя анемичную модель мы можем отказаться от DTO, так как в качестве DTO можем использовать сами объекты данных и составные объекты на базе них.
Re[25]: роль ООП при работе с данными
От: Воронков Василий Россия  
Дата: 26.11.08 19:28
Оценка: :)
Здравствуйте, gandjustas, Вы писали:

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

G>Действительно у груза может быть разное состояние\статус, которое выражается одним полем объекта.

ВВ>>причем всякий раз за действия с грузом отвечает разный оператор, действия, которые можно совершать над грузом, зависят от состояния Груза.

G>Действительно мы можем создать workflow, в котором задаем различные этапы взаимодействия Оператора с Грузом.
G>Отделяя при этом workflow от Оператора и Груза мы уменьшаем связывание и позволяем менять workflow без перекомпиляции.

"Уменьшаем связывания" я так посмотрю это какая-то мантра. Зачем мне действие, которое само по себе вводится некоторым субьектом, "отделять" от этого субьекта? Операции с Грузом на складе — это действия Оператора Склада.

Причем операторы — они как бы разные. И каждый работает с грузом по-своему. Сколько тут всего будет workflow и как вы собираетесь их менять без перекомпиляции? Собственно, без перекомпиляции чего?
А оператор, который хранит груз на складе, и оператор, который его перевозит еще и обладают разным набором характеристик, которые надо учитывать. И что в итоге получится? Сервис РаботаНаСкладе? Универсальная бизнес-логика прямо в нем прошита, чтобы "избежать перекомпиляции" видимо, в форме красиво названных методов? А потом СервисПеревозка? И еще какой-нибудь сервис.
Тогда и получается — отдельная иерархия сервисов совпадающая с иерархией классов — как я и говорил. Или вы предлагаете работу разных операторов, которые не связаны друг с другом, в единый сервис зафигачить? Вот они удивятся, наверное

Описывайте все-таки более конкретную архитектуру, а не общие слова — "ликвидируем связанность", "красиво названные методы", "изменения без перекомпляции" — тогда и обсудим. А пока советую чуть больше подумать над примером.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[26]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 26.11.08 20:09
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


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

G>>Действительно у груза может быть разное состояние\статус, которое выражается одним полем объекта.

ВВ>>>причем всякий раз за действия с грузом отвечает разный оператор, действия, которые можно совершать над грузом, зависят от состояния Груза.

G>>Действительно мы можем создать workflow, в котором задаем различные этапы взаимодействия Оператора с Грузом.
G>>Отделяя при этом workflow от Оператора и Груза мы уменьшаем связывание и позволяем менять workflow без перекомпиляции.

ВВ>"Уменьшаем связывания" я так посмотрю это какая-то мантра.

Конечно мантра. Уменьшение связности уменьшает сложность кода и стоимость внесения изменений.

ВВ>Зачем мне действие, которое само по себе вводится некоторым субьектом, "отделять" от этого субьекта? Операции с Грузом на складе — это действия Оператора Склада.

Это в жизни так. Не всегда модель реального мира стоит переносить на программу.
Кроме того, Оператор.ОперацияСГрузом(Груз) всегда можно записать как ОперацияСГрузом(Оператор, Груз).
Второй вариант предпочтительнее, ибо не вносит зависимость класса оператора от класса груза.

ВВ>Причем операторы — они как бы разные. И каждый работает с грузом по-своему.

И чем собственно операторы различаются?

ВВ>Сколько тут всего будет workflow и как вы собираетесь их менять без перекомпиляции? Собственно, без перекомпиляции чего?

Без перекомпиляции кода приложения. В идеале и без перезапуска приложения.

ВВ>А оператор, который хранит груз на складе, и оператор, который его перевозит еще и обладают разным набором характеристик, которые надо учитывать.

А кто сказал что что нельзя использовать наследование?

ВВ>И что в итоге получится? Сервис РаботаНаСкладе?

Зависит от бизнес-задач.

ВВ>Универсальная бизнес-логика прямо в нем прошита, чтобы "избежать перекомпиляции" видимо, в форме красиво названных методов? А потом СервисПеревозка? И еще какой-нибудь сервис.

В чем проблема? Сложно назвать нормально методы и классы?

В случае жирной модели вместо сервиса РаботаНаСкладе, будут теже самые методы в сущности.


ВВ>Тогда и получается — отдельная иерархия сервисов совпадающая с иерархией классов — как я и говорил.

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

ВВ>Или вы предлагаете работу разных операторов, которые не связаны друг с другом, в единый сервис зафигачить? Вот они удивятся, наверное

Не предлагаю, создайте несколько сервисов.

ВВ>Описывайте все-таки более конкретную архитектуру, а не общие слова — "ликвидируем связанность", "красиво названные методы", "изменения без перекомпляции" — тогда и обсудим. А пока советую чуть больше подумать над примером.

"ликвидируем связанность" и "изменения без перекомпляции" — вполне конкретные преимущества.

А что может жирная модель предложить, кроме мнимых достоинств?
Re[27]: роль ООП при работе с данными
От: Воронков Василий Россия  
Дата: 26.11.08 21:52
Оценка: 3 (1) -1
Здравствуйте, gandjustas, Вы писали:

ВВ>>"Уменьшаем связывания" я так посмотрю это какая-то мантра.

G>Конечно мантра. Уменьшение связности уменьшает сложность кода и стоимость внесения изменений.

"Уменьшение связности" надо делать там, где действительно не должно быть связности, а не трактовать lousely coupled как полную бессвязность. Согласны?

ВВ>>Зачем мне действие, которое само по себе вводится некоторым субьектом, "отделять" от этого субьекта? Операции с Грузом на складе — это действия Оператора Склада.

G>Это в жизни так. Не всегда модель реального мира стоит переносить на программу.
G>Кроме того, Оператор.ОперацияСГрузом(Груз) всегда можно записать как ОперацияСГрузом(Оператор, Груз).
G>Второй вариант предпочтительнее, ибо не вносит зависимость класса оператора от класса груза.

Откуда вы ввзяли ОперацияСГрузом? ОперацияСГрузом — нет такой штуки. Есть РазместитьГрузНаСкладе, ПеревезтиСамолетом и пр. И знаете что — они все не зависят от класса груза ровно в той степени, в какой зависят от оператора. Независимо от того, внутри ли класса, сервиса или вообще в виду глобальной функции вы это опишите. Потому что владелец склада №526 не занимается авиа-перевозками.

ВВ>>Причем операторы — они как бы разные. И каждый работает с грузом по-своему.

G>И чем собственно операторы различаются?

Чем отличается владелец склада №526 от Delta Airlines?

ВВ>>Сколько тут всего будет workflow и как вы собираетесь их менять без перекомпиляции? Собственно, без перекомпиляции чего?

G>Без перекомпиляции кода приложения. В идеале и без перезапуска приложения.

Мне так и не понятно, что конкретно собираетесь менять.

ВВ>>А оператор, который хранит груз на складе, и оператор, который его перевозит еще и обладают разным набором характеристик, которые надо учитывать.

G>А кто сказал что что нельзя использовать наследование?

А кто тут говорил про наследование?

ВВ>>И что в итоге получится? Сервис РаботаНаСкладе?

G>Зависит от бизнес-задач.
ВВ>>Универсальная бизнес-логика прямо в нем прошита, чтобы "избежать перекомпиляции" видимо, в форме красиво названных методов? А потом СервисПеревозка? И еще какой-нибудь сервис.
G>В чем проблема? Сложно назвать нормально методы и классы?

Назвать — несложно. Но дело наверное не в названии.
А в том, что бизнес-логика не должна быть ни частью сервиса, ни частью сущности. Бизнес-правило — отдельная сущность. Заметьте, это не я придумал
Популярная тут в некоторых кругах критика жирной модели сводится к тому, что сами "структуры" данных вроде как меняются очень редко, тогда как поведение меняется часто. Это в корне неверено. Поведение сущностей не меняется никогда. Кошка не начнет лаять как собака, а владелец склада №526 не будет заниматься авиа-перевозками. Меняются — и действительно довольно часто — бизнес-правила — правило "перегрузки" контейнеров, правило для рождественской скидки. И сами по себе эти правила имеют внешний характер по отношению к сущностям. Они не только не являются их поведением, они вообще ни в каком смысле не являются их частью. Вы можете "указать" сущности какое правило ей нужно использовать, не более. Правило — на то и правило, что его все видели, что ему все следовали, а не прятали "в себе" и не притворялись, что это часть их поведения.

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

G>В случае жирной модели вместо сервиса РаботаНаСкладе, будут теже самые методы в сущности.


Да нет, не те же. Я вот например бизнес-логику в виде методов не предлагаю "инжектировать".

ВВ>>Тогда и получается — отдельная иерархия сервисов совпадающая с иерархией классов — как я и говорил.

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

А кто эти задачи решает? Они же не сами решаются. Вот есть задача — перевезти груз. Кто там это делает? А, Дельта Айрлаинс.

ВВ>>Или вы предлагаете работу разных операторов, которые не связаны друг с другом, в единый сервис зафигачить? Вот они удивятся, наверное

G>Не предлагаю, создайте несколько сервисов.
ВВ>>Описывайте все-таки более конкретную архитектуру, а не общие слова — "ликвидируем связанность", "красиво названные методы", "изменения без перекомпляции" — тогда и обсудим. А пока советую чуть больше подумать над примером.
G>"ликвидируем связанность" и "изменения без перекомпляции" — вполне конкретные преимущества.
G>А что может жирная модель предложить, кроме мнимых достоинств?

Я так до сих пор не понял — что можете предложить лично вы. Я уже просил один раз, повторю еще.
Мне непонятно то, о чем вы пишите. Это похоже на какие-то общие слова — какие-то workflow, низкая связанность, какие-то задачи уже поставлены вроде менять без перекомпиляции — при этом абсолютно неясно о чем конкретно речь.

Опишите как будет выглядеть архитектура в свете представленного примера с грузом, вот тогда и будет что обсудить.
Если конкретного описания не будет — то не обессудьте, продолжать дискуссию не буду.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[28]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.11.08 07:16
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


ВВ>>>"Уменьшаем связывания" я так посмотрю это какая-то мантра.

G>>Конечно мантра. Уменьшение связности уменьшает сложность кода и стоимость внесения изменений.

ВВ>"Уменьшение связности" надо делать там, где действительно не должно быть связности, а не трактовать lousely coupled как полную бессвязность. Согласны?

Не согласен. К уменьшению связности надо стремиться всегда. Чем меньше связность — тем меньше сложность. Чем меньше связность, тем больше возможностей повтороного использования кода. Чем меньше связность, тем больше возможность изменять реализацию без остановки приложения.
В каких случаях не надо уменьшать связность?

ВВ>>>Зачем мне действие, которое само по себе вводится некоторым субьектом, "отделять" от этого субьекта? Операции с Грузом на складе — это действия Оператора Склада.

G>>Это в жизни так. Не всегда модель реального мира стоит переносить на программу.
G>>Кроме того, Оператор.ОперацияСГрузом(Груз) всегда можно записать как ОперацияСГрузом(Оператор, Груз).
G>>Второй вариант предпочтительнее, ибо не вносит зависимость класса оператора от класса груза.

ВВ>Откуда вы ввзяли ОперацияСГрузом? ОперацияСГрузом — нет такой штуки. Есть РазместитьГрузНаСкладе, ПеревезтиСамолетом и пр. И знаете что — они все не зависят от класса груза ровно в той степени, в какой зависят от оператора. Независимо от того, внутри ли класса, сервиса или вообще в виду глобальной функции вы это опишите. Потому что владелец склада №526 не занимается авиа-перевозками.


ВВ>>>Причем операторы — они как бы разные. И каждый работает с грузом по-своему.

G>>И чем собственно операторы различаются?
ВВ>Чем отличается владелец склада №526 от Delta Airlines?
Чем отличается? Давнными или поведением, или тем и другим?
Если только поведением, то Опаератор — сервис в себе, если только данными, то все поведение можно вынести в отдельные сервисы. Если и тем и другим, то можно выделить полиморфное поведение для всех операторов и частное для различных операторов. Причем это будут не параллельные иерархии наследования. например РазместитьГрузНаСкладе будет в сервисе склада, а ПеревезтиСамолетом в сервисе перевозок.

ВВ>>>Сколько тут всего будет workflow и как вы собираетесь их менять без перекомпиляции? Собственно, без перекомпиляции чего?

G>>Без перекомпиляции кода приложения. В идеале и без перезапуска приложения.
ВВ>Мне так и не понятно, что конкретно собираетесь менять.
Бизнес-логику.

ВВ>>>И что в итоге получится? Сервис РаботаНаСкладе?

G>>Зависит от бизнес-задач.
ВВ>>>Универсальная бизнес-логика прямо в нем прошита, чтобы "избежать перекомпиляции" видимо, в форме красиво названных методов? А потом СервисПеревозка? И еще какой-нибудь сервис.
G>>В чем проблема? Сложно назвать нормально методы и классы?

ВВ>Назвать — несложно. Но дело наверное не в названии.

ВВ>А в том, что бизнес-логика не должна быть ни частью сервиса, ни частью сущности. Бизнес-правило — отдельная сущность. Заметьте, это не я придумал
Какое-то странное понимание "сервиса". Сервис в данном случае — набор действий, которек выполняются с данными. Бизнес-правило — тоже сервис.

ВВ>Популярная тут в некоторых кругах критика жирной модели сводится к тому, что сами "структуры" данных вроде как меняются очень редко, тогда как поведение меняется часто. Это в корне неверено.

Доказательства?

ВВ>Поведение сущностей не меняется никогда. Кошка не начнет лаять как собака, а владелец склада №526 не будет заниматься авиа-перевозками.

В анемичной модели мы отказываемся от наделения данных поведением. У нас остаются бизнес-правила и бизнес-процессы. Правила и процессы вполне моделируются классами-сервисами.

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

Вот и получаются сервисы. Осталось отделить "поведение" от сущностей и вы получите анемичную модель.
Причина отедлять "поведение" от данных — повторное использование модели данных.


G>>В случае жирной модели вместо сервиса РаботаНаСкладе, будут теже самые методы в сущности.

ВВ>Да нет, не те же. Я вот например бизнес-логику в виде методов не предлагаю "инжектировать".
Ну да, логика будет жестко зашита в сущности. Это и есть сильная связность, что есть плохо.

ВВ>>>Тогда и получается — отдельная иерархия сервисов совпадающая с иерархией классов — как я и говорил.

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

ВВ>А кто эти задачи решает? Они же не сами решаются. Вот есть задача — перевезти груз. Кто там это делает? А, Дельта Айрлаинс.

Ну и? В чем семантическая разница между ПеревезтиГруз(ДельтаАйрлаинс, Груз) и ДельтаАйрлаинс.ПеревезтиГруз(Груз). О том почему первый вариант лучше я уже писал.

ВВ>Я так до сих пор не понял — что можете предложить лично вы. Я уже просил один раз, повторю еще.

ВВ>Мне непонятно то, о чем вы пишите. Это похоже на какие-то общие слова — какие-то workflow, низкая связанность, какие-то задачи уже поставлены вроде менять без перекомпиляции — при этом абсолютно неясно о чем конкретно речь.

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

ВВ>Если конкретного описания не будет — то не обессудьте, продолжать дискуссию не буду.
Каковы решаемые задачи в этом примере и какова схема данных (хотябы примерно)?
Re[26]: роль ООП при работе с данными
От: IB Австрия http://rsdn.ru
Дата: 27.11.08 07:39
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Save в БД тоже во всем том же отдельном лаере.

Нет уж, ты от темы не увиливай, ты двавай за свои слова отвечай.
Куда пихать второй Save, если первый не в отдельном?

ВВ>Почитай что-нибудь про model-driven design в конце концов.

Спорим, я больше умных слов знаю?
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[26]: роль ООП при работе с данными
От: IB Австрия http://rsdn.ru
Дата: 27.11.08 07:39
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Нда... Что тут сказать...

Действительно, по делу-то тебе сказать и нечего.

ВВ>Ну приведем другой примерчик:

Это ты к чему?
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[24]: роль ООП при работе с данными
От: IB Австрия http://rsdn.ru
Дата: 27.11.08 07:39
Оценка: +1 -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Представим, что у нас есть сущности Перевозка и Груз.

Пока, все это вполне себе стройная модель.

ВВ>Фактически у нас есть важное бизнес-правило, и оно смешано с каким-то другим кодом.

С каким кодом оно смешано и откуда такой вывод, что оно вообще смешано? До этого оно просто находилось неизвестно где..

ВВ>Сам код внутри этого БронироватьПеревозку — на кого он расчитан? Бизнес-модель по нашей модели уже не построишь — упс. Программер — ну для этого это пару ифоф каких-то непонятных, что-то там на 1.1 помножается — не факт, что он вообще это соотнесет с каким-то правилом.

Вот тут я ход мысли, честно говоря, потерял.

ВВ> Бизнес-правила это не отдельный BusinessRuleService — они должны читаться по модели.

Почему они должны это делать и почему бизнес-правило не может быть отдельным BusinessRuleService?

ВВ>
ВВ>ПравилоПерегрузки
ВВ>(
ВВ>  ПерегрузкаДопустима(Перевозка, Груз);
ВВ>)
ВВ>

Ну, чем это не сервис?... =)

ВВ>Класс, естестественно, должен быть полиморфным — или через интерфейс, или через виртуальность. Захотим поменять правила перегрузки и разрешить, допустим, 20% перегруз — это коснется только сущности ПравилоПерегрузки.

Для этого не нужен полиморфизм. Для этого надо ввести параметр МаксимальнаяПерегрузка и вынести его в модель, передав в сервис ПравилоПерегрузки при инстанцировании, например... Но в целом, да, такой сервис вполне может реализовывать какой-нибудь общий интерфейс.. )


ВВ>
ВВ>Перевозка[ПравилоПерегрузки]
ВВ>(
ВВ>  Вместительность;
  
ВВ>  Бронировать(Груз);
ВВ>)
ВВ>

Вот тут уже каша какая-то. Почему груз бронирует Перевозка, а не тот, кто отвечает за перевозку груза? Ну или наоборот, может это груз должен решать какой Перевозкой пользоваться? =)

ВВ>Сама по себе модель будет содержать структуру рабочего процесса.

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

ВВ>А что окажется в случае с сервисами?

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

ВВ> При моем безграничном уважении к тов. Фаулеру, на к-м основано, можно, сказать мое понимание ООП.

ОМГ.. Разбираться в ООП по Фаулеру — это все равно что основы общей физики по второму тому Ландавшица учить, понятно почему такая каша..

ВВ> Да и честно после Фаулера и Ко как-то совсем странно воспринмается такая трактовка ООП-модели.

Конечно, потому что в ОО надо разбираться не по Фаулеру и Ко.

ВВ>Мне кажется датасеты — вообще некая концепция просто-контейнера-данных — является как бы следующим шагом в анемичной модели. Фактически логическим ее развитием.

Наоборот, датасеты — это типичный пример жирной модели.
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[29]: роль ООП при работе с данными
От: Воронков Василий Россия  
Дата: 27.11.08 11:31
Оценка: -1 :)
Здравствуйте, gandjustas, Вы писали:

ВВ>>"Уменьшение связности" надо делать там, где действительно не должно быть связности, а не трактовать lousely coupled как полную бессвязность. Согласны?

G>Не согласен. К уменьшению связности надо стремиться всегда. Чем меньше связность — тем меньше сложность. Чем меньше связность, тем больше возможностей повтороного использования кода. Чем меньше связность, тем больше возможность изменять реализацию без остановки приложения.
G>В каких случаях не надо уменьшать связность?

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

— Чтобы изменения в данных Оператора не затронули действие Оператора?
А почему должна меняться структура данных у Дельты? С чего бы это вдруг? А если вдруг у Дельты появятся дополнительные атрибуты, новое состояние, которое будет стоить того, чтобы ради него менять соответствующй класс, вы уверены, что это не приведет к изменению действия? Я уверен, что приведет.

— Чтобы изменения в действиях Оператора не затронули структуру данных Оператора?
А какие могут быть изменения в действиях Оператора? Кошка "сменит пол" и начнет лаять? Дельта свернет свою лавочку и откроет сеть ресторанов "На девятом небе"? Ну тогда наверное мы вообще не сможет использовать ее как оператора. Будет летать Аэрофлотом

ВВ>>>>Причем операторы — они как бы разные. И каждый работает с грузом по-своему.

G>>>И чем собственно операторы различаются?
ВВ>>Чем отличается владелец склада №526 от Delta Airlines?
G>Чем отличается? Давнными или поведением, или тем и другим?

Я бы сказал, что и данными тоже, вернее, даже не столько данными, сколько характеристиками состояния — ведь это такие разные вещи — хранить на складе и перевозить самолетом.

G>Если только поведением, то Опаератор — сервис в себе,


А можно по-подробнее? Как будет выглядеть этот сервис?

G>если только данными, то все поведение можно вынести в отдельные сервисы. Если и тем и другим, то можно выделить полиморфное поведение для всех операторов и частное для различных операторов. Причем это будут не параллельные иерархии наследования. например РазместитьГрузНаСкладе будет в сервисе склада, а ПеревезтиСамолетом в сервисе перевозок.


Ну т.е. на каждый тип оператора по сервису. К чему мы и пришли в итоге и на что Блажкович еще как-то пытался возражать. Есть иерархия операторов, а есть параллельная иерархия сервисов операторов.
А чего мы этим добились, кстати?

ВВ>>>>Сколько тут всего будет workflow и как вы собираетесь их менять без перекомпиляции? Собственно, без перекомпиляции чего?

G>>>Без перекомпиляции кода приложения. В идеале и без перезапуска приложения.
ВВ>>Мне так и не понятно, что конкретно собираетесь менять.
G>Бизнес-логику.

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

ВВ>>>>И что в итоге получится? Сервис РаботаНаСкладе?

G>>>Зависит от бизнес-задач.
ВВ>>>>Универсальная бизнес-логика прямо в нем прошита, чтобы "избежать перекомпиляции" видимо, в форме красиво названных методов? А потом СервисПеревозка? И еще какой-нибудь сервис.
G>>>В чем проблема? Сложно назвать нормально методы и классы?

ВВ>>Назвать — несложно. Но дело наверное не в названии.

ВВ>>А в том, что бизнес-логика не должна быть ни частью сервиса, ни частью сущности. Бизнес-правило — отдельная сущность. Заметьте, это не я придумал
G>Какое-то странное понимание "сервиса". Сервис в данном случае — набор действий, которек выполняются с данными. Бизнес-правило — тоже сервис.

А у сервиса могут быть какие-то еще характеристики, кроме "набор действий"? Как мне понять, сервис это или не сервис? А том, может, у меня и правда одни сервисы кругом.
Каковы правила изменения сервиса? Сервис может быть полиморфным в том же смысле, что и класс? Может ли сервис зависеть от других сервисов? А может ли сервис явно зависеть от каких-то структур данных в нашей Доменной Модели? Может ли сервис иметь состояние?

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

ВВ>>Популярная тут в некоторых кругах критика жирной модели сводится к тому, что сами "структуры" данных вроде как меняются очень редко, тогда как поведение меняется часто. Это в корне неверено.

G>Доказательства?

Я доказательства привожу дальше вообще-то. Поведение — сущностная характеристика класса. Поведение определяет класс. Кошка может лаяться как собака?
Придумайте сами пример, когда структура не менялась, а менялось поведение — и заодно посмотрите, действительно ли то, что изменялось является поведением.
Типичная ошибка — это что-то типа — ИметьСкидку вставить как поведение для Товар. Естественно, это самое ИметьСкидку мы будет менять по 200 раз. Но какое же это поведение для Товар? Это бизнес-правило.

ВВ>>Поведение сущностей не меняется никогда. Кошка не начнет лаять как собака, а владелец склада №526 не будет заниматься авиа-перевозками.

G>В анемичной модели мы отказываемся от наделения данных поведением. У нас остаются бизнес-правила и бизнес-процессы. Правила и процессы вполне моделируются классами-сервисами.



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

G>Вот и получаются сервисы. Осталось отделить "поведение" от сущностей и вы получите анемичную модель. Причина отедлять "поведение" от данных — повторное использование модели данных.

Каким образом вы собираетесь использовать оператора авиа-перевозок независимо от его действий?

G>>>В случае жирной модели вместо сервиса РаботаНаСкладе, будут теже самые методы в сущности.

ВВ>>Да нет, не те же. Я вот например бизнес-логику в виде методов не предлагаю "инжектировать".
G>Ну да, логика будет жестко зашита в сущности. Это и есть сильная связность, что есть плохо.

Вы меня читаете вообще? Бизнес-логика представлена в виде отдельных сущностей. В сами классы защита та логика, которая не меняется по определению.

ВВ>>>>Тогда и получается — отдельная иерархия сервисов совпадающая с иерархией классов — как я и говорил.

G>>>Не получится, ибо методы в сервисы группируются по решаемым задачам, а не по субъекту действий.
ВВ>>А кто эти задачи решает? Они же не сами решаются. Вот есть задача — перевезти груз. Кто там это делает? А, Дельта Айрлаинс.
G>Ну и? В чем семантическая разница между ПеревезтиГруз(ДельтаАйрлаинс, Груз) и ДельтаАйрлаинс.ПеревезтиГруз(Груз).

Это вы мне скажите, в чем разница. Оператор в первом и во втором случае — это одно и то же. Думаю, нет. Или одно и то же?
Ведь оператор уже не может быть просто набором данных. У вас будет иерархия операторов, причем полиморфная, у операторов будет состояния. Осталось только вернуть им поведение — и это будет ОО-модель.

G>О том почему первый вариант лучше я уже писал.


А вы это покажите.

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

ВВ>>Если конкретного описания не будет — то не обессудьте, продолжать дискуссию не буду.
G>Каковы решаемые задачи в этом примере и какова схема данных (хотябы примерно)?

Доставить груз из пункта А в пункт Б. Груз едет морем и воздухом, Груз надо страховать, хранить на складе в перерывах между перевозками. Есть бизнес-правило вокруг всего это, вроде допустимости 10% перегруза. Можете придумать сами. За каждое из действий отвечает отдельный оператор. Остальное можете додумать сами — неважно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[30]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.11.08 12:23
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

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


ВВ>>>"Уменьшение связности" надо делать там, где действительно не должно быть связности, а не трактовать lousely coupled как полную бессвязность. Согласны?

G>>Не согласен. К уменьшению связности надо стремиться всегда. Чем меньше связность — тем меньше сложность. Чем меньше связность, тем больше возможностей повтороного использования кода. Чем меньше связность, тем больше возможность изменять реализацию без остановки приложения.
G>>В каких случаях не надо уменьшать связность?

ВВ>Наверное в тех случаях, когда эта связь является сущностной характеристикой, первичным половым признаком, так сказать

ВВ>Какую вот связь вы хотите здесь устранить? Между Оператором и действием оператора? А что нам это даст?
Возможность использовать объект оператора в тех частях системы, которые не должны знать о его поведении (например в клиентской части).

ВВ>- Чтобы изменения в данных Оператора не затронули действие Оператора?

ВВ>А почему должна меняться структура данных у Дельты? С чего бы это вдруг? А если вдруг у Дельты появятся дополнительные атрибуты, новое состояние, которое будет стоить того, чтобы ради него менять соответствующй класс, вы уверены, что это не приведет к изменению действия? Я уверен, что приведет.
И пусть приведет. Изменение структуры данных практически всегда приводит к изменению практичечски всего кода вплоть до UI.

ВВ>- Чтобы изменения в действиях Оператора не затронули структуру данных Оператора?

ВВ>А какие могут быть изменения в действиях Оператора? Кошка "сменит пол" и начнет лаять? Дельта свернет свою лавочку и откроет сеть ресторанов "На девятом небе"? Ну тогда наверное мы вообще не сможет использовать ее как оператора. Будет летать Аэрофлотом
Не надо демагогию разводить. Изменения могут быть любые.

ВВ>>>>>Причем операторы — они как бы разные. И каждый работает с грузом по-своему.

G>>>>И чем собственно операторы различаются?
ВВ>>>Чем отличается владелец склада №526 от Delta Airlines?
G>>Чем отличается? Давнными или поведением, или тем и другим?

ВВ>Я бы сказал, что и данными тоже, вернее, даже не столько данными, сколько характеристиками состояния — ведь это такие разные вещи — хранить на складе и перевозить самолетом.

Конкретнее. Какими характеристиками состояния?
Я за этими "такими разными вещами" сейчас вижу только enum ShippingType.

G>>Если только поведением, то Опаератор — сервис в себе,

ВВ>А можно по-подробнее? Как будет выглядеть этот сервис?
Все сервисы — классы, что непонятно? there is no magic

G>>если только данными, то все поведение можно вынести в отдельные сервисы. Если и тем и другим, то можно выделить полиморфное поведение для всех операторов и частное для различных операторов. Причем это будут не параллельные иерархии наследования. например РазместитьГрузНаСкладе будет в сервисе склада, а ПеревезтиСамолетом в сервисе перевозок.


ВВ>Ну т.е. на каждый тип оператора по сервису. К чему мы и пришли в итоге и на что Блажкович еще как-то пытался возражать. Есть иерархия операторов, а есть параллельная иерархия сервисов операторов.

ВВ>А чего мы этим добились, кстати?
См выделенное. Методы в сервисы группируются по другим признакам.


G>>Какое-то странное понимание "сервиса". Сервис в данном случае — набор действий, которек выполняются с данными. Бизнес-правило — тоже сервис.


ВВ>А у сервиса могут быть какие-то еще характеристики, кроме "набор действий"? Как мне понять, сервис это или не сервис? А том, может, у меня и правда одни сервисы кругом.

Наверное тебе стоит почитать про SOA.

ВВ>Каковы правила изменения сервиса? Сервис может быть полиморфным в том же смысле, что и класс?

Да, сервис — это класс.

ВВ>Может ли сервис зависеть от других сервисов?

Да.

ВВ>А может ли сервис явно зависеть от каких-то структур данных в нашей Доменной Модели?

Он будет явно зависить он них, почтому что выполняет какие-то действия с данными. А данные не будут зависить от сервисов.

ВВ>Может ли сервис иметь состояние?

Может.

ВВ>Мне в общем-то по фигу как это называть. Мне важно не название, а то, где это бизнес-правило находится. А оно должно представлять собой отдельный класс. Структуры данных и действия не должны явно зависеть от бизнес-правила.

Почему действия не должны зависеть от бизнес-правил? Сам же выше приводил пример с такой зависимостью.

ВВ>>>Популярная тут в некоторых кругах критика жирной модели сводится к тому, что сами "структуры" данных вроде как меняются очень редко, тогда как поведение меняется часто. Это в корне неверено.

G>>Доказательства?

ВВ>Я доказательства привожу дальше вообще-то. Поведение — сущностная характеристика класса. Поведение определяет класс. Кошка может лаяться как собака?

У нас не кошки и собаки. Прочитай название темы.

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

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


ВВ>Типичная ошибка — это что-то типа — ИметьСкидку вставить как поведение для Товар. Естественно, это самое ИметьСкидку мы будет менять по 200 раз. Но какое же это поведение для Товар? Это бизнес-правило.

Это словоблудие.
Что такое бизнес-правило? Когда покажешь пример, то окажется что это тоже самое что и сервис в анемичной модели.


ВВ>Каким образом вы собираетесь использовать оператора авиа-перевозок независимо от его действий?

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

G>>>>В случае жирной модели вместо сервиса РаботаНаСкладе, будут теже самые методы в сущности.

ВВ>>>Да нет, не те же. Я вот например бизнес-логику в виде методов не предлагаю "инжектировать".
G>>Ну да, логика будет жестко зашита в сущности. Это и есть сильная связность, что есть плохо.

ВВ>Вы меня читаете вообще? Бизнес-логика представлена в виде отдельных сущностей. В сами классы защита та логика, которая не меняется по определению.

Это какая логика "не меняектся по-определению"? Только тривиальная, типа получить сумму по цене и количеству. Любая нетривиальная логика изменится не один раз.

ВВ>>>>>Тогда и получается — отдельная иерархия сервисов совпадающая с иерархией классов — как я и говорил.

G>>>>Не получится, ибо методы в сервисы группируются по решаемым задачам, а не по субъекту действий.
ВВ>>>А кто эти задачи решает? Они же не сами решаются. Вот есть задача — перевезти груз. Кто там это делает? А, Дельта Айрлаинс.
G>>Ну и? В чем семантическая разница между ПеревезтиГруз(ДельтаАйрлаинс, Груз) и ДельтаАйрлаинс.ПеревезтиГруз(Груз).

ВВ>Это вы мне скажите, в чем разница. Оператор в первом и во втором случае — это одно и то же. Думаю, нет. Или одно и то же?

Одно и тоже. Только поведение в первом случае внешнее, а во втором — нет. А если нет разницы, то зачем нам большая связность?

ВВ>Ведь оператор уже не может быть просто набором данных. У вас будет иерархия операторов, причем полиморфная, у операторов будет состояния. Осталось только вернуть им поведение — и это будет ОО-модель.

Действительно. А не возвращать им поведение и будет стройная модель.

G>>О том почему первый вариант лучше я уже писал.

ВВ>А вы это покажите.
Показать почему меньшая связность — лучше?
Это должен быть достаточно большой проект. "На пальцах" не получится.

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

ВВ>>>Если конкретного описания не будет — то не обессудьте, продолжать дискуссию не буду.
G>>Каковы решаемые задачи в этом примере и какова схема данных (хотябы примерно)?

ВВ>Доставить груз из пункта А в пункт Б. Груз едет морем и воздухом, Груз надо страховать, хранить на складе в перерывах между перевозками. Есть бизнес-правило вокруг всего это, вроде допустимости 10% перегруза. Можете придумать сами. За каждое из действий отвечает отдельный оператор. Остальное можете додумать сами — неважно.

Детали тут — как раз самое важное. При проектировании сферического коня в вакууме ничего хорошего не получается.


После таких уверенных рассказов про операторов и грузы могу предположить что есть готовая система, покажите здесь код и обсудим на конкретных примерах.
Re[31]: роль ООП при работе с данными
От: Воронков Василий Россия  
Дата: 27.11.08 15:03
Оценка: +1 -1 :)
Здравствуйте, gandjustas, Вы писали:

ВВ>>Наверное в тех случаях, когда эта связь является сущностной характеристикой, первичным половым признаком, так сказать

ВВ>>Какую вот связь вы хотите здесь устранить? Между Оператором и действием оператора? А что нам это даст?
G>Возможность использовать объект оператора в тех частях системы, которые не должны знать о его поведении (например в клиентской части).

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

ВВ>>- Чтобы изменения в действиях Оператора не затронули структуру данных Оператора?

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

Демагогию разводите вы. Ничего конкретного я так и слышу. Чтобы отвечать в вашем стиле, достаточно заучить несколько общих фраз и отвечать, комбинируя их в разном порядке.
Изменения в действиях субьекта по определению не могут быть независимыми от структуры субьекта. Если они независимы — значит неправильно выделен субьект.

ВВ>>Я бы сказал, что и данными тоже, вернее, даже не столько данными, сколько характеристиками состояния — ведь это такие разные вещи — хранить на складе и перевозить самолетом.

G>Конкретнее. Какими характеристиками состояния?
G>Я за этими "такими разными вещами" сейчас вижу только enum ShippingType.

Т.е. отличие между Оператором, хранящим груз на складе, и Оператором, перевозящим груз, это "enum ShippingType"?

G>>>Если только поведением, то Опаератор — сервис в себе,

ВВ>>А можно по-подробнее? Как будет выглядеть этот сервис?
G>Все сервисы — классы, что непонятно? there is no magic

Да, теперь все понятно

ВВ>>Ну т.е. на каждый тип оператора по сервису. К чему мы и пришли в итоге и на что Блажкович еще как-то пытался возражать. Есть иерархия операторов, а есть параллельная иерархия сервисов операторов.

ВВ>>А чего мы этим добились, кстати?
G>См выделенное. Методы в сервисы группируются по другим признакам.

Да, я уже услышал этот великий признак. Только вот все примеры сервисов, которые приводятся, почему-то совпадают с иерархией классов. Сервисы группируются по решаемым задачам, да? А кто решает задачи?

ВВ>>А у сервиса могут быть какие-то еще характеристики, кроме "набор действий"? Как мне понять, сервис это или не сервис? А том, может, у меня и правда одни сервисы кругом.

G>Наверное тебе стоит почитать про SOA.

Наверное, стоит перестать хамить и подумать, почему бизнес-правило это не сервис. А я про SOA я знаю побольше вашего.

ВВ>>Каковы правила изменения сервиса? Сервис может быть полиморфным в том же смысле, что и класс?

G>Да, сервис — это класс.

Нет.

ВВ>>Может ли сервис зависеть от других сервисов?

G>Да.

Нет.

ВВ>>А может ли сервис явно зависеть от каких-то структур данных в нашей Доменной Модели?

G>Он будет явно зависить он них, почтому что выполняет какие-то действия с данными. А данные не будут зависить от сервисов.

Нет.

ВВ>>Может ли сервис иметь состояние?

G>Может.

Нет.
Может быть вам стоит прочитать про SOA?

ВВ>>Мне в общем-то по фигу как это называть. Мне важно не название, а то, где это бизнес-правило находится. А оно должно представлять собой отдельный класс. Структуры данных и действия не должны явно зависеть от бизнес-правила.

G>Почему действия не должны зависеть от бизнес-правил? Сам же выше приводил пример с такой зависимостью.

Действия определяются бизнес-правилами. Это разные вещи. "Купить товар" и "получить скидку".

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

G>Тоже бронирование грузовю Вполне может потребоваться цепочка аппрувов для перегруза.

Это не поведение, это бизнес-логика.

G>В жирной модели приедтся сущность Перевозка дополнить парамертрами аппрувов,


Нет, придется определить новое бизнес-правило.

Остальные мудрствования поскипаны. Больше писать в этом топике не буду.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[32]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.11.08 15:15
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

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


ВВ>>>- Чтобы изменения в действиях Оператора не затронули структуру данных Оператора?

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

ВВ>Демагогию разводите вы. Ничего конкретного я так и слышу. Чтобы отвечать в вашем стиле, достаточно заучить несколько общих фраз и отвечать, комбинируя их в разном порядке.

ВВ>Изменения в действиях субьекта по определению не могут быть независимыми от структуры субьекта. Если они независимы — значит неправильно выделен субьект.
Контр-пример. Изменение порядка бронирования груза. от самого руза никак не зависит.

ВВ>>>Я бы сказал, что и данными тоже, вернее, даже не столько данными, сколько характеристиками состояния — ведь это такие разные вещи — хранить на складе и перевозить самолетом.

G>>Конкретнее. Какими характеристиками состояния?
G>>Я за этими "такими разными вещами" сейчас вижу только enum ShippingType.

ВВ>Т.е. отличие между Оператором, хранящим груз на складе, и Оператором, перевозящим груз, это "enum ShippingType"?

В таком случае это 2 разных набора данных: "склад" и "перевозчик" или два разных сервиса.


ВВ>>>Ну т.е. на каждый тип оператора по сервису. К чему мы и пришли в итоге и на что Блажкович еще как-то пытался возражать. Есть иерархия операторов, а есть параллельная иерархия сервисов операторов.

ВВ>>>А чего мы этим добились, кстати?
G>>См выделенное. Методы в сервисы группируются по другим признакам.

ВВ>Да, я уже услышал этот великий признак. Только вот все примеры сервисов, которые приводятся, почему-то совпадают с иерархией классов.

Какие примеры?

ВВ>Сервисы группируются по решаемым задачам, да? А кто решает задачи?

Сервисы и решают.

ВВ>>>А у сервиса могут быть какие-то еще характеристики, кроме "набор действий"? Как мне понять, сервис это или не сервис? А том, может, у меня и правда одни сервисы кругом.

G>>Наверное тебе стоит почитать про SOA.

ВВ>Наверное, стоит перестать хамить и подумать, почему бизнес-правило это не сервис. А я про SOA я знаю побольше вашего.

И в чем же разница между бизнес-правилом и сервисом?

ВВ>>>Каковы правила изменения сервиса? Сервис может быть полиморфным в том же смысле, что и класс?

G>>Да, сервис — это класс.
ВВ>Нет.
?

ВВ>>>Может ли сервис зависеть от других сервисов?

G>>Да.
ВВ>Нет.
И кто-то после этого говорит что понимает SOA?

ВВ>>>А может ли сервис явно зависеть от каких-то структур данных в нашей Доменной Модели?

G>>Он будет явно зависить он них, почтому что выполняет какие-то действия с данными. А данные не будут зависить от сервисов.
ВВ>Нет.
Совсем бред. Как сервисы могут что-то делать с данными если ничего о них не знают?

ВВ>>>Может ли сервис иметь состояние?

G>>Может.
ВВ>Нет.
Причины?

ВВ>Может быть вам стоит прочитать про SOA?

Улыбнуло.

ВВ>>>Мне в общем-то по фигу как это называть. Мне важно не название, а то, где это бизнес-правило находится. А оно должно представлять собой отдельный класс. Структуры данных и действия не должны явно зависеть от бизнес-правила.

G>>Почему действия не должны зависеть от бизнес-правил? Сам же выше приводил пример с такой зависимостью.

ВВ>Действия определяются бизнес-правилами. Это разные вещи. "Купить товар" и "получить скидку".

и какая разница с точки зрения программы?

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

G>>Тоже бронирование грузовю Вполне может потребоваться цепочка аппрувов для перегруза.

ВВ>Это не поведение, это бизнес-логика.

А что тогда "поведение", чем оно отличается "бизнес-логики", чем они отличаются от "бизнес-правил"?
С точки зрения программы. Концептуальные вещи не интересуют.

G>>В жирной модели приедтся сущность Перевозка дополнить парамертрами аппрувов,

ВВ>Нет, придется определить новое бизнес-правило.
Правильно, а как код, который бронирует груз узнает о новом бизнес-правиле?
Re[32]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.11.08 15:17
Оценка: -1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Остальные мудрствования поскипаны. Больше писать в этом топике не буду.

Слив засчитан.
Re[33]: роль ООП при работе с данными
От: Воронков Василий Россия  
Дата: 27.11.08 15:29
Оценка:
Здравствуйте, gandjustas, Вы писали:

ВВ>>Может быть вам стоит прочитать про SOA?

G>Улыбнуло.

Почитайте МСДН хотя бы, чтобы в следующий раз свое невежество так не выказывать:
http://msdn.microsoft.com/en-us/library/ms954638.aspx

Кстати, было бы очень интересно посмотреть на сервис, зависящий от типов в конкретной Доменной Модели
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[34]: роль ООП при работе с данными
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 27.11.08 17:40
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


ВВ>>>Может быть вам стоит прочитать про SOA?

G>>Улыбнуло.

ВВ>Почитайте МСДН хотя бы, чтобы в следующий раз свое невежество так не выказывать:

ВВ>http://msdn.microsoft.com/en-us/library/ms954638.aspx
Вау, круто. Вообще-то SOA гораздо шире, чем веб-сервисы.

ВВ>Кстати, было бы очень интересно посмотреть на сервис, зависящий от типов в конкретной Доменной Модели

В случае анемичной модели типы в ней описывают только данные.
Теперь вопрос, может ли сервис что-то делать с данными если он о них ничего не знает?
Re[5]: роль ООП при работе с данными
От: Mike Chaliy Украина http://chaliy.name
Дата: 27.11.08 19:20
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Sergey T., Вы писали:


ST>>Если дела обстоят именно так, как Вы описываете, тогда действительно, делать Order.Items свойством — это ошибка проектирования.


S>>>Все эти полезные подробности, вытекающие из удаленного характера Items, скрыты за тупым геттером.

ST>>См. выше. Однако, рассмотрите также и ситуацию, когда Ордер.Айтемс — это именно свойство Ордер. С семантикой свойства. Ни один Айтем без заказа не существует. Удаляются они все вместе. Ну и так далее. Скажите, в таком случае отложенная загрузка — тоже плохо?
S>Естественно. Совершенно неважно, что айтемы не могут жить без ордера.
S>Во-первых, это неправда — в топике Иван приводил, почему. В частности, менеджера поставок вообще не интересует, в каких заказах расположены айтемы.
S>С его точки зрения, айтемы принадлежат товару.

Так это же преимущество доменной модели. В отличии от анемичной, она вообще не завист от БД. Это более чем нормально строить отдельные доменные области для разныех областей применения промапленные на одни и теже физичиские данные. Если есть описанный рекваирмент, то вообще не проблема создать одну модель для склада (ордер и чаилдами ввиде ордер айтемс) и вторую для менеджера (товар, а к ниму ридонли прилинкованы ордер айтмс).

Более того в анемичной такая схема выходит значительно сложней. Я думаю вам легко будет представить себе модель в которой ордер айтемс для модели склада значительно отличаеться от ордер айтмс для менеджера.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
А тут я живу и пишу...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.