Обновить
8
0
Толмачёв Дмитрий@FiresShadow

Разработчик ПО

Отправить сообщение
А, понятно, у idiv указано, что он из Германии…
Есть правда экономические механизмы, поиски своих ниш, борьба за качество, но проще ведь налог ввести, чтобы нормальные товары стоили дороже?

Хех, так ведь никто и не отрицал других экономических механизмов, просто был предложен ОДИН ИЗ таких механизмов. Сами что-то себе придумали и сами же себя и раскритиковали.
Ну, думаю, и электронику тоже можно свою производить. Страна то большая и развитая. Просто не до конца отошла от 90х.
Наверное, со временем подешевеют, тогда можно будет и домой отечественный комп поставить. Имхо, нужно потихоньку налог увеличивать на те импортные товары, которые у нас невыгодно производить из-за необходимости больших первоначальный денежных вложений. Тогда будет возможность вложениям окупиться быстрее, чем за 100 лет.
Настройка БД для каскадного удаления — один из примеров проникновения логики предметной области в логику сохранения данных.

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

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

Какие вы видите альтернативы каскадному удалению на стороне бд? 1)Каждый раз делать каскадное удаление вручную? 2)Удалить внешние ключи? 3)Указать необходимость каскадного удаления на стороне ORM, если она поддерживает такую функциональность (если да, а в чём тогда принципиальное отличие — указать правило в маппинге ORM или в бд)? Имхо, нет ничего плохого в каскадном удалении на стороне бд, даже без генерации внешних ключей на основании атрибутов. Между прочим, вопрос о том, что следует помещать на уровень бд, уже рассматривался в комментариях к предыдущей статье автора. Автор видимо не читал. А зря…
Как уже говорил lair, холиварить можно на любую тему, было бы желание. Например, знает ли Эванс что такое DDD, или же определение, которое он дал в своей книге, неверно. Имеет ли деление кода на слои и уровни какое то отношение к коду, или это просто болтология. Можно ли реализовать приложение в духе DDD с приемлемым быстродействием. Но у меня нет желания холиварить на эти темы. Так что будем считать что каждый остался при своей точке зрения.
У меня есть предположение, что может не давать вам покоя в вопросе про проверку уникальности билета на стороне хранилища. Сначала нужно сделать проверку в доменном уровне на уникальность, а потом ещё и в инфраструктурном. Но этот вопрос легко решается. В одном месте задаём правило, а потом на основе этого правила и делаем проверку в доменном уровне, и генерируем правило для хранилища. Правила для хранилища можно генерировать например вот так.
DDD не описывает инфраструктурный уровень если что. Максимум что описывает DDD — репозиторий, как компонент между инфраструктурой и доменом.
Повторюсь, DDD — это концепция проектирования. Цитируя Эванса, DDD — это «система взглядов и подходов». Один из таких подходов — разделить приложение на уровни, в том числе на инфраструктурный уровень. И репозиторий не является компонентом между инфраструктурным и доменным уровнями.
Если честно, мне немного непонятно, зачем человек, который не знает определения DDD, не понимает какой уровень за что отвечает и пр, берётся пропагандировать, что
Теория DDD красива только в теории.


Расчет — как обычно просто сумма по позициям
Тогда в доменной сущности.
Ну собственно что и требовалось доказать, важная часть логики (на самом деле САМАЯ важная часть) выпала из структуры DDD вообще.
Инфраструктурный уровень, по вашему, не имеет ничего общего со структурой DDD? DDD — это концепция проектирования программ, и понятие инфраструктурного уровня — часть этой концепции.

Вы не ответили на конкретный вопрос, это будет класс сущности, domain service или репозиторий?
Алгоритм расчёта суммы заказа будет или в доменной сущности, или в доменном сервисе — в зависимости от предметной области и сложности самого расчёта.
И в какой уровень по вашему нужно запихнуть проверку уникальности?
Если мы проверяем, не продан ли билет на это место перед тем, как начать создание и сохранение билета, то это бизнес-логика приложения: «нельзя продавать два билета на одно и то же место». Проверка в процессе сохранения того, что мы не пытаемся сохранить в персистентное хранилище два билета на одно и то же место — это уже не бизнес-логика приложения, а всего лишь необходимость, возникающая из-за того, что несколько клиентов могут попытаться почти одновременно создать два билета на одно место. А так как это не бизнесс-логика и не координирование задач, то, согласно DDD, проверку уникальности в момент сохранения нужно поместить в инфраструктурный уровень. Процитирую определение Эванса, которое он даёт инфраструктурному уровню: инфраструктурный уровень обеспечивает непосредственную техническую поддержку для верхних уровней: передачу сообщений на операционном уровне, непрерывность существования объектов на уровне модели, вывод элементов управления на уровне пользовательского интерфейса и т.д. Итак, проверка должна находиться в инфраструктурном уровне.
Давайте теперь определимся в каком именно классе. Согласно ООП, данные и код, работающий с этими данными, следует поместить в одном классе. Таким образом, проверка уникальности должна находиться в коде персистентного хранилища. Если в качестве персистентного хранилища у вас используется файл на жёстком диске, то нужно написать класс, который будет производить чтение\запись в этот файл и контролировать уникальность. Если в качестве персистентного хранилища вы используете базу данных, то вам повезло — этот код уже написан за вас и вам нужно лишь декларативно указать, что два билета на одно место сохранять в хранилище нельзя.

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

Прочитайте лучше книжку Эванса. Как я и говорил, он все эти моменты довольно подробно разжёвывает, в том числе объясняет когда следует использовать доменные сервисы.
в DDD нет нормальной возможности выразить всю логику в терминах операций с доменными объектами.
Почитайте Эванса, помимо доменного уровня в DDD есть и другие уровни. Не нужно запихивать всю логику в доменный уровень.

1) Как распределеть отвественность между сервисами, репозитариями и сущностями?
2) Кто вызвает сущности\репозитарии\сервисы?
У Эванса, кстати, нет ответа на эти вопросы.
У Эванса подробно и детально разжёвано, кто и к кому обращается и какой слой за что несёт ответственность. Процитирую отрывок: «уровни прикладных операций и предметной области обращаются к СЛУЖБАМ, предоставляемым инфраструктурным уровнем.»

Насколько я понял, там говорится про sequence из базы данных, т.е. примерно тоже самое, что и я предлагал. Метод, который бы генерировал идентификаторы также, как и NH, был бы в пару строчек кода и умел бы работать с любым sequence. В крайнем случае, можно написать эту пару строчек кода и выложите в Nuget, и проблема решена.
Если точнее, не программист запрос к бд на всех заказчиков указанных заказов напишет, а NH автоматически джойн заказов с заказчиками сделает в момент доставания заказов из бд и соответствующие свойства Заказ.Заказчик заранее заполнит, если флаг LazyLoad не выставлен.
Не совсем понимаю, почему если точно знать будут ли в этом месте использоваться заказчики и перед загрузкой заказов указать нужно ли сразу загрузить и заказчиков, то возникает недетерминированная производительность? Очень даже определенная производительность — можно даже план запроса посмотреть. А будут использоваться заказчики или же нет, можно и по коду посмотреть. Но вот если до того, как мы достали заказы точно неизвестно, нужны заказчики или нет, да ещё для некоторых заказов нужны, а для некоторых нет, то лучше их сразу всех загрузить одним запросом. По крайней мере мы точно можем определить по коду (или по постановке задачи): или заказчики точно не нужны, или возможно понадобятся.
А NH как будто может отслеживать такие ситуации, что на двух компьютерах попытались почти одновременно сохранить две сущности, в результате чего им сгенерировались одинаковые идентификаторы? Исключение ведь выбросится. Такие проблемы решаются на уровне бд и решение применимо к любой ORM.
А зачем вам нужны идентификаторы? Наверное чтобы сослаться на эту сущность в других сущностях, так? Для этого есть NavigationProperty.
Но даже если вам всё таки нужны идентификаторы, то это вполне реализуемо для любой ORM. Храним максимальный идентификатор в каком-нибудь sequence или отдельной таблице, и в рамках одной транзакции увеличиваем его на единицу и достаём из бд. Получаем уникальный идентификатор без необходимости сохранения сущностей в базу.
Так я как раз и писал о том,
что необходимость отложенности загрузки зависит от места использования
Не совсем понимаю. По-моему, всегда в выигрыше. Если без использования LazyLoad NH сгенерирует примерно следующий код
select * from Table
join Table2 on…
join Table3 on…
Если указать что Table2 и Table3 LazyLoad, то NH сгенерирует «select * from Table».
Если потом в коде не обращаться к Table.Table2 и Table.Table3, то всегда в выигрыше.
Если в коде для каждого объекта Table обратиться к Table.Table2 и Table.Table3, то всегда в проигрыше.
Например в маппинге fluent nhibernate заказа есть следующий код:
References(x => x.Customer).Column(«CUSTOMER_ID»).LazyLoad();
Тогда при загрузке из бд заказа поле Customer не заполнится, но оно считается из бд при первом обращении к этому полю.
Если грузится сразу много заказов и по факту нужна только треть таких полей (связанных сущностей из других таблиц), то запрос может занимать несколько минут, и его оптимизация оправдана.
Почему не нужен? В некоторых случаях Lazy load позволяет уменьшить время запроса в несколько раз.

Информация

В рейтинге
Не участвует
Откуда
Россия
Дата рождения
Зарегистрирован
Активность