В любой мало-мальской экосистеме обязательно будет такая штука, как «job runner» Нет, мы не сделаем правильно, не поправим наши схемы, не озаботимся триггерами и persistent views
Загрузить обновления данных в CSV для 60000 товаров. С валидацией данных конечно же, с выдачей ошибок валидации пользователю в том же CSV. Отправить 40000 товаров на обработку в другую систему, с соответствующими изменениями в своей базе для каждого товара в результате успешной и неуспешной отправки. Загружать файл, загруженный пользователем, в 2 разных файловых хранилища. В одно во время запроса пользователя, в другое позже, чтобы он не ждал. Нужно учесть, что любое хранилище может быть недоступно в данный момент, и загружать когда станет доступно.
Ну давайте, расскажите, как вы это сделаете с триггерами и persistent views, без фонового процесса обработки.
Конечно. Как и в любую другую сущность. Если он меняет состояние договора, состояние пользователя, создает одни сущности и удаляет другие, значит он существует вне любой сущности и задает правила как они должны взаимодействовать.
Как вообще можно вызвать метод "создатьЗаказ" у объекта заказа, который еще не создан. Будете помещать в конструктор всю логику, включая взаимодействие с платежным провайдером?
В вашем варианте в классе Пользователь будет изменяться состояние множества разных ничем не связанных сущностей
Это не мой вариант, я просто привел пример вопроса "Куда поместить бизнес-логику", который возникает, когда в процессе участвует и изменяется несколько сущностей. Мой вариант это не помещать ни в какую. Бизнес задает правила, как выполнять какой-то бизнес-процесс, а не какая-то отдельная сущность.
А с логикой в сущности есть аналогичная же проблема - она превращается в God-object, потому что содержит абсолютно все связанные с ней методы бизнес-логики - для пользовательской части, для админки, для импорта через консольную команду, для обработки сообщений из Кафки.
Так он не только состояние договора меняет. В разной бизнес-логике он может например менять флаг пользователя "Договор подписан", создавать сущности для истории изменений "ПодписаниеДоговора", создавать записи "УчастникДоговора" для связи многие-ко-многим, с transactional outbox создавать сущности "УведомлениеНаЭлектроннуюПочту".
Я сильно сомневаюсь, что в статьях на Хабре массово используется информация из "монографий, журнальных статей, сборников докладов на конференциях", чтобы можно было высказывать претензии к тому, что их не указывают.
Вот в том и дело, что нет. Мне ссылка на то, кто такой Дональд Кнут, в каждой статье с его упоминанием не нужна. Тем более в виде отдельного списка литературы.
А её там нету.
Тогда, как я сказал в самом первом комментарии, интересующиеся могут спросить в комментариях "Откуда вы взяли эту информацию?". Если ее там нету, то вообще непонятно, на что вы ссылку собираетесь давать.
Потому что полная реализация бизнес-логики требует зависимости для ввода-вывода и другие сущности, а это создает разные сложности. И почему логика должна быть именно в "Договор", почему бы не сделать метод "Пользователь.подписатьДоговор()"?
Тут можно или отослать вас на три других статьи, или скопировать их на двадцати страницах.
А можно не отсылать и не копировать. Кому надо поищет в интернете или спросит в комментариях.
А если не повторять эти статьи, тогда многие читатели просто не поймут, о чём идёт речь.
1. Значит они не являются аудиторией статьи. 2. Они могут поискать сами эту информацию в интернете. 3. Такого рода ссылки и так встречаются в статьях на Хабре. Я сейчас на первой странице своей ленты нашел больше 10 ссылок только в превьюшках.
https://habr.com/ru/articles/748900/ В это вашей статье вы почему-то не привели ссылку на информацию, кто такой Дональд Кнут и на описание формата TeX. Вас не волновало, что многие читатели просто не поймут, о чём идёт речь. Наверно вы решили, что аудитория и так знает, кто это, и в этом нет необходимости?
А зачем для этого ссылки, если можно просто не повторять? Зачем повторять, если вы не хотите повторять? Просто не пишете текст, который является повтором другого текста, и всё.
И? Вывод-то какой? Я вот из этого делаю вывод, что ссылки и в научных статьях не нужны. Или все-таки нужны? А зачем тогда? Если вы попробуете ответить на этот вопрос, то разница между научной статьей и статьей на Хабре будет очевидна.
Если логика для действий "подписание через веб, мобильное приложение, еще каким-то способом" различается, то и в сущности это будут разные методы. Если логика одинаковая, то будет вызываться один метод, даже если он находится не в сущности.
Вызывать метод "подписать" при импорте уже подписанных точно не надо. Вот как раз если у вас переводить в подписанные можно только через метод "Подписать" со всеми соответствующими уведомлениями, то сделать импорт невозможно, потому что импорт предполагает, что надо создать новую запись сразу в подписанном состоянии.
Этот подход ломается, когда в бизнес-действии участвуют другие объекты и ввод-вывод, для которого нужны зависимости.
Давайте так. Вместо того, чтобы писать комменты как всё будет хорошо, лучше сравним код. У меня есть эта статья, там описаны бизнес-требования. Покажите, как будет выглядеть код с "действиями над объектом" для действий "Сохранение товара" и "Отправка на ревью". Я думаю, лучше написать 200 строк кода, чем 200 строк комментов.
до более сложных "договор" с методами "подписать", "принять", "отклонить"
Конкретно здесь проблема в том, что эти методы не принадлежат объекту "договор". "Подписать договор" это не действие договора, это действие _с_ договором. И кроме самого договора оно может включать много других объектов. Инструкция бизнеса как подписывать договор не принадлежит никакому из упоминающихся в ней объектов, она существует сама по себе как отдельный объект. Это правило взаимодействия других объектов, которое бизнес придумывает сам и изменяет по желанию.
При этом в объекте "договор" могут быть методы "подписать", "принять", "отклонить", но они будут просто комплексными сеттерами, которые записывают несколько значений в поля объекта. Они не должны содержать всю бизнес-логику действия.
Не бывает научных публикаций без списка литературы. Без ссылок на источники. А здесь ровно наоборот - только без ссылок и бывают.
Я не планирую проверять источники, поэтому лично мне они не нужны. Хабр это не сайт научных публикаций, здесь многие статьи написаны на основе личного опыта, какие источники тут приводить. Кому надо, могут прекрасно сами поискать информацию в интернете, а если не найдут то спросить в комментах "Откуда вы взяли эту информацию?".
Тогда непонятно, против чего вы возражали. Я в самом первом комментарии написал, что говорю про изменяющие операции в приложении и транзакции БД, а не про долгие бизнес-процессы. Какую часть бизнес-процесса содержат изменяющие операции в конкретном приложении, это совсем другой вопрос.
Запись лочится на время уменьшения одного поля для переноса этой суммы на холд а понимать логику бизнес-процесса
Еще раз говорю, я говорю о технической реализации любого (вообще любого) действия приложения, которое что-то меняет в базе данных. Для любой бизнес-логики. Действие может делать то, что вы хотите, только оно должно быть с локами до чтения данных в приложение. Если у вас обработчик запроса только переносит на холд, отлично, он всё равно должен ставить лок на запись, которую он хочет обновить или проверить, до ее чтения (и разблокировать после переноса на холд). В примере из статьи автор решил делать все проверки в одном обработчике, там тоже надо блокировать записи до их чтения.
Ну так если они все хотят обновить например баланс одного счета, то в вашем подходе все кроме первого откатятся, потому что первый вклинился, и повторят все действия заново. Но сохранит данные опять только один, а другие опять откатятся, потому что второй вклинился. И так далее. В результате это займет столько же времени, сколько с ожиданием, только с лишней нагрузкой на сервер.
Если они меняют разные группы полей, то можно попробовать разделить одну сущность на две со связью один-к-одному.
Я согласен, что может быть в вашей архитектуре это подходящее решение, но я бы постарался сначала использовать другие решения из-за вероятности бесконечного вклинивания. А если вероятность отсутствия вклинивания высокая, то мне кажется и с локами при правильном подходе должно быть все нормально.
Я не говорю, что вы говорите, что локи не нужны. Вы говорите, что локи не нужны до чтения данных. Я говорю, что нужны.
Только на момент изменения данных.
А какой смысл записывать данные, которые некорректно рассчитаны?
Когда работает в репозитории - лочите на время работы все объекты с которыми работаете?
В очередной раз повторяю - я не предлагаю блокировать данные на часы и дни.
а потенциальные конфликты решаете потом при мерже?
Решение конфликтов это ручное действие. Если вы хотите разбирать и исправлять некорректные данные в миллионах строк в базе вручную, то конечно можно не использовать локи.
Загрузить обновления данных в CSV для 60000 товаров. С валидацией данных конечно же, с выдачей ошибок валидации пользователю в том же CSV.
Отправить 40000 товаров на обработку в другую систему, с соответствующими изменениями в своей базе для каждого товара в результате успешной и неуспешной отправки.
Загружать файл, загруженный пользователем, в 2 разных файловых хранилища. В одно во время запроса пользователя, в другое позже, чтобы он не ждал. Нужно учесть, что любое хранилище может быть недоступно в данный момент, и загружать когда станет доступно.
Ну давайте, расскажите, как вы это сделаете с триггерами и persistent views, без фонового процесса обработки.
Конечно. Как и в любую другую сущность. Если он меняет состояние договора, состояние пользователя, создает одни сущности и удаляет другие, значит он существует вне любой сущности и задает правила как они должны взаимодействовать.
Как вообще можно вызвать метод "создатьЗаказ" у объекта заказа, который еще не создан. Будете помещать в конструктор всю логику, включая взаимодействие с платежным провайдером?
Это не мой вариант, я просто привел пример вопроса "Куда поместить бизнес-логику", который возникает, когда в процессе участвует и изменяется несколько сущностей. Мой вариант это не помещать ни в какую. Бизнес задает правила, как выполнять какой-то бизнес-процесс, а не какая-то отдельная сущность.
А с логикой в сущности есть аналогичная же проблема - она превращается в God-object, потому что содержит абсолютно все связанные с ней методы бизнес-логики - для пользовательской части, для админки, для импорта через консольную команду, для обработки сообщений из Кафки.
Так он не только состояние договора меняет. В разной бизнес-логике он может например менять флаг пользователя "Договор подписан", создавать сущности для истории изменений "ПодписаниеДоговора", создавать записи "УчастникДоговора" для связи многие-ко-многим, с transactional outbox создавать сущности "УведомлениеНаЭлектроннуюПочту".
Я сильно сомневаюсь, что в статьях на Хабре массово используется информация из "монографий, журнальных статей, сборников докладов на конференциях", чтобы можно было высказывать претензии к тому, что их не указывают.
Если его можно заполнить и подписать, значит он может изменяться.
Если коротко, объекты не должны сами себя рисовать. Было похожее обсуждение, я там приводил пример с рисованием собаки и ее гавкания.
Вот в том и дело, что нет. Мне ссылка на то, кто такой Дональд Кнут, в каждой статье с его упоминанием не нужна. Тем более в виде отдельного списка литературы.
Тогда, как я сказал в самом первом комментарии, интересующиеся могут спросить в комментариях "Откуда вы взяли эту информацию?".
Если ее там нету, то вообще непонятно, на что вы ссылку собираетесь давать.
Потому что полная реализация бизнес-логики требует зависимости для ввода-вывода и другие сущности, а это создает разные сложности. И почему логика должна быть именно в "Договор", почему бы не сделать метод "Пользователь.подписатьДоговор()"?
А можно не отсылать и не копировать. Кому надо поищет в интернете или спросит в комментариях.
1. Значит они не являются аудиторией статьи.
2. Они могут поискать сами эту информацию в интернете.
3. Такого рода ссылки и так встречаются в статьях на Хабре. Я сейчас на первой странице своей ленты нашел больше 10 ссылок только в превьюшках.
https://habr.com/ru/articles/748900/
В это вашей статье вы почему-то не привели ссылку на информацию, кто такой Дональд Кнут и на описание формата TeX. Вас не волновало, что многие читатели просто не поймут, о чём идёт речь. Наверно вы решили, что аудитория и так знает, кто это, и в этом нет необходимости?
А зачем для этого ссылки, если можно просто не повторять? Зачем повторять, если вы не хотите повторять? Просто не пишете текст, который является повтором другого текста, и всё.
И? Вывод-то какой?
Я вот из этого делаю вывод, что ссылки и в научных статьях не нужны. Или все-таки нужны? А зачем тогда? Если вы попробуете ответить на этот вопрос, то разница между научной статьей и статьей на Хабре будет очевидна.
Если логика для действий "подписание через веб, мобильное приложение, еще каким-то способом" различается, то и в сущности это будут разные методы. Если логика одинаковая, то будет вызываться один метод, даже если он находится не в сущности.
Вызывать метод "подписать" при импорте уже подписанных точно не надо. Вот как раз если у вас переводить в подписанные можно только через метод "Подписать" со всеми соответствующими уведомлениями, то сделать импорт невозможно, потому что импорт предполагает, что надо создать новую запись сразу в подписанном состоянии.
Этот подход ломается, когда в бизнес-действии участвуют другие объекты и ввод-вывод, для которого нужны зависимости.
Давайте так. Вместо того, чтобы писать комменты как всё будет хорошо, лучше сравним код.
У меня есть эта статья, там описаны бизнес-требования. Покажите, как будет выглядеть код с "действиями над объектом" для действий "Сохранение товара" и "Отправка на ревью". Я думаю, лучше написать 200 строк кода, чем 200 строк комментов.
Почему вдруг оно будет в сотне разных мест, если действие "Подписать договор" у бизнеса одно?
Конкретно здесь проблема в том, что эти методы не принадлежат объекту "договор". "Подписать договор" это не действие договора, это действие _с_ договором. И кроме самого договора оно может включать много других объектов. Инструкция бизнеса как подписывать договор не принадлежит никакому из упоминающихся в ней объектов, она существует сама по себе как отдельный объект. Это правило взаимодействия других объектов, которое бизнес придумывает сам и изменяет по желанию.
При этом в объекте "договор" могут быть методы "подписать", "принять", "отклонить", но они будут просто комплексными сеттерами, которые записывают несколько значений в поля объекта. Они не должны содержать всю бизнес-логику действия.
Я не планирую проверять источники, поэтому лично мне они не нужны. Хабр это не сайт научных публикаций, здесь многие статьи написаны на основе личного опыта, какие источники тут приводить. Кому надо, могут прекрасно сами поискать информацию в интернете, а если не найдут то спросить в комментах "Откуда вы взяли эту информацию?".
Тогда непонятно, против чего вы возражали. Я в самом первом комментарии написал, что говорю про изменяющие операции в приложении и транзакции БД, а не про долгие бизнес-процессы. Какую часть бизнес-процесса содержат изменяющие операции в конкретном приложении, это совсем другой вопрос.
Еще раз говорю, я говорю о технической реализации любого (вообще любого) действия приложения, которое что-то меняет в базе данных. Для любой бизнес-логики. Действие может делать то, что вы хотите, только оно должно быть с локами до чтения данных в приложение. Если у вас обработчик запроса только переносит на холд, отлично, он всё равно должен ставить лок на запись, которую он хочет обновить или проверить, до ее чтения (и разблокировать после переноса на холд). В примере из статьи автор решил делать все проверки в одном обработчике, там тоже надо блокировать записи до их чтения.
Ну так если они все хотят обновить например баланс одного счета, то в вашем подходе все кроме первого откатятся, потому что первый вклинился, и повторят все действия заново. Но сохранит данные опять только один, а другие опять откатятся, потому что второй вклинился. И так далее. В результате это займет столько же времени, сколько с ожиданием, только с лишней нагрузкой на сервер.
Если они меняют разные группы полей, то можно попробовать разделить одну сущность на две со связью один-к-одному.
Я согласен, что может быть в вашей архитектуре это подходящее решение, но я бы постарался сначала использовать другие решения из-за вероятности бесконечного вклинивания. А если вероятность отсутствия вклинивания высокая, то мне кажется и с локами при правильном подходе должно быть все нормально.
Я не говорю, что вы говорите, что локи не нужны. Вы говорите, что локи не нужны до чтения данных. Я говорю, что нужны.
А какой смысл записывать данные, которые некорректно рассчитаны?
В очередной раз повторяю - я не предлагаю блокировать данные на часы и дни.
Решение конфликтов это ручное действие. Если вы хотите разбирать и исправлять некорректные данные в миллионах строк в базе вручную, то конечно можно не использовать локи.