Любой программист, вне зависимости от уровня, когда-то сталкивался с этим. Ты садишься за проект, полный планов и идей, предвкушаешь, как создашь нечто совершенное, но… проходит час, второй, а на экране только десяток папок, пара заглушек и файл README.md. И вот уже начинаешь возвращаться к документации в поисках “правильной” структуры проекта или подсматриваешь, как сделали другие.
Примерно то же самое происходит, когда ты работаешь в команде: собрания перетекают в бесконечное обсуждение архитектуры, абстракций и фреймворков. Идеи летят кометами, все соглашаются, что “всё должно быть как надо”, но реальная работа — застопорилась. Потому что команда вместе с тобой подсознательно ждет чего-то: идеального старта.
Синдром идеального старта — не просто миф, а настоящая преграда для продуктивной разработки. В этой статье мы поговорим о том, почему ждать «идеальности» — значит тормозить, как такой подход мешает развитию, и что с этим можно сделать.
Зачем мы ждём идеального старта?
Давайте начистоту. Инженерный подход прививает большинству программистов стремление к «чистоте» и «вечному». Важно, чтобы проект был построен на устойчивом фундаменте, который можно будет развивать много лет. Но эта стремительность к «безупречности» часто оборачивается довольно токсичной привычкой откладывать реальные действия, пока не будет найдено «идеальное решение».
Проблема в том, что идеальное, как правило, недостижимо. Вот почему:
-
Мир меняется быстрее, чем мы пишем код. Пока вы анализируете новый фреймворк или паттерн, релизнется его следующая версия, ваше окружение изменится, а требования проекта могут вообще перерасти из веб-приложения в мобильное.
-
Мы не можем всё предусмотреть. На старте проекта кажется, что нужно принять сразу сотню решений: будет ли разделение на микросервисы? Поддерживать ли monorepo? Какими должны быть слои абстракции? Но в большинстве случаев это приводит к параличу. Пока вы думаете, реальная работа замедляется.
-
Боимся «испачкать» кодовую базу. Привычка к чистому коду иногда мешает. Мы так сильно отталкиваемся от идеи, что код должен быть понятным, тестированным и стильным прямо с первой строчки, что боимся писать что-то, что выглядит «не идеальным».
Почему важно перестать ждать идеального старта?
В программировании, как и в жизни, самое важное — движение. Делать маленькие изменения быстрее и поступательно гораздо эффективнее, чем тратить дни на создание теоретически идеальной структуры или идеологически верной архитектуры.
Вот несколько причин:
-
Решения всегда меняются по мере роста проекта. На стадии планирования вы даже не представляете, какие реальные вызовы ждут позже. Проект определяет архитектуру, а не наоборот.
-
Рабочий прототип важнее абстрактных концепций. В большинстве случаев сделать что-то работающее, пусть даже далеко от совершенства, — это уже половина пути. Реальный код порождает не только движение вперёд, но и обратную связь.
-
Процесс — это опыт, который впоследствии улучшит систему. Даже если начальный код будет «грязным», путь проложен. А рефакторинг (да-да, любимое слово) — верный друг любого разработчика.
-
Польза для бизнеса. Важно помнить, что деньги зарабатываются не за «идеальный код». Заказчику, продукту или пользователю важно, чтобы это работало. Код всегда можно улучшить позже, а вот время вернуть не получится.
История с попыткой «идеального начала»
n-нное количество лет назад мне воочию пришлось наблюдать такие стремления к «правильной архитектуре со старта». Это была разработка приложения для внутреннего использования: большой дашборд для анализа данных, интерактивные таблицы, графики, интеграция с несколькими API. Задача амбициозная, но на старте всё шло довольно быстро: дизайн-систему выбрали, фреймворки обсудили, даже базовую структуру за несколько дней собрали.
А дальше понеслась… Команда, уставшая от поддержки «старых» проектов, проникнувшаяся идеей, что старый проект плохой потому что
-
он старый и вообще legacy
-
на рефакторинг времени бизнес не дает, поэтому всё там плохо
пустилась во все тяжкие в стремлении «сделать круто», современно и далее по тексту.
Казалось, что решение любой задачи должно быть сразу на высшем уровне: например, чтобы каждое взаимодействие с API было строго типизированным, универсализированным, а обработчики ошибок настроены по всем лучшим практикам. Начали выстраивать кастомный механизм взаимодействия со всеми сервисами, на тот случай, если их API когда-нибудь изменится, рисовали зубодробительные ролевые модели и логику доступов… и что в итоге?
Через месяц у нас не было вообще ничего полезного, кроме горы абстракций, десятков интерфейсов и базового логирования. Как в том бородатом меме:
У нас было 35 строчек кода, 2 цикла, 2 конструкции try/catch для безопасности, 4 условия if/else и целое множество отступов и костылей. Не то чтобы это был необходимый запас для решения этого задания. Но если начал писать г*внокод, становится трудно остановиться. Единственное что вызывало у меня опасение была рекурсия. Нет ничего более запутанного чем рекурсия. Я знал что рано или поздно мы перейдем и на эту дрянь.
В конце концов всё пришлось просто выбросить и начать заново, максимально упростив подход. Мы сосредоточились на базовых сценариях: нужно ли сразу заморачиваться с универсальным API-модулем? Нет. Создаём обычные функции для каждого сервиса. Требуется ли нам с первого дня универсальная абстракция для обработки данных с фронта? Нет. И т.д. и т.п. per rectum ad astra, как говорят в русских селениях.
Мы быстро собрали рабочий прототип, который можно было показывать бизнесу. И знаете что? Многие добавленные фичи, которые мы так хотели реализовать в начале, просто не понадобились вовсе. Если бы мы их сразу сделали, они были бы пустой тратой времени.
Парадокс идеального старта
Самое интересное в гонке за идеальным началом работы в том, что в реальной жизни он никогда не наступает. Вот пара причин, почему это происходит:
-
Идеальная архитектура рождается только из практики. Пока проект живёт только в голове, у вас нет полной картины — лишь гипотезы, которые не прошли проверку практикой. Реальные требования бизнеса или пользователей ломают ваши планы.
-
Фреймворки и технологии устаревают быстрее вашей разработки. Не стоит ожидать, что выбор прошлого года на старте сильно поможет вам через год.
-
Всё становится понятнее после первого хаоса. Когда проект уже заработал в минимальном виде, вы простыми глазами видите, что действительно нужно улучшить.
Как перестать ждать идеального старта?
1. Разделяй задачи — дроби их до безобразия
Когда вы сидите перед пустым проектом с глобальной целью «создать что-то большое», эта цель просто подавляет. Решение — дробить задачи так мелко, как только возможно, до тех пор, пока они не сделаются совершенно очевидными.
Пример:
Вместо глобальной «Настроить архитектуру API» попробуйте начать с «Создать базовый сервер Express, который выводит Hello World». Да, это звучит слишком просто. Но через час у вас будет что-то, с чем можно двигаться дальше.
2. Не принимайте слишком много решений одновременно
Если вы разрабатываете новый проект, не нужно сразу соглашаться, что он «уже сегодня» должен иметь:
-
чёткую структуру директорий;
-
“идеальный” Redux/Signals/Vuex-стор;
-
пользовательскую CI/CD-пайплайн;
-
100%-ный тестовый coverage.
Оставьте эти задачи на потом и фокусируйтесь на минимальных, но работающих версиях.
3. Пусть ранние этапы будут хаосом
Превращайте процесс построения проекта в последовательность итераций. На самом деле, никакого идеального кода на старте не существует, потому что сам проект находится на этапе неопределённости.
В работе нужно перестать рассматривать написание «грязного» кода или использование временных решений как проблему. Главное — постоянно держать в голове эту цепочку:
-
Написать рабочий код.
-
Улучшить что-то в существующей кодовой базе.
-
Повторить.
Рефакторинг не страшен, если вы делаете его регулярно.
4. Ставьте цели, которые зависят от действий, а не от результата
Вместо того чтобы говорить себе: «Сегодня я построю модульную структуру backend-а», лучше напишите: «Сегодня я создам функционал аутентификации с минимальной связностью». Такой подход помогает сосредоточиться на процессе и меньше страдать от ощущения, что результат пока не «грандиозный».
5. Учитесь отпускать
Отпустите иллюзию, что первое решение — всегда окончательное. Это не так. Код предполагает, что его пишут, а не высекут в камне. Если выбрали стратегию, но она потом оказалась неэффективной, ничто не мешает её изменить. Не бойтесь оставить что-то недоделанным. Главное — ваша способность двигаться вперёд. В индустрии выживают не те, кто создаёт идеальное с первой попытки, а те, кто выпускает работающие проекты и готов улучшать их с каждым новым обновлением.
Рефакторинг не ждёт особого момента
Тут важно подчеркнуть ещё одну мысль — важность постоянного рефакторинга. Часто мы мысленно отделяем разработку от рефакторинга. Есть мол, этап «мы быстро кодим для MVP», а потом — этап «мы возвращаемся, чтобы всё зачистить». Однако этот подход в корне ошибочен: бизнес не даст денег на «этап рефакторинга», если только проект уже не горит, как свечка.
Я, честно говоря, больше никогда не разделяю эти вещи. Рефакторинг — не отдельная стадия проекта, это часть процесса разработки. Это то, что вы делаете каждый день, с каждым коммитом, чтобы сделать код хотя бы чуточку лучше, чем он был вчера.
Много лет назад я принимал участие в проекте, который на старте был классическим примером плохой разработки. Кодовая база была хаотичной: множество «хотфиксов», дублирования, отсутствия тестов и полной каши в структуре директорий. Понятие «архитектура» здесь не применялось совсем, а куча логики была расфокусирована по всему проекту. Несмотря на то, что продукт выполнял свои задачи, работать с ним было настолько сложно, что каждый новый функционал превращался в кошмар даже для опытных разработчиков.
Проект уже приносил какие-то деньги, но любые добавления функций или исправления багов занимали в 2-3 раза больше времени, чем изначальные оценки. Компанию поставили перед выбором: взять и полностью переписать проект (что может занять до года) или постепенно улучшать его без остановок для бизнеса.
Первое, что было сделано, — команда договорилась о практическом подходе: «каждый коммит должен оставлять код чуть лучше, чем он был до этого». Это не значило, что мы сразу перепишем всё. План включал следующие шаги:
-
При добавлении нового функционала — рефакторим окружающую часть кода. Например: если добавлялся метод в устаревший класс, этот класс приводился в более аккуратное состояние, а сам метод мы старались реализовать в соответствии с лучшими практиками.
-
Постепенно внедряли тестирование. Каждый новый или изменённый кусок кода покрывался тестами, чтобы минимизировать риск поломок.
-
Писали себе маленькие задачи «по ходу». Например, если мы находили сложный нечитаемый метод, мы редко перерабатывали его сразу, но заводили тикет «Оптимизировать X».
-
Приводили к единому стилю кодирования. Даже порядок импортов и форматирование стали для нас важными.
После года постепенного улучшения проект прошёл внешний аудит, так как компания привлекла крупного клиента. Внешний аудитор отметил, что, хотя в глубине оставалось наследие старого плохо написанного кода, текущая структура и сопровождение уже соответствовали стандартам. Что самое главное, бизнес увидел разницу — добавление новых функций занимало меньше времени и стоило компании гораздо дешевле. Благодаря этому продукт удалось вырастить до уровня, при котором он приносил заметный доход.
Этот случай показал мне и команде, что постепенное улучшение — это реально работающая стратегия. Нет необходимости переписывать проект с нуля, если есть желание и дисциплина улучшать его шаг за шагом. Главное — системность и желание двигаться к порядку.
Никто не помнит, с чего началось, но все увидят результат
Когда проект завершён (или хотя бы работает), никто уже не заботится о том, какой хаос был на старте. Пользователи будут пользоваться, клиенты подпишут контракт, ваш темлид похвалит (или не похвалит — зато проект жил).
Давайте вспомним, как создавалась большая часть успешных продуктов. Facebook начинался с локальной сети университетов. Amazon — как книжный магазин. А первый код популярного языка Python, по воспоминаниям создателя Гвидо ван Россума, выглядел далеко не лучше вашего студенческого проекта.
Если самые известные компании мира начинались с функциональности, работающей «как-нибудь», то откуда у нас уверенность, что наш код с первой попытки должен быть идеальным?
Заключение
Идеального старта не бывает. Точка.
Код пишется, а не рождается. Он живёт в постоянных итерациях. Не нужно писать идеальную структуру с первых дней разработки — это иллюзия. Задача разработчика — не сотворить произведение искусства на старте, а двигаться вперёд, чтобы в каждый конкретный момент улучшать то, что уже создано.
Красивый код — это миф. А хороший код — это тот, который работает. Выбирайте второе.
P.S. Можно почитать:
-
«Continuous Delivery»/Джез Хамбл, Дэвид Фарли. Старенькая, но фундаментальные концепции живут в веках)
-
«Refactoring»/Мартин Фаулер (ну вдруг кто-то еще не читал)
-
«Release It!»/Майкл Нигард. Про реальную жизнь и разочарования, которые подстерегают нас в реальных проектах.
ссылка на оригинал статьи https://habr.com/ru/articles/897468/
Добавить комментарий