Привет — спасибо за вводную. Прежде чем давать подробные советы, хорошо бы увидеть твою «краткую историю опыта» (я смогу точнее подсказывать, если знаю: на каких языках ты пишешь, в каких командах/проектах работал, какие типичные проблемы видишь). Но уже сейчас дам универсальный набор признаков, критериев и практических проверок, чтобы определять плохой ( «говно‑») код.
Коротко о принципе: «плохой код» — это не всегда просто «плохо написанный» с точки зрения синтаксиса. Это код, который трудно понимать, поддерживать, расширять, тестировать или который постоянно порождает баги/инциденты/технический долг. Ниже — признаки, объективные критерии, инструменты и чек‑лист для быстрой оценки.
Признаки плохого кода (поведенческие и видимые)
- Частые баги и срочные хотфиксы (hotfixes) в одних и тех же местах.
- Разработчики боятся менять код (боятся «взорвать» функциональность).
- Длинные PR‑ы, множество правок в ревью, конфликтующие изменения.
- Тесты медленные/хрупкие/отсутствуют; покрытие низкое.
- Много «костылей», TODO/ FIXME, закомментированного кода.
- Код «неформальный» — разные стили в одном проекте, нет единого соглашения.
- Документации нет или она устарела; сложнее понять поведение, чем читать код.
Структурные признаки «говно‑кода»
- Большие функции/методы (длиннее ~50–100 строк), глубокая вложенность (if/for внутри if/for).
- «God objects» / классы, выполняющие много ответственности.
- Сильная связанность модулей (high coupling) и слабая когезия (low cohesion).
- Повторяющийся код (copy‑paste).
- Длинные списки параметров и флаги boolean вместо отдельных функций.
- Глобальное состояние, скрытые сайд‑эффекты, скрытые зависимости.
- Магические числа и строки (magic constants) вместо именованных констант.
- Плохая обработка ошибок — подавление исключений, пустые catch, игнорируемые ошибки.
- Хрупкие API/контракты, при изменении мелкого параметра ломается куча мест.
Критерии и метрики (пороговые ориентиры)
- Цикломатическая сложность функции: >10 — подозрительно; >20 — плохо.
- Длина функции/метода: >50 строк — стоит пересмотреть; >100 — почти наверняка плохо.
- Размер класса/файла: >500–1000 строк — часто признак недостаточной декомпозиции.
- Дублирование кода: >10% — тревожный сигнал.
- Покрытие тестами: <50% — плохо; 50–80% — риск; >80% — нормально (зависит от контекста).
- Количество открытых багов/горячих исправлений по одному модулю: растущее число — признак проблем.
- Время на выполнение тестов/CI: очень долгое (>10–20 мин) — тормозит разработку и ведёт к вырождению качества.
Паттерны «говно‑кода» (конкретные антипаттерны)
- Spaghetti code — поток управления непонятен.
- Lava flow — ненужный старый код, который никто не решается удалить.
- Shotgun surgery — одно изменение требует правки многих файлов.
- Golden hammer / overengineering — чрезмерно сложное архитектурное решение там, где не нужно.
- Primitive obsession — широкое использование базовых типов вместо доменных абстракций.
Инструменты и автоматизация для обнаружения проблем
- Статический анализ: SonarQube, ESLint, Pylint, rubocop, clang‑tidy.
- Замер метрик: CodeClimate, Sonar, lizard (для сложность), radon (Python).
- Покрытие: coverage.py, Istanbul/nyc, dotCover.
- CI/CD: автоматические проверки стиля, тесты, линтеры, slow tests detection.
- Security scanners: Snyk, Dependabot, Bandit.
Практический чек‑лист для оценки кода (быстрая ревизия)
1. Сборка/запуск: проект собирается и запускается без хаков?
2. Тесты: есть ли тесты; можно ли их запускать локально; сколько времени они занимают; покрытие.
3. Структура: понятны ли модули/пакеты/контракты; нет ли файлов‑монстров.
4. Именования: имена функций/переменных говорящие? Нет ли аббревиатур?
5. Дублирование: легко ли найти похожий код в нескольких местах?
6. Сложность функций: есть ли сильно ветвящиеся места?
7. Ошибки: проверяется ли возможная ошибка; не игнорируются ли исключения?
8. Сайд‑эффекты: функции возвращают значения или меняют глобальное состояние?
9. Документация/комментарии: объясняют ли они «почему», а не «что»?
10. CI/linters: присутствуют ли автоматические проверки?
Как отличить «плохой, но работающий» от «плохого и опасного»
- Работает и редко меняется → может быть «грязным, но приемлемым» (высокий технический долг, но низкий риск).
- Часто ломается, мешает развитию → нужно рефакторить или переписать участки.
- Без тестов и с критическими ошибками/уязвимостями → опасно, требует немедленного вмешательства.
Что делать при обнаружении плохого кода
- Оценить влияние (как часто ломается, на сколько это важно для продукта).
- Собрать метрики и примеры реальных проблем.
- Небольшими шагами рефакторить (тестируй → рефакторь).
- Добавить автотесты и линтеры/CI перед рефакторингом.
- Разделять большие PR на мелкие изменения.
- Документировать контракт/поведение и добавить интеграционные тесты для критичных участков.
Примеры «красных флагов» в коде (быстрая проверка в код‑ревью)
- Метод с глубиной вложенности >4.
- Комментарий «FIXME» или «HACK» в логике, лежащий рядом с важной бизнес‑логикой.
- try/catch, где catch пустой или логирует «ignore».
- SQL/шаблоны, склеенные через конкатенацию строк (risk of injection).
- Использование глобальных переменных или singletons, передающих состояние по всему приложению.
Если хочешь — могу:
- Прислать короткий чек‑лист в виде задач на ревью (чтоб распечатать/использовать в PR).
- Посмотреть репозиторий/файл/фрагмент кода и дать конкретные замечания.
- Подготовить план рефакторинга для конкретного примера (маленькие безопасные шаги).
Напиши, пожалуйста, твою краткую историю опыта (языки, типы проектов, что тебя беспокоит) или пришли кусок кода/ссылку на репозиторий — и я дам более прицельный анализ.