Упрощать корпоративный шпионаж для конкурентов, как мне кажется, не стоит
Плюс это дополнительная защита
Вдруг окажется, что ваш эндпоинт GET /orders/<ID> не защищен и любой может получить заказ. С UUID такая бреж в безопасности будет, конечно, критичной, но заметно менее критичной, чем с Serial
Но множественное число наталкиваем в принципе на ошибки. Не всё слова тривиально плюрализируются (parking, aircraft, like), а также не совсем очевидно что делать с таблицами типа user_subscription -users_subscriptions? А если у юзера только одна подписка может быть, то кто-то может додуматься и сделать users_subscrition
Большой плюс единственного числа - оно просто проще (за исключением резервированных таблиц)
В одной компании мы отключали FK просто чтобы меньше БД нагружать (они всё-таки не бесплатные)
В другой FK были в локальных таблицах, но между кластерами БДшек не было FK, потому что дорого и это были разные отделы, не факт что у них вообще постгрес была:)
В общем случае их лучше добавлять, но часто бывают ситуации, когда они мешают или просто невозможны
Скажем часть БДшки для архивов вы выгружаем в холодное хранилище в S3, из-за чего у каких-то таблиц может быть нарушение FK
Или ещё более простая ситуация - делаем интернет магазин и шардируем по доменам - таблица пользователей в одном кластере, таблица покупок и корзины - в другом. А меж кластерами делать FK - точно не стоит
Геттер это скорее про DTO и сам класс/структуру. Скажем есть type User struct {Birthday time.Time}, мы может сделать геттер Age(), который вернёт возраст юзера исходя из даты рождения
А GetAll - это метод похода в БДшку, он не реализует какого-либо доступа до класса, от которого вызывается
Я даже больше скажу — в корпорациях типа гугла, яндекса и тд, таблица с юзерами будет находится в отдельном датацентре во владении отдельной команды и у нас, как разработчиков сервиса заказов вообще не будет к ней доступа, только приватная рестапишка и может кафка с ивентами апдейтов пользователей
И в таком случае чисто технически FK невозможно будет использовать
FK не даст гарантии, что юзер не забанен, не отключен или что-то еще, поэтому нужно делать в транзакции:
begin;
select * from user where id = ? for update;
insert into order ...;
commit;
(Либо уместить в 1 SQL запрос)
Конечно, если у вас система простая, без soft-delete, можно обойтись одними FK. Но в больших и нагруженных системах крайне часто FK не дает достаточных гарантий и все равно нужно делать проверки на беке
Кореютилс помимо перехода на раст ещё пытаются в оптимизацию, видел недавно баг репорт, что sort некорректно работает, но зато раз в 5 быстрее оригинала:)
Плюс в том, что беку не нужно думать о конкретных эндпоинтах, просто выдать доступ ко всему
Но есть минус - фронтендер может не предупредить о том, что меняет какой-то запрос. И может получится, что он поменяет запрос на что-то, что будет тригеррит Н+1 проблему
По мне graphql слишком специфичная штука, чаще рест удобнее
Asyncio корректнее сравнивать с тредами, а не синхронностью
В питоне requests спокойно может работать в 10 потоков (паралельно) через concurrency.threads.ThreadPoolExecutor, без необходимости использования asyncio
Фишка asyncio в том, что он использует корутины, а они дешевле тредов, поэтому лучше использовать их
Сама БДшка будет буквально такой же, что и при FK, просто без FK.
Разница будет только на стороне бекенда и только на операции удаления. Если вы не хотите использовать soft-delete, то на удаление статьи нужно будет сделать `delete from post_change where post_id = ?` (post_change - таблица дат). А после `delete from post where id = ?`. В остальном архитектура будет такой же, как и с FK
Акцент у статьи я пытался чуть другим сделать — FK не уменьшает ошибки, FK не дает каких-либо гарантий, которые уже не были бы даны нормальным бэкендом.
То есть реально ПД нужны исключительно тогда и в тех решениях, когда их не требуется удалять даже при наличии запроса от физического лица.
Раскройте, пожалуйста, мысль не понял...
Если мы говорим про воображаемый интернет-магазин, то ПД нужны для авторизации (телефон) и отправки чека (почта).
После удаления аккаунта юзера, очевидно, эти ПД нам больше и не нужны, потому что юзер не будет авторизовываться и ему не будут отправляться чеки об покупках.
В БД останется только его айдишник, по нему не получится связать его с реальным человеком
Да, безусловно, и их тоже нужно валидировать если вы не доверяете источнику!
Например, у заказа может быть shop_id и delivery_id. Если юзер отправляет запрос вида `POST /order {"shopId": ..., "deliveryId": ..., "cartItems": []}` вам же все равно нужно сходить в БД и проверить, что такой shop существует, что он может принимать заказы, что в нем есть указанные товары.
Вставить в БДшку поля без проверки можно только в случае, если мы доверяем отправителю, например, в приватной апишке между сервисами.
Так вам в любом случае нужно сходить в БД, чтобы проверить, что юзер авторизован и имеет право сделать заказ
Если вы никак не верифицируете айдишники в системе, то злоумышленик может просто насоздавать заказов на чужих юзеров? Вам же так и так нужно верифицировать, что инпут в систему корректен
Почему не бывает дополнительных защит? Я только что привел пример дополнительной защиты
Так я и не решаю проблему безопасности через гуиды, а строю дополнительную защиту
Очевидно, что приватные данные должны быть закрыты, но кто-то из разрабов или девопсов может накосячить и благодаря гуидам урон от косяка будет меньше
Упрощать корпоративный шпионаж для конкурентов, как мне кажется, не стоит
Плюс это дополнительная защита
Вдруг окажется, что ваш эндпоинт GET /orders/<ID> не защищен и любой может получить заказ. С UUID такая бреж в безопасности будет, конечно, критичной, но заметно менее критичной, чем с Serial
Но множественное число наталкиваем в принципе на ошибки. Не всё слова тривиально плюрализируются (parking, aircraft, like), а также не совсем очевидно что делать с таблицами типа user_subscription -users_subscriptions? А если у юзера только одна подписка может быть, то кто-то может додуматься и сделать users_subscrition
Большой плюс единственного числа - оно просто проще (за исключением резервированных таблиц)
В одной компании мы отключали FK просто чтобы меньше БД нагружать (они всё-таки не бесплатные)
В другой FK были в локальных таблицах, но между кластерами БДшек не было FK, потому что дорого и это были разные отделы, не факт что у них вообще постгрес была:)
Внешние ключи спорная тема
В общем случае их лучше добавлять, но часто бывают ситуации, когда они мешают или просто невозможны
Скажем часть БДшки для архивов вы выгружаем в холодное хранилище в S3, из-за чего у каких-то таблиц может быть нарушение FK
Или ещё более простая ситуация - делаем интернет магазин и шардируем по доменам - таблица пользователей в одном кластере, таблица покупок и корзины - в другом. А меж кластерами делать FK - точно не стоит
Мне кажется, что единственное число всегда лучше просто потому что далеко не у всех разрабов С2 по английскому:)
Стандарт языка описывает геттер, а не все методы и функции. GetAll, ListUsers, ListBooks это не гетеры
Я бы поспорил
Геттер это скорее про DTO и сам класс/структуру. Скажем есть type User struct {Birthday time.Time}, мы может сделать геттер Age(), который вернёт возраст юзера исходя из даты рождения
А GetAll - это метод похода в БДшку, он не реализует какого-либо доступа до класса, от которого вызывается
Я даже больше скажу — в корпорациях типа гугла, яндекса и тд, таблица с юзерами будет находится в отдельном датацентре во владении отдельной команды и у нас, как разработчиков сервиса заказов вообще не будет к ней доступа, только приватная рестапишка и может кафка с ивентами апдейтов пользователей
И в таком случае чисто технически FK невозможно будет использовать
Я про это как раз и писал в статье...
FK не даст гарантии, что юзер не забанен, не отключен или что-то еще, поэтому нужно делать в транзакции:
(Либо уместить в 1 SQL запрос)
Конечно, если у вас система простая, без soft-delete, можно обойтись одними FK. Но в больших и нагруженных системах крайне часто FK не дает достаточных гарантий и все равно нужно делать проверки на беке
Кореютилс помимо перехода на раст ещё пытаются в оптимизацию, видел недавно баг репорт, что sort некорректно работает, но зато раз в 5 быстрее оригинала:)
Гибкость graphql это сразу и плюс и минус
Плюс в том, что беку не нужно думать о конкретных эндпоинтах, просто выдать доступ ко всему
Но есть минус - фронтендер может не предупредить о том, что меняет какой-то запрос. И может получится, что он поменяет запрос на что-то, что будет тригеррит Н+1 проблему
По мне graphql слишком специфичная штука, чаще рест удобнее
Asyncio корректнее сравнивать с тредами, а не синхронностью
В питоне requests спокойно может работать в 10 потоков (паралельно) через concurrency.threads.ThreadPoolExecutor, без необходимости использования asyncio
Фишка asyncio в том, что он использует корутины, а они дешевле тредов, поэтому лучше использовать их
Крутая статья!
У меня получилось что-то наоборот:)
В комментариях автору, как мне кажется, корректно ответили, что не всегда мягкое удаление не нужно и его аргументы можно обойти.
Да, согласен.
Как доп. защиту FK можно использовать.
Сама БДшка будет буквально такой же, что и при FK, просто без FK.
Разница будет только на стороне бекенда и только на операции удаления. Если вы не хотите использовать soft-delete, то на удаление статьи нужно будет сделать `delete from post_change where post_id = ?` (post_change - таблица дат). А после `delete from post where id = ?`.
В остальном архитектура будет такой же, как и с FK
Акцент у статьи я пытался чуть другим сделать — FK не уменьшает ошибки, FK не дает каких-либо гарантий, которые уже не были бы даны нормальным бэкендом.
Раскройте, пожалуйста, мысль не понял...
Если мы говорим про воображаемый интернет-магазин, то ПД нужны для авторизации (телефон) и отправки чека (почта).
После удаления аккаунта юзера, очевидно, эти ПД нам больше и не нужны, потому что юзер не будет авторизовываться и ему не будут отправляться чеки об покупках.
В БД останется только его айдишник, по нему не получится связать его с реальным человеком
Да, безусловно, и их тоже нужно валидировать если вы не доверяете источнику!
Например, у заказа может быть shop_id и delivery_id. Если юзер отправляет запрос вида `POST /order {"shopId": ..., "deliveryId": ..., "cartItems": []}` вам же все равно нужно сходить в БД и проверить, что такой shop существует, что он может принимать заказы, что в нем есть указанные товары.
Вставить в БДшку поля без проверки можно только в случае, если мы доверяем отправителю, например, в приватной апишке между сервисами.
Так вам в любом случае нужно сходить в БД, чтобы проверить, что юзер авторизован и имеет право сделать заказ
Если вы никак не верифицируете айдишники в системе, то злоумышленик может просто насоздавать заказов на чужих юзеров?
Вам же так и так нужно верифицировать, что инпут в систему корректен