diff --git a/best_practices.md b/best_practices.md new file mode 100644 index 0000000..801cac2 --- /dev/null +++ b/best_practices.md @@ -0,0 +1,64 @@ +# Best Practices + + + +## Correctness & error handling +- Обробляй помилки явно; не ковтай винятки порожнім `catch`/`except` і не логуй-та-продовжуй там, де стан уже невалідний. +- Не втрачай і не «плавай» проміси/async: кожен асинхронний виклик має бути awaited або свідомо запущений з обробкою помилок. +- Перевіряй граничні випадки: null/undefined/порожні колекції, нуль, відʼємні числа, переповнення, часові зони, локаль. +- Не покладайся на порядок або істинність там, де можливий `0`, `""`, `false` як валідні значення. +- Помилки — з контекстом (що саме впало і з якими вхідними), без «німих» перезакидань. + +## Security +- Уся валідація й авторизація — на серверній межі; клієнтським даним не довіряй ніколи. +- Захищені ендпоінти завжди перевіряють автентифікацію та права доступу перед виконанням. +- Параметризуй запити до БД; ніякої конкатенації користувацького вводу в SQL/шелл/шляхи (SQLi, command injection, path traversal). +- Екрануй/санітизуй вивід у HTML/шаблони (XSS); не рендери сирий користувацький HTML. +- Жодних секретів у коді, логах чи повідомленнях про помилки; лише з env/секрет-сховища. +- Не віддавай у відповідях стектрейси й внутрішні деталі; клієнту — узагальнена помилка, деталі — в лог. +- Вебхуки та зовнішні колбеки — перевірка підпису на сирому тілі запиту до парсингу. +- Публічні/дорогі ендпоінти — rate limiting і ліміти розміру вводу. + +## API & boundaries +- Тримай межі модулів: доменна логіка не залежить від транспорту (HTTP/UI); не тягни інфраструктуру в домен. +- Публічні контракти (API/типи, що експортуються) змінюй сумісно; ламкі зміни — свідомо й задокументовано. +- Валідуй і нормалізуй вхід на межі; далі всередині працюй уже з довіреними типами. + +## Data & persistence +- Операції, що мають бути атомарними, — в одній транзакції; не лишай частково записаний стан. +- Остерігайся N+1: батчі/join замість запитів у циклі. +- Міграції даних — оборотні або з чітким планом відкату; не видаляй колонки/дані без бекапу. +- Гроші й точні величини — цілочисельні/decimal, ніколи float; округлення — єдиною узгодженою функцією. + +## Concurrency & async +- Уникай спільного мутабельного стану без синхронізації; бійся гонок і фантомних читань. +- Зовнішні виклики — з таймаутом; повторні спроби — ідемпотентні та з backoff. +- Звільняй ресурси (зʼєднання, файли, локи) детермінованим шляхом навіть на помилках. + +## Tests +- Нова поведінка й фікси багів супроводжуються тестами, що падали б до зміни. +- Тестуй граничні й негативні сценарії, а не лише «щасливий шлях». +- Тести детерміновані: без залежності від реального часу, мережі, порядку виконання чи випадковості. + +## Performance +- Не роби зайвої роботи в гарячому шляху; виноси інваріантні обчислення з циклів. +- Пильнуй складність на великих входах (уникай прихованих O(n²) на списках/вкладених циклах). +- Кешуй свідомо, з чіткою інвалідацією; не кешуй чутливе чи per-user під спільним ключем. + +## Maintainability +- Імена відображають намір; уникай абревіатур і «магічних» констант — виноси в іменовані значення. +- Прибирай мертвий код, закоментовані блоки й невикористані змінні/імпорти. +- Тримай функції сфокусованими; глибоку вкладеність спрощуй ранніми поверненнями. +- Не дублюй логіку: спільне — у переви́користовуваний хелпер, а не copy-paste. +- Публічну поведінку, що не очевидна з коду, коротко документуй. + +## Dependencies & config +- Не додавай важку залежність заради дрібниці, яку робить стандартна бібліотека. +- Конфіг і фіче-флаги — з середовища, з безпечними дефолтами; поведінка не залежить від хардкоду оточення. +- Закріплюй версії залежностей; уникай неявних major-апгрейдів у звичайному PR.