Два года пишу соло без code review. Деградировал или нет?
в Positive Technologies был один коллега который иногда заглядывал в PR. не сеньор и не ментор - просто человек который мог написать "а зачем тут это?" и ты начинаешь думать. полгода там, потом ушёл в соло.
прошло примерно восемь месяцев прежде чем я по-настоящему осознал: никто больше не видит мой код кроме меня.
оговорка: я не сеньор, три года в Python из которых больше половины - соло и фриланс. кто в больших командах - у вас другая история, интересно будет послушать))
Как я это обнаружил
открыл проект который писал несколько месяцев назад - FastAPI-сервис под внутреннюю задачу. routes.py на 800 строк. 14 эндпойнтов в одном файле. логика вперемешку с SQL-запросами. пара функций которые делают три разные вещи каждая.
работало. работает до сих пор.
но если бы я прислал это на ревью - любой человек с нормальным стеком написал бы «ты вообще слышал про single responsibility?». никто не написал. просто некому.
это не катастрофа, но звоночек. начал думать что ещё я не замечаю.
Что я поставил вместо ревью
полной замены нет. но есть несколько вещей которые, по ощущению, ловят 60-70% того что поймало бы нормальное ревью.
mypy --strict. когда пишешь сам для себя, незаметно начинаешь экономить на аннотациях - и теряешь связность. mypy в строгом режиме больно в первый месяц, потом перестаёшь писать функции которые принимают «что попало» и возвращают «как получится». часть архитектурных косяков всплывает именно здесь - когда видишь что функция возвращает Optional[str] | dict | None и это всё технически легально.
pytest с нормальным покрытием. тесты я начал писать не потому что «так правильно», а потому что без ревью это единственное место где код вынужден отвечать на вопросы. граничные случаи которые коллега нашёл бы в ревью - pytest находит когда пишу тест и понимаю что сам не знаю что вернёт функция при пустом списке.
ruff + pre-commit. стиль не обсуждается, просто фиксируется автоматически и не лезет в коммит. мелочь - но без этого naming conventions уехали бы быстрее.
и личный ритуал который работает примерно на половину: перед мержем читаю diff как будто это чужой код. не своё. иногда комментирую вслух зачем это написано. звучит странно, иногда реально помогает поймать что-то очевидное))
Что не заменяется ничем
архитектурные решения. это самая больная точка.
routes.py на 800 строк я заметил сам - но спустя месяц. а сколько таких решений я не замечаю потому что «работает» и никто не смотрит?
в корпорации или хотя бы в небольшой команде - есть кто-то кто скажет «подожди, ты думал вынести это в отдельный сервис?» или «а Redis тут не уместен?». когда архитектурный выбор делается один раз в тишине - он просто фиксируется. обратная связь приходит только когда проект начинает болеть.
и ещё одно что инструменты не ловят: слепые пятна по стеку. в команде кто-то знает про PostgreSQL глубже, кто-то знает про Celery глубже - случайно узнаёшь что делал что-то неэффективно. соло - не узнаёшь пока сам не наткнёшься. или пока не полезешь в чаты с конкретным вопросом.
Честный итог
деградировал в чём-то, вырос в другом - и это честнее чем «всё под контролем».
хуже стало с архитектурой: слишком быстро принимаю решения без второго мнения. naming conventions иногда выглядят как писал один человек в трёх разных настроениях.
неожиданно лучше стало с тестами. когда код ревьюит только pytest - начинаешь писать тесты не для галочки, а потому что без них реально страшно. покрытие на текущих проектах выше чем было в Positive.
mypy тоже. научился наконец аннотировать нормально - просто потому что без этого код начал разъезжаться и инструмент сигналил.
так что: инструменты вытягивают технику. архитектуру и «а правильно ли ты вообще решаешь задачу» - ничего не вытягивает кроме другого человека.
интересно послушать у кого похожий опыт - соло, фриланс, небольшая команда. как держите качество кода без регулярного ревью? или не держите - и ничего страшного не произошло)
· 29.04
У меня к счастью память плохая, и я уже через 5 минут забуду, чо написал, поэтому если сразу не воспринимается легко, думаю, куда что вынести, но чаще всего всё стандартно, репозиторий, причем в виде модуля и функций, урл, модели, вьюха, сериализатор, будь он проклят, какие-нибудь функции помогающие, и какой-нибудь класс, недавно стал создавать dto ещё, функции с многими параметрами воспринимаются сложнее, тут принципиальная вещь чтобы вызывающий код думал о том, чтобы передавать правильные параметры, если dto надо собрать, ну будет значит ещё функция сборщик, получение данных и редактирование тоже обычно разделяется, если всё это сделать, а ещё сами функции лаконично писать по 1-3 действия на логической строчке, получается хорошо
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён
· 30.04
звучит как нормальная структура честно говоря - репозитории, dto, маленькие функции по 1-3 действия. именно всего этого и не было в том routes.py который я открыл) там функции делали "три вещи каждая" именно потому что я не заставлял себя думать о параметрах и ответственности - просто дописывал по месту
dto в питоне у меня обычно через pydantic-схемы, не выделяю явно, но по сути похоже. интересно что ты именно dto отдельно выделяешь - свои классы под это или тоже dataclass/pydantic?
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён
· 30.04
Namedtuple и dataclass
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён