Перейти к основному содержимому

Культура кода — итоги

Разработчику Аналитику Тестировщику Архитектору Инженеру
Теория данных (раздел 3)

Структуры в коде — Структуры данных; persistence — ORM.

Кратко — что стоит унести из раздела "Культура кода". Если пункт кажется туманным — откройте указанную главу или оглавление. Базовая теория терминов (синтаксис, рефакторинг, исключения) — 4.02 Код, методы рефакторинга. Определения для самопроверки — в чек-листе.


FAQ — Часто задаваемые вопросы

Типичные ситуации на первой работе и в ревью — споры о стиле, "красный" линтер, перегруженные методы. Здесь — что делать на практике; формулировки для зачёта — в чек-листе.

Вопрос. Ревьюер просит переименовать половину переменных — это про культуру или про личный вкус?

Ответ. Если имена нарушают соглашения проекта или скрывают смысл (data, temp) — это культура. Если спор только о синониме (user vs client) при едином стиле — зафиксируйте правило в глоссарии или style guide, а не в каждом PR. Подробнее здесь — глава 1.

Вопрос. Первый PR упал на CI из‑за линтера — можно "попросить отключить правило"?

Ответ. Сначала прогоните форматтер и линтер локально — это часть культуры, а не "мелочь CI". Отключение правила без обсуждения команды создаёт прецедент. Если правило реально мешает — предложите изменение конфига в отдельном PR. Подробнее здесь — глава 1.

Вопрос. Коллега пишет иначе, чем в учебнике — кто прав?

Ответ. В команде важнее единый стиль репозитория, чем "идеальный" учебник. Смотрите .editorconfig, eslint/prettier, существующий код в том же модуле. Спор — повод обновить документ команды, а не переписывать чужой PR целиком. Подробнее здесь — глава 1.

Вопрос. Когда писать комментарий, а когда просто переименовать переменную?

Ответ. Если смысл виден из имени и структуры — переименуйте. Комментарий нужен для "почему" (бизнес-ограничение, баг API, legacy), а не для пересказа цикла for. Устаревший комментарий хуже отсутствующего. Подробнее здесь — глава 1.

Вопрос. PR вернули с формулировкой "слишком сложно" — с чего начать правку?

Ответ. Посмотрите цикломатическую сложность и вложенность: часто помогает ранний выход, вынос веток в именованные методы по смыслу (SRP), а не механическое "разбить на десять функций". Подробнее здесь — глава 2.

Вопрос. В legacy-коде везде "магические" числа — трогать при своей задаче?

Ответ. В рамках своей правки — локально вынесите константу с говорящим именем, если понимаете смысл. Массовый рефакторинг без тестов рискован; большой объём — отдельный PR или техдолг-тикет. Подробнее здесь — глава 1, глава 10.

Вопрос. Две функции почти одинаковые — обязательно выносить в общую?

Ответ. Не всегда: дублирование знания (одна формула в двух местах) опасно; два похожих блока ради читаемости в одном файле иногда допустимы. Спросите: изменится ли бизнес-правило в обоих местах одновременно? Подробнее здесь — глава 1.

Вопрос. Нужна фича, но код вокруг "грязный" — рефакторить в том же PR?

Ответ. Мелкая уборка на пути к фиче — нормально; большой рефакторинг лучше отдельным PR, чтобы ревью видело риск и откат был проще. Подробнее здесь — глава 10.

Вопрос. В проекте Singleton на каждый сервис — это нормально?

Ответ. Частый запах: скрытая глобальная связанность, сложные тесты, неочевидный порядок инициализации. Предпочитайте явную передачу зависимостей; если Singleton уже есть — не плодите новые без необходимости. Подробнее здесь — глава 9.

Вопрос. Метод на 80 строк из if (x != null) — как не утонуть?

Ответ. Сужайте контракт: fail fast на входе, явные типы вместо null где возможно, guard-clauses вместо пирамиды вложенности. Подробнее здесь — глава 8.

Вопрос. Sonar показывает "Critical", а тимлид говорит "мерджим" — кому верить?

Ответ. Метрики — повод для разговора, не автоматический запрет. Разберите конкретное замечание: реальный риск регресса или шум правила? Зелёный дашборд ради KPI без смысла — другая крайность. Подробнее здесь — глава 2, глава 10.

Вопрос. Старший прислал PR на 2500 строк — что делать ревьюеру?

Ответ. Вежливо попросите разбить или выделить логические коммиты; ориентир команды — порядка 200–400 строк. Большой diff повышает риск пропустить баг — это про безопасность, а не иерархию. Подробнее здесь — глава 10.

Вопрос. Имена только на английском, а домен на русском — путаница в голове.

Ответ. Заведите глоссарий: Order = заказ, Contract = договор. В коде — один язык (обычно английский в идентификаторах); в комментариях к неочевидным местам можно пояснить по-русски, если так принято в команде. Подробнее здесь — глава 1, глава 5.

Вопрос. formatOnSave ломает чужие отступы при merge — конфликт каждый раз.

Ответ. Команда должна иметь один форматтер в CI и .editorconfig; тогда diff только по смыслу. Локально отключайте formatOnSave только если конфиг ещё не внедрён — временная мера. Подробнее здесь — глава 1.

Вопрос. Боюсь задавать вопросы в ревью — кажется, что "тупой".

Ответ. Вопрос "рассмотрите…", "что если…" — нормальная часть психологически безопасного ревью. Если не поняли код через полгода — проблема читаемости, а не вашей квалификации. Подробнее здесь — глава 1.

Вопрос. "У меня работает" — а у ревьюера падает тест.

Ответ. Проверьте окружение: версия языка, переменные, порядок тестов, flaky. В PR приложите шаги воспроизведения; культура — когда CI на общем runner зелёный до merge. Подробнее здесь — глава 11.

Вопрос. Начальник просит "на будущее" абстракцию под три несуществующих клиента.

Ответ. Аргументируйте через YAGNI: лишний слой усложняет сопровождение без запроса. Компромисс — простой интерфейс, который легко расширить, когда появится второй реальный кейс. Подробнее здесь — глава 10.

Вопрос. Метод processOrder() делает всё подряд — с чего резать?

Ответ. По ответственностям: валидация, расчёт, сохранение, уведомление — отдельные компоненты или private-методы с говорящими именами. "Вынести в метод" без смены ответственности запутанность не лечит. Подробнее здесь — глава 2.

Вопрос. Модель — только поля и getters/setters, логика в сервисе на 500 строк.

Ответ. Это анемичная модель: доменная логика размазана. Там, где правило устойчиво ("скидка не больше X"), подумайте о методах сущности или value object. Подробнее здесь — глава 6.

Вопрос. Везде catch (Exception e) { } — как поднять тему без конфликта?

Ответ. Покажите пример, где глотание ошибки скрыло инцидент; предложите лог + проброс или узкий catch. Культура — явные сообщения и fail fast, а не "тихий" прод. Подробнее здесь — глава 12.

Вопрос. В коде три разных класса Customer, Client, User про одно и то же.

Ответ. Запах MAPPER: модель кода не совпадает с доменом. Согласуйте термин с аналитиком, постепенно сводите к одному понятию или явному маппингу на границе. Подробнее здесь — глава 5.

Вопрос. Цикломатическая сложность 14 — обязательно делить?

Ответ. Порядка 10 — ориентир для обсуждения, не закон. Если метод читается как рассказ и покрыт тестами — можно оставить; если ревьюер теряется — декомпозиция по смыслу. Подробнее здесь — глава 2.

Вопрос. Ревью висит три дня — это норма?

Ответ. Для потока команды — нет: задержка блокирует интеграцию. Договоритесь о SLA ревью (например, первый ответ в тот же день), уменьшайте размер PR. Подробнее здесь — глава 1.

Вопрос. Спор в ревью: "надо паттерн" vs "надо проще".

Ответ. Критерий — сопровождение через полгода: что проще объяснить новому человеку и безопаснее менять? Паттерн оправдан, если снимает повторяющуюся боль, а не для галочки в резюме. Подробнее здесь — глава 1, справочник.

Вопрос. Старый модуль без форматтера — при правке "причесывать" весь файл?

Ответ. Лучше только затронутые строки, иначе diff на сотни строк скроет суть. Отдельный PR "только форматting" по модулю — если команда решила навести порядок. Подробнее здесь — глава 10.

Вопрос. JSDoc написал, а подсказки в IDE не появились.

Ответ. Проверьте синтаксис docstring, экспорт символа и настройки языка в IDE. Документация публичного API — для тех, кто вызывает модуль извне. Подробнее здесь — глава 1.

Вопрос. Flaky-тест блокирует merge — чинить тест или фичу?

Ответ. Flaky опаснее отсутствия теста: команда перестаёт верить CI. Сначала стабилизируйте тест (время, порядок, моки), потом merge. Подробнее здесь — глава 11.

Вопрос. Вижу техдолг — тикет или чинить "по ходу"?

Ответ. Мелочь на пути задачи — можно сразу; системный долг — тикет с контекстом и оценкой риска, иначе он никогда не попадёт в спринт. Подробнее здесь — глава 10.

Вопрос. Хочу писать "красиво" через LINQ/map, коллеги просят "проще for".

Ответ. Декларативный стиль уместен, когда намерение читается; если команда тонет в цепочках — упростите или добавьте промежуточные имена. Единство важнее личной эстетики. Подробнее здесь — глава 14.

Вопрос. Мутирую объект "для скорости" — когда это плохая идея?

Ответ. Когда объект разделяется между потоками, слоями или тестами — побочные эффекты дают Heisenbugs. Локальная мутация в одном методе часто нормальна; публичные сеттеры "на всё" — повод насторожиться. Подробнее здесь — глава 7.


FAQ — Поисковые запросы

Краткие ответы на формулировки, которые часто вводят в Google и Yandex. Полные разборы — в статьях раздела по ссылкам ниже.

Вопрос. Что такое чистый код (clean code)?

Ответ. Код, который легко читать и менять: понятные имена, простая структура, явные контракты, минимум сюрпризов для коллеги через полгода. Подробнее здесь — культура написания кода.

Вопрос. Что такое цикломатическая сложность и какая норма?

Ответ. Метрика числа независимых путей в функции; рост — сигнал упростить или разбить. Ориентир для повседневного кода — порядка до 10. Подробнее здесь — цикломатическая сложность.

Вопрос. Как правильно называть переменные в Python, Java, C#?

Ответ. Следуйте стилю языка и проекта (snake_case, camelCase, PascalCase); имя отвечает на "что это" и "в каких единицах", не data/temp. Подробнее здесь — именование и стиль.

Вопрос. Чем camelCase отличается от snake_case и PascalCase?

Ответ. camelCasemyVariable (Java, JS); PascalCaseMyClass; snake_casemy_variable (Python, SQL). Главное — единообразие в репозитории. Подробнее здесь — глава 1.

Вопрос. Что такое code review (код-ревью) и зачем оно нужно?

Ответ. Совместная проверка изменений до merge: риски, читаемость, тесты, а не "перепиши как я люблю". Снижает дефекты и распространяет знания. Подробнее здесь — глава 1.

Вопрос. Зачем нужен линтер (ESLint, Pylint, SonarQube)?

Ответ. Автоматически ловит стиль, запахи и частые ошибки, чтобы в ревью не спорить о пробелах. Запускают локально и в CI. Подробнее здесь — глава 1.

Вопрос. Что такое технический долг (tech debt) в коде?

Ответ. Упрощения в прошлом, за которые платите временем и риском при каждой следующей правке. Лечится планом, тестами и малыми PR. Подробнее здесь — YAGNI и техдолг.

Вопрос. Принцип DRY — что значит Don't Repeat Yourself?

Ответ. Не дублировать знание (одно правило в нескольких местах); механическое копирование двух похожих блоков ради читаемости иногда допустимо. Подробнее здесь — глава 1.

Вопрос. SOLID принципы простыми словами для начинающих.

Ответ. Пять правил модульности: одна ответственность, расширение без ломки, подстановка типов, узкие интерфейсы, зависимость от абстракций. Подробнее здесь — глава 1, чек-лист.

Вопрос. Что такое рефакторинг кода и когда его делать?

Ответ. Изменение структуры без смены поведения; безопасно после теста или в маленьких шагах. Отдельно от фичи — в своём PR. Подробнее здесь — глава 10, глава 2.

Вопрос. Как писать комментарии в коде — примеры и правила.

Ответ. Пишите почему и про ограничения (legacy, закон, баг API), а не пересказ цикла. Устаревший комментарий хуже отсутствующего. Подробнее здесь — глава 1.

Вопрос. Что такое магическое число (magic number) в программировании?

Ответ. Число или строка в коде без объяснения смысла (86400, 9999). Заменяйте именованной константой с доменным именем. Подробнее здесь — глава 1, глава 8.

Вопрос. Prettier и ESLint — в чём разница?

Ответ. Prettier — форматирование (отступы, кавычки); ESLint — правила качества и ошибок. Обычно используют оба + CI. Подробнее здесь — глава 1.

Вопрос. Что такое god object и антипаттерн spaghetti code?

Ответ. God object — класс "на всё"; spaghetti — запутанные зависимости. Лечение — декомпозиция по ответственности и явные границы. Подробнее здесь — глобалы и связанность, сложность.

Вопрос. YAGNI — что это и примеры?

Ответ. You Aren't Gonna Need It — не стройте задел "на будущее" без запроса; меньше кода — меньше сопровождения. Подробнее здесь — глава 10.

Вопрос. Как улучшить читаемость кода junior разработчику?

Ответ. Имена вместо комментариев, короткие функции, ранний выход, форматтер, ревью с вопросами, а не приказами. Подробнее здесь — глава 1, справочник симптомов.

Вопрос. Сколько строк кода должно быть в одной функции?

Ответ. Жёсткого лимита нет; ориентир — одна логическая операция и цикломатическая сложность порядка до 10. Длиннее — повод разбить по смыслу. Подробнее здесь — глава 2.

Вопрос. Что такое self-documenting code (самодокументируемый код)?

Ответ. Когда имена и структура объясняют намерение без комментария; не отменяет документирование бизнес-контекста. Подробнее здесь — глава 1.

Вопрос. Почему Singleton считают плохим паттерном?

Ответ. Скрытая глобальная зависимость, сложные тесты, неявный порядок инициализации. Предпочитайте явную инъекцию зависимостей. Подробнее здесь — глава 9.

Вопрос. Value object — что это в доменной модели?

Ответ. Объект-значение без identity (деньги, email, диапазон дат) вместо "голого" string/int. Подробнее здесь — анемичные модели и VO.

Вопрос. Как избежать NullPointerException и проверок на null?

Ответ. Fail fast на входе, явные типы (Optional, nullable-аннотации), контракты API, меньше "тройных" if. Подробнее здесь — null и контракты.

Вопрос. Code smell — что такое "запах кода"?

Ответ. Признак возможной проблемы (длинный метод, дубли, feature envy), а не ошибка сама по себе. Повод для рефакторинга или обсуждения. Подробнее здесь — глава 2, справочник.

Вопрос. EditorConfig — зачем нужен в команде?

Ответ. Единые отступы, кодировка, конец строки во всех IDE; основа вместе с форматтером в репозитории. Подробнее здесь — глава 1.

Вопрос. Как именовать boolean переменные — is, has, can?

Ответ. Префикс is/has/can/should + утверждение: isActive, hasPermission. Избегайте flag, status без смысла. Подробнее здесь — глава 1.


Что запомнить

Раздел собран вокруг простой идеи: код — это средство общения команды во времени. Ниже — сжатые выводы; подробности и примеры — в основной статье и в материале про цикломатическую сложность.


Что такое культура кода

  • Договорённости, которые команда реально соблюдает (не PDF в шкафу).
  • Инструменты, которые снимают споры о пробелах и стиле (форматтер, линтер, editorconfig).
  • Ревью, где обсуждают риски и читаемость, а не "перепиши как я люблю".

Именование и стиль

  1. Следуйте соглашениям языка и проекта (camelCase, snake_case, PascalCase — не "как нравится").
  2. Имя отвечает на вопросы — что это, зачем, в каких единицах (weeklyPayRateRub, не data).
  3. Короткие имена (i, j) уместны только при короткой области видимости (типичный цикл на 5–10 строк).
  4. Аббревиатуры — только если они общеприняты в домене (id, url) или зафиксированы в глоссарии.
  5. Форматирование — зона автоматики; в PR не тратьте время на ручное выравнивание.

Комментарии и документация

  1. Самодокументируемый код — осмысленные имена и явная структура; не замена бизнес-контексту.
  2. Комментарий пишут про почему и про ограничения, которые не видны из кода (legacy, регуляторика, баг API).
  3. Не дублируйте в комментарии то, что уже сказано циклом for или именем метода.
  4. Устаревший комментарий хуже отсутствующего — обновляйте вместе с кодом в том же PR.
  5. XML-doc / JSDoc / docstring — для публичного API и подсказок IDE, не для каждой строки.

Сложность и структура

  1. Цикломатическая сложность — про число независимых путей в функции; рост — сигнал упростить или разбить.
  2. Ориентир для повседневного кода: держать методы в зоне примерно до 10; выше — осознанное обсуждение в ревью.
  3. "Вынести в метод" без смены ответственности не лечит запутанность — лечит декомпозиция по смыслу (SRP, политики, данные).
  4. KISS — проще решение, которое закрывает задачу сейчас; YAGNI — не строить задел "на будущее" без запроса.
  5. DRY — не копировать знание; дублирование ради читаемости в одном месте иногда допустимо.

MAPPER и модель

  1. Код описывает часть реальности; лишние классы и примитивы — запах (MAPPER).
  2. Value object вместо string/int там, где в домене есть понятие (статья 6).
  3. Меньше null и if — явные состояния и контракты (статья 8).
  4. Глобалы и Singleton — скрытая связанность (статья 9).
  5. Рефакторинг отдельно от фичи в PR (статья 10).

Команда и ревью

  1. Размер PR 200–400 строк (ориентир) — проще ревью и меньше регрессий.
  2. В ревью — вопросы и предложения ("рассмотрите…", "что если…"), не ярлыки про человека.
  3. Психологическая безопасность: ошибки обсуждают как улучшение процесса, не как "вину".
  4. Метрики (Sonar, complexity) — повод для диалога, не для отчёта "зелёный ради галочки".

Три правила на каждый день

  1. Перед push — прогон форматтера/линтера и самопроверка по чек-листу.
  2. В ревью — ищите риск для сопровождения, а не стиль, который уже ловит tooling.
  3. При сомнении — выберите вариант, который проще объяснить коллеге через полгода.

Дальше: Чек-лист самопроверки — 50 вопросов для закрепления; справочник тем — поиск по симптому.


Куда идти дальше

Полный маршрут — на странице о разделе.