@oop_ru

Страница 760 из 785
Dmitry
26.09.2018
14:22:05
мм… а разве уровень домена и доменные штуки — это разные вещи?

Adel
26.09.2018
14:22:34
я говорил "приложение" имея ввиду весь код приложения. а не какой-то слой

Aleh
26.09.2018
14:23:03
уровни, слои это все обманы. Есть объекты, модули и связи между ними

их циклы изменения

Google
Aleh
26.09.2018
14:23:16
а загоны по слоям дают больше проблем чем пользы

Adel
26.09.2018
14:24:13
ну... слои дают некоторые правильные понятия ящитаю... но согласен что некоторый народ слишком по ним упарывается и теряет суть

Dmitry
26.09.2018
14:24:41
я говорил "приложение" имея ввиду весь код приложения. а не какой-то слой
ну какая-то часть приложения таки должна знать про эти объекты, иначе они бесполезны же

Adel
26.09.2018
14:24:56
это какие-то технические детали твоей самописной ORM

Dmitry
26.09.2018
14:25:36
так она не моя самописная, а обычный хибернейт

Adel
26.09.2018
14:25:42
они не должны вылезти из папки vendor

аа. так у тебя Ява?

а хибернейт же просто создает все как надо? или ты из того что он создал лепишь уже своё?

Dmitry
26.09.2018
14:27:48
чтобы он работал ему нужно подсунуть размеченные аннотациями классы, в которых аннотациями же «проставлены» связи между классами по полям и типы этих связей. вот в это дерево классов он потом по запросу и заливает данные. из него же и сохраняет

Adel
26.09.2018
14:28:01
угу

и ты эти классы называешь моделями базы?

Dmitry
26.09.2018
14:28:19
вот это дерево классов я называю моделями, да

Google
Adel
26.09.2018
14:28:25
и потом из них уже лепишь доменные обьекты?

Aleh
26.09.2018
14:28:34
не надо так

Adel
26.09.2018
14:28:42
однако ты очень любишь тратить кучу времени на бесполезный труд.

Dmitry
26.09.2018
14:29:01
лепил. получалось, что DO очень похожи на модели и была куча лишних мапперов

после того как перестал, у меня образовались в этих моделях поля, которые нужны в рантайме и не нужны в базе. отсюда и пошёл дискас

Dmitry
26.09.2018
14:34:46
корни агрегатов, сущности и vo это доменные штуки
корень лежит в доменных штуках модельки базы — в базовых штуках там же лежит моделька, которая повторяет структуру агрегата вот как обычно соотносится эта моделька корня и сам корень? экземпляр модели лежит в поле корня агрегата? или корень является потомком этой модельки?

что за поля то?
https://t.me/oop_ru/75852

Adel
26.09.2018
14:36:25
ну тебе уже говорили про риски. что если упадет то состояние не сохранится и вероятно нужны саги какие-то.

Dmitry
26.09.2018
14:37:06
мне не нужно сохранять именно это состояние. когда всё поднимется состояние прилетит с активных клиентов

Aleh
26.09.2018
14:37:32
так зачем это в агрегате?

Dmitry
26.09.2018
14:38:13
незачем. будет лежать в бизнес-логике или каком-нибудь доменном объекте это два разных вопроса

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

Aleh
26.09.2018
14:56:42
Забыть про модели базы данных

И не придется связывать

Dmitry
26.09.2018
14:57:05
и вот если разделять поля которые нужны в рантайме и поля, которые не нужны. если всё хранить в одном месте, то получается простая работа с DTO. Спросил у агрегата состояние, смаппил в DTO и отдал на фронт, а потом эвентами менять состояние фронта при смене состояния агрегата. если же хратить в разных местах — придётся запрашивать состояние из двух мест и в двух местах райзить эвенты для обновления фронта

И не придется связывать
так. а как тогда сохранять стейт агрегата? забываю про модели => забываю про орм => базы нет => ничего нет.

Aleh
26.09.2018
14:59:07
Корень агрегата мапится в базу, конец истории

Dmitry
26.09.2018
15:05:14
а что значит «маппится в базу» в моём случае с орм? корень агрегата == модель базы + логика поддержания консистентности ¹ корень агрегата с помощью маппера маппит свой стейт на модели базы ²

Google
Dmitry
26.09.2018
15:32:15
Что значит у тебя модель базы? Это описание маппинга с агрегата на таблицы?
я не знаю как это правильно называется. слышал, что называют моделями базы это куча файлов для ОРМ в которых аннотациями проиписаны сущности и связи между ними по полям и по этим аннотациям ОРМ вытаскивает из базы данные, запихивая в классы и также обратно сохраняет.

Yury
26.09.2018
15:55:50
а что значит «маппится в базу» в моём случае с орм? корень агрегата == модель базы + логика поддержания консистентности ¹ корень агрегата с помощью маппера маппит свой стейт на модели базы ²
Возможны на мой взгляд оба варианта. Если у тебя только модели базы, а сервисы отдельно то 1 вар. Если у тебя и модели базы и бизнес модели, то 2 вариант либо переписать маппинг не в объекте, а декларативно отдельно.

Роман
26.09.2018
16:15:04
Предположим есть примерно такая задача: Есть некая подсистема которая производит некий выстрел в пространстве. В ответ она возвращает информацию о том, куда попал выстрел: либо это выстрел по мишени, либо по некоторому объекту окружения. Ещё выстрел мог никуда не попасть. Суть текущей реализации: Есть тип Hit. От него два производных типа: TargetHit и EnviromentHit. Все три типа не содержат методов и состоят только из полей. Есть такая абстракция public interface IShootBroadcaster { Hit Shoot(Shoot shoot); } Т.е мы полностью скрываем то, как там высчитываются попадания и в ответ только получаем попадание определённого типа. Далее в зависимости от типа, происходят различные действия. При попадание в цель, высчитываются очки, пишутся логи и прочее. В случае с окружением происходит другой не связный набор действий. var hit = _shootBroadcaster.Shoot(shoot); if(hit is EnviromentHit) { OnHitEnviroment?.Invoke((EnviromentHit)hit); } else if(hit is TargetHit) { OnHitTarget?.Invoke((TargetHit)hit); } На сколько это адекватно? Классическая реализация паттерна Визитор тут не подойдёт по ряду причин. Я тут вижу только один аналогичный путь - изменить абстракцию. Но на ум ничего лучше не приходит. Сейчас по сути хрупкое место сосредоточено в том месте, где действие над типом делегируется другой системе (сейчас это выражено через события). Вопрос: как можно побороть это?

Извините что влез в оживлённый спор

Dmitry
26.09.2018
16:18:13
Мб это не оч конечно, но у меня маппинг jpa описан в xml. А domain объекты никак с ним не связаны. Тк у меня rich model и я не хотел мешать персистенс и доменную часть.
у меня было разделение на объекты домена и энтити под хибернейт с маппингом через мапстракт. но эти сущности были ооочень похожи и по итогу я перенёс немного логики и полей из DO в энтити и удалил DO. получается, что сейчас есть бизнес-модели и модели базы. с одной стороны стало чуть логичнее и без дублирования. с другой — возникают вопросы с полями, которые не нужны в базе, но которые, по сути, негде теперь красиво хранить в первом варианте агрегат лежит в persistence-штуках, а во втором — в домене? и вот про Rich/Anemic. Хибернейт разве не подталкивает к использованию Rich моделей?

Yury
26.09.2018
16:29:33
у меня было разделение на объекты домена и энтити под хибернейт с маппингом через мапстракт. но эти сущности были ооочень похожи и по итогу я перенёс немного логики и полей из DO в энтити и удалил DO. получается, что сейчас есть бизнес-модели и модели базы. с одной стороны стало чуть логичнее и без дублирования. с другой — возникают вопросы с полями, которые не нужны в базе, но которые, по сути, негде теперь красиво хранить в первом варианте агрегат лежит в persistence-штуках, а во втором — в домене? и вот про Rich/Anemic. Хибернейт разве не подталкивает к использованию Rich моделей?
"но эти сущности были ооочень похожи и по итогу я перенёс немного логики и полей из DO в энтити и удалил DO." Не понял чем мотивировано подобное решение? Почему бы не оставить бизнес-логику в бизнес-сущности, а логику персистенса в персистенс сущность(хибернейт энтити)?

"и вот про Rich/Anemic. Хибернейт разве не подталкивает к использованию Rich моделей?" Думаю он ни к какой модели не подталкивает.

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

В целом можно забить на это и работать в смежной сущности. Доменная сущность и hibernate entity в одном объекте. Это экономит время.

Adel
26.09.2018
16:36:32
Предположим есть примерно такая задача: Есть некая подсистема которая производит некий выстрел в пространстве. В ответ она возвращает информацию о том, куда попал выстрел: либо это выстрел по мишени, либо по некоторому объекту окружения. Ещё выстрел мог никуда не попасть. Суть текущей реализации: Есть тип Hit. От него два производных типа: TargetHit и EnviromentHit. Все три типа не содержат методов и состоят только из полей. Есть такая абстракция public interface IShootBroadcaster { Hit Shoot(Shoot shoot); } Т.е мы полностью скрываем то, как там высчитываются попадания и в ответ только получаем попадание определённого типа. Далее в зависимости от типа, происходят различные действия. При попадание в цель, высчитываются очки, пишутся логи и прочее. В случае с окружением происходит другой не связный набор действий. var hit = _shootBroadcaster.Shoot(shoot); if(hit is EnviromentHit) { OnHitEnviroment?.Invoke((EnviromentHit)hit); } else if(hit is TargetHit) { OnHitTarget?.Invoke((TargetHit)hit); } На сколько это адекватно? Классическая реализация паттерна Визитор тут не подойдёт по ряду причин. Я тут вижу только один аналогичный путь - изменить абстракцию. Но на ум ничего лучше не приходит. Сейчас по сути хрупкое место сосредоточено в том месте, где действие над типом делегируется другой системе (сейчас это выражено через события). Вопрос: как можно побороть это?
а зачем ты вообще сделал разные классы если не используешь полиморфизм?

Роман
26.09.2018
16:36:58
Adel
26.09.2018
16:37:25
ударение у меня было на слово полиморфизм ?

Роман
26.09.2018
16:37:42
Я вас не понимаю

Adel
26.09.2018
16:37:56
а что такое полиморфизм понимаем?

Роман
26.09.2018
16:38:20
Да

Adel
26.09.2018
16:40:26
я б вообще эвент генерил. и обрабатывал каждый по своему

в принципе у тебя также... почти

в системе произошел выстрел. и она генерит эвент. либо попавший выстрел. либо непопавший.

Google
Adel
26.09.2018
16:42:12
а дальше идет реакция на этот эвент. на каждый разная.

Роман
26.09.2018
16:42:32
И в чём разница?

Если более чётко выделить проблематику: мы не можем делегировать тому во что попали полную обработку попадания

Я помню у Теплякова в книге похожая ситуация разбиралась на примере логгера и разных событий лога

Но всё целиком вспомнить не могу, и видимо лучше перечитать

Dmitry
26.09.2018
16:47:51
Дублирования тут нет, тк две сущности отвечают за разные контексты. Доменную область и хранение в базе. Если вам нужно будет поменять название поля в базе, то вы поменяете его в сущности персистенса.
да, в этом есть некоторый плюс. но обычно переименовываю поле сразу везде или вот добавление поля. добавить в базу, добавить в энтити, добавить в DO и два раза добавить в маппер грустная штука немного

Dmitry
26.09.2018
17:05:28
Поэтому можно забить и в одном объекте совмещать оба контекста. DO и модель базы. Я потерял нить, в чем проблема то?)
ок, спасибо, чуть прояснилось. я почему-то не подумал, что так можно было (смешать DO и Persistence) получается а-ля active-record объект. который и доменный, и немного отвечает за своё сохранение я просто уточнял, не совсем ли глупость творю с агрегатом стало понятно — если он лежит в persistence слое, то энтити может быть корнем агрегата и отдельная сущность не нужна. «проблема» осталась одна — «лишние» поля в энтити. но, наверное, с этим можно смириться.

Dmitry
26.09.2018
17:09:24
Вот это поясни детальнее, почему это не мапится автоматом?
насколько я понял, мапстракт мапит один объект на другой по заданным правилам. но когда он маппит A на A' он не знает, что у A есть родительский элемент B на смапленный экземпляр которого нужно тоже поставить ссылку. т.е. в A' должна быть ссылка на B' которая автоматом не делается. и проще всего её сделать на этапе афтемаппинга B', когда все A' уже смаппились и можно в них проставить ссылки на B'

Aleh
26.09.2018
17:09:28
вы все-таки погрязли в слоях, забудьте про базу и смоделируйте объекты, который пусть просто лежат в памяти

никакого персиста, просто объекты с поведением

после этого надо поверх навесить персист, который будет жить в конфигурациях и новых реализациях репозитория

Dmitry
26.09.2018
17:12:01
"«проблема» осталась одна — «лишние» поля в энтити. но, наверное, с этим можно смириться." - а разве те поля которые не аннотированы - они как и не сохраняются?
оно умное и пытается понять куда неаннотированное сохранить. по умаолчанию в поля с теми же именами. но указав @Transient оно не будет этого делать. проблема не в автосохранении, а в том, что в энтити не нужно это поле, если это Persistence. Но если это Persistence и Do — то норм

Перейдите на другую маппинг либу где поддержка маппинга связей есть.
так эта проблема решается несколькими строчками кода и, в целом, не такая уж и проблема (сама по себе)

Google
Dmitry
26.09.2018
17:18:38
после этого надо поверх навесить персист, который будет жить в конфигурациях и новых реализациях репозитория
чуть-чуть не понял про «будет жить в конфигурациях и новых реализациях репозитория». в что такое конфигурации репозитория? а результате получится, что есть DO и есть пресист со своими Энтитями и маппинг между ними и что энтити будут ооочень похожи на DO и в результате получится состояние недельной давности, где было такое разделение. о. ещё я про тесты забыл. что DO в персист смаппится нормально и обратно

Yury
26.09.2018
17:21:24
это в целом идея data mapepr
Он вроде, как я понял, пришел к выводу, что ему не нужны отдельно DO и Персистенс модель.

Aleh
26.09.2018
17:21:38
это хорошо

Yury
26.09.2018
17:26:54
Предположим есть примерно такая задача: Есть некая подсистема которая производит некий выстрел в пространстве. В ответ она возвращает информацию о том, куда попал выстрел: либо это выстрел по мишени, либо по некоторому объекту окружения. Ещё выстрел мог никуда не попасть. Суть текущей реализации: Есть тип Hit. От него два производных типа: TargetHit и EnviromentHit. Все три типа не содержат методов и состоят только из полей. Есть такая абстракция public interface IShootBroadcaster { Hit Shoot(Shoot shoot); } Т.е мы полностью скрываем то, как там высчитываются попадания и в ответ только получаем попадание определённого типа. Далее в зависимости от типа, происходят различные действия. При попадание в цель, высчитываются очки, пишутся логи и прочее. В случае с окружением происходит другой не связный набор действий. var hit = _shootBroadcaster.Shoot(shoot); if(hit is EnviromentHit) { OnHitEnviroment?.Invoke((EnviromentHit)hit); } else if(hit is TargetHit) { OnHitTarget?.Invoke((TargetHit)hit); } На сколько это адекватно? Классическая реализация паттерна Визитор тут не подойдёт по ряду причин. Я тут вижу только один аналогичный путь - изменить абстракцию. Но на ум ничего лучше не приходит. Сейчас по сути хрупкое место сосредоточено в том месте, где действие над типом делегируется другой системе (сейчас это выражено через события). Вопрос: как можно побороть это?
А что обработчики делают с Hit?

Роман
26.09.2018
17:28:24
А что обработчики делают с Hit?
Зависит от типа, и это не может сокрываться под интерфейсом типа Hit

Dmitry
26.09.2018
17:28:29
после этого надо поверх навесить персист, который будет жить в конфигурациях и новых реализациях репозитория
а… поверх — это в получившихся классах расставить аннотации для ОРМ и получив, в итоге, смесь DO с Энтити?

Aleh
26.09.2018
17:28:56
а… поверх — это в получившихся классах расставить аннотации для ОРМ и получив, в итоге, смесь DO с Энтити?
это может быть отдельный файлик с конфигом для маппера, можно распихать аннотации, которые будут только метаинфой

это уже как удобнее лично вам в проекте управлять конфигами

Dmitry
26.09.2018
17:30:05
спасибо, теперь понял в принципе, оно так и получилось к текущему моменту.

сейчас вспомнил ещё одно поле, которое не хочу в базу сохранять — список с EventListener'ами. (хотя, может быть его там тоже не должно быть)

Aleh
26.09.2018
17:34:00
да уж, список eventListener’ов вряд ли походит на информацию предметной области

Yury
26.09.2018
17:44:39
Зависит от типа, и это не может сокрываться под интерфейсом типа Hit
Бес конкретики посоветовать что-то сложно. Вообще мне кажется что такая абстракция бесполезна в данном случае, если вы так ее используете. Есть ли у hit-ов что-то общее? И чем они отличаются? Могут ли обработчики hit-ов вызвать какой-то абстрактный метод у hit?

Dmitry
26.09.2018
17:45:07
т.е EventListenerы в DO — не очень красиво? а как красивее информировать заинтересованные объекты о изменении какого-то DO? сделать «шину» для сообщений и передавать ссылку на оную в DO и DO будет её дёргать в нужный момент? или контроль изенения DO лежит за его пределами? бизнес-логика смотрит на результат сеттера и вызывает листенеров, список которых тоже в бизнес-логике лежит?

Роман
26.09.2018
17:45:45
Бес конкретики посоветовать что-то сложно. Вообще мне кажется что такая абстракция бесполезна в данном случае, если вы так ее используете. Есть ли у hit-ов что-то общее? И чем они отличаются? Могут ли обработчики hit-ов вызвать какой-то абстрактный метод у hit?
Нет, методы вызывать не могут. Но разница между ними есть, как и общее. Так например все попадание имеют некоторую точку в пространстве и нормаль поверхности. Попадание по цели, отправляется на сервер для последующих обработак. Попадание по окружению нужно только для визуализации

При этом попадание по цели тоже имеет визуализацию. Возможно мне стоит пересмотреть иеерархию классов

Страница 760 из 785