Главный критерий хорошего кода
Хороший код — понятный и непрожорливый до ресурсов. Давайте поговорим об этом.
Время на понимание
Главный критерий хорошего кода — это время T, которое требуется не-автору, чтобы разобраться в коде. Причем разобраться не на уровне «вроде понятно», а достаточно хорошо, чтобы внести изменения и ничего не сломать.
Чем меньше T, тем лучше код.
Допустим, Нина и Витя реализовали одну и ту же фичу, а вы хотите ее доработать. Если разберетесь в коде Нины за 10 минут, а в коде Вити за 30 минут — код Нины лучше. Неважно, насколько у Вити чистая архитектура, функциональный подход, современный фреймворк и всякое такое.
T-метрика для начинающего и опытного программиста отличается. Поэтому имеет смысл ориентироваться на средний уровень коллег, которые будут работать с кодом. Если у вас в коллективе люди трудятся 10+ лет, и каждый написал по компилятору — даже очень сложный код будет иметь низкое T. Если у вас огромная текучка, а нанимают вчерашних студентов — код должен быть совершенно дубовым, чтобы T не зашкаливало.
Напрямую T не очень-то померяешь, поэтому часто отслеживают вторичные метрики, которые влияют на T:
- соответствие код-стайлу (
black
для питона), - «запашки» в коде (
pylint
,flake8
), - цикломатическую сложность (
mccabe
), - зависимости между модулями (
import-linter
).
Плюс код-ревью.
Количество ресурсов
Второй критерий хорошего кода — количество ресурсов R, которое он потребляет (времени, процессора, памяти, диска). Чем меньше R, тем лучше код.
Если Нина и Витя реализовали фичу с одинаковым T, но код Нины работает за O(n), а код Вити за O(n²) (при одинаковом потреблении прочих ресурсов) — код Нины лучше.
Насчет ситуации «пожертвовать понятностью ради скорости». Для каждой задачи есть порог потребления ресурсов R0, в который должно уложиться решение. Если R < R0, не надо ухудшать T ради дальнейшего сокращения R.
Если некритичный сервис обрабатывает запрос за 50мс — не надо переписывать его с питона на C, чтобы сократить время до 5мс. И так достаточно быстро.
Иногда, если ресурсы ограничены, или исходные данные большие — не получается достичь R < R0 без ухудшения T. Тогда действительно приходится жертвовать понятностью. Но:
- Это последний вариант, когда все прочие уже испробованы.
- Участки кода, где T↑ ради R↓, должны быть хорошо изолированы.
- Таких участков должно быть мало.
- Они должны быть подробно документированы.
Итого
Мнемоника хорошего кода:
T↓ R<R0
Оптимизируйте T, следите за R. Коллеги скажут вам спасибо.
Подписывайтесь на канал, чтобы не пропустить новые заметки 🚀