Идея с DeletedUsers и VIEW через UNION кажется простой и элегантной, но на практике влечёт за собой немало сложностей.
Если у пользователя есть связанные сущности — заказы, активности, сообщения — то при его удалении (и переносе в DeletedUsers) придётся переносить и их. Иначе нарушится целостность (внешние ключи, каскадные удаления), да и восстановить данные будет невозможно. Получается, нужно создавать DeletedOrders, DeletedMessages, DeletedWhatever — с теми же колонками и логикой. С ростом модели количество «зеркальных» таблиц быстро удваивает схему.
А самое главное — восстановление данных перестаёт быть надёжным. Например:
Не получится отличить заказы, удалённые пользователем вручную, от тех, что удалились каскадно;
Восстанавливать нужно уже кодом, не через триггеры, строго в порядке каскадного удаления;
Могут нарушиться уникальные индексы или внешние ключи при восстановлении;
Придётся придумывать идентификатор удаления наподобие request_id в микросервисах, чтобы связывать удалённые группы записей между собой. Сделать доступным такой request_id во всех триггерах удаления это нетривиальная задача;
В итоге «простое» удаление с переносом в Deleted* может превратиться в мину замедленного действия, потому что успех восстановления будет зависеть от конкретных данных в таблицах и связей между ними. Тестировать такие ситуации будет сложно.
При этом остаются и другие минусы: дублирование схем, необходимость синхронизации структуры таблиц, рост количества сущностей. Всё это усложняет сопровождение.
В большинстве случаев soft delete (is_deleted, deleted_at, deleted_by и пр.) — это куда более управляемый и безопасный подход.
Что вы будете делать, если вам понадобится атрибут, который ссылается на другую сущность в БД? К примеру, атрибут клиента, который ссылается на услугу или другого клиента. Судя по статье вы храните там только скалярные типы (в перспективе составные), но потребность в ссылках на другие сущности рано или поздно появится. Опять же к примеру, для ЮЛ нужно будет указывать ФЛ лицо руководителя или аффилированные ЮЛ. Если идентификаторы хранить в JSONB, то теряется целостность БД, а если городить таблицы связей для отдельных атрибутов, то теряется динамичность самих атрибутов.
Поиск по атрибутам в 40 сек. это явно не повод для гордости и сущее мучение для пользователей вашей системы. Я, когда столкнулся с подобной задачей, вынес поиск и листинг в отдельный поисковый индекс, а операции CRUD оставил за БД. Такой подход усложняет поддержание целостности данных в системе, но значительно сохраняет время её пользователям.
Первая строка в случае получения данных, вторая - закрытие успешного потока, третья - ошибка. В этом нет complete после каждого next-а, как в вашем первом примере и нет дубликации complete как в вашем втором примере. Откройте в конце концов документацию и прочитайте её внимательно.
Не Ангуляр с HttpClient вызывает дополнительный complete, это вы его вызываете подписавшись через объект с complete обработчиком. Вот вам альтернативный пример без дополнительного вызова complete stackblitz.com
У меня складывается впечатление, что вы пытаетесь критиковать стандартный оператор без попытки понять как он работает. Я предлагаю закончить эту дискуссию, потому что я получил ответ на свой первоначальный вопрос.
Вы каждое значение в диапазоне оборачиваете в отдельный поток, поэтому у вас получается 5 complete. Но зачем?! В обычном потоке complete прилетает один раз в конце по завершению потока. В остальном же поведение eitherify и materialize как по мне одинаковые. Ну а получать на выходе union тип или же notification это уже вкусовщина.
Идея с DeletedUsers и VIEW через UNION кажется простой и элегантной, но на практике влечёт за собой немало сложностей.
Если у пользователя есть связанные сущности — заказы, активности, сообщения — то при его удалении (и переносе в DeletedUsers) придётся переносить и их. Иначе нарушится целостность (внешние ключи, каскадные удаления), да и восстановить данные будет невозможно. Получается, нужно создавать DeletedOrders, DeletedMessages, DeletedWhatever — с теми же колонками и логикой. С ростом модели количество «зеркальных» таблиц быстро удваивает схему.
А самое главное — восстановление данных перестаёт быть надёжным. Например:
Не получится отличить заказы, удалённые пользователем вручную, от тех, что удалились каскадно;
Восстанавливать нужно уже кодом, не через триггеры, строго в порядке каскадного удаления;
Могут нарушиться уникальные индексы или внешние ключи при восстановлении;
Придётся придумывать идентификатор удаления наподобие request_id в микросервисах, чтобы связывать удалённые группы записей между собой. Сделать доступным такой request_id во всех триггерах удаления это нетривиальная задача;
В итоге «простое» удаление с переносом в Deleted* может превратиться в мину замедленного действия, потому что успех восстановления будет зависеть от конкретных данных в таблицах и связей между ними. Тестировать такие ситуации будет сложно.
При этом остаются и другие минусы: дублирование схем, необходимость синхронизации структуры таблиц, рост количества сущностей. Всё это усложняет сопровождение.
В большинстве случаев soft delete (is_deleted, deleted_at, deleted_by и пр.) — это куда более управляемый и безопасный подход.
Что вы будете делать, если вам понадобится атрибут, который ссылается на другую сущность в БД? К примеру, атрибут клиента, который ссылается на услугу или другого клиента. Судя по статье вы храните там только скалярные типы (в перспективе составные), но потребность в ссылках на другие сущности рано или поздно появится. Опять же к примеру, для ЮЛ нужно будет указывать ФЛ лицо руководителя или аффилированные ЮЛ. Если идентификаторы хранить в JSONB, то теряется целостность БД, а если городить таблицы связей для отдельных атрибутов, то теряется динамичность самих атрибутов.
Поиск по атрибутам в 40 сек. это явно не повод для гордости и сущее мучение для пользователей вашей системы. Я, когда столкнулся с подобной задачей, вынес поиск и листинг в отдельный поисковый индекс, а операции CRUD оставил за БД. Такой подход усложняет поддержание целостности данных в системе, но значительно сохраняет время её пользователям.
Первая строка в случае получения данных, вторая - закрытие успешного потока, третья - ошибка. В этом нет complete после каждого next-а, как в вашем первом примере и нет дубликации complete как в вашем втором примере. Откройте в конце концов документацию и прочитайте её внимательно.
Не Ангуляр с HttpClient вызывает дополнительный complete, это вы его вызываете подписавшись через объект с complete обработчиком. Вот вам альтернативный пример без дополнительного вызова complete stackblitz.com
У меня складывается впечатление, что вы пытаетесь критиковать стандартный оператор без попытки понять как он работает. Я предлагаю закончить эту дискуссию, потому что я получил ответ на свой первоначальный вопрос.
Вы каждое значение в диапазоне оборачиваете в отдельный поток, поэтому у вас получается 5 complete. Но зачем?! В обычном потоке complete прилетает один раз в конце по завершению потока. В остальном же поведение eitherify и materialize как по мне одинаковые. Ну а получать на выходе union тип или же notification это уже вкусовщина.
Подскажите, чем
either
отличается от оператора materialize()?Я заметил такую тенденцию в новостных постах и реже в корпоративных. В обычных же опыт пока что ценнее мнения.
На текущий момент, если названия и типы полей в обоих таблицах совпадают, то в результирующей Map-е они будут перемешены.
Точнее, значения из второй таблицы будут стоять и в первой и во второй модели.
Возможно статью стоит добавить в хаб Читальный зал.
Другими словами, десктопный дизайн это больше про UI, а мобильный про UX?
Вам ведь доступна программа всего курса? Какое соотношение между веб и мобильным дизайном?