Путь к успешному программному обеспечению вымощен тысячами небольших улучшений.

Сколько раз это случалось с вами?

Другой инженер отправляет вам и вашим товарищам по команде запрос на включение Git. Открывая его, вы видите, что пул-реквест такой же длинный и запутанный, как русский роман. Сотни изменений файлов во всех частях приложения. Реорганизация репозитория, изменения бизнес-логики в полдюжине сервисов приложений, перемещение пространств имен, реорганизация файлов в новые каталоги. Кажется, что ни один из них не обязательно связан, просто все резко изменилось, какофония переделки кода, все объединено в одну функциональную ветвь. Просматривая список коммитов, вы ловко ищете пресловутую кухонную раковину.

Мы все видели это хотя бы раз в своей карьере. Все мы знаем этого инженера, который просто не может не делать этого, внося слишком много изменений в одну ветку.

Не поймите меня неправильно. Бывают времена для больших обновлений. Они действительно существуют, и для их необходимости есть веские причины, что бы вам ни говорили гуру по микросервисам / Agile-коуч. Бывают моменты, когда что-то нужно капитально отремонтировать.

Большинство достойных инженеров не в восторге от этого факта. Большое изменение рискованно; это сложно проверить. Непредвиденные люди вскидывают болотистые головы и ухмыляются, глядя на большие перемены. Многочисленные переделки и рефакторинг неизменно означают много места для неудач. Однако иногда у нас нет выбора, кроме как смириться с Большим изменением. Это может быть архитектура, программное обеспечение, развертывание и т.д.

Помня об этом, вам следует избегать подобных Больших изменений, когда и как только возможно. По всем вышеперечисленным причинам и рискам, большие перемены являются опасной стратегией, и для ее реализации требуется бесконечно больше ресурсов, усилий и беспокойства. Придерживайтесь небольших изменений. Небольшие повторяющиеся изменения - это реальный путь к успеху программного обеспечения.

Чем меньше, тем лучше.

Вы не новичок?

Возможно, вы фыркаете и думаете: «Да, нет». Справедливо, потому что на этом этапе небольшие итеративные изменения программного обеспечения часто считаются общеизвестным и общепринятым мнением.

Если вы думаете, что придерживаться небольших итеративных изменений - это просто здравый смысл, вы в меньшинстве. Факт в том, что большинство компаний, большинство разработчиков / инженеров не могут не придерживаться мышления «немного больше, чем безопасно».

"Пока вы там, почему бы не исправить эту ошибку javascript?"

«Вы знаете, поскольку я добавляю эту новую библиотеку в код, я могу также добавить обновление к этим другим (несвязанным) библиотекам».

«Мы можем обновить эти сохраненные процессы И обновить БД до vX.Y.Z, пока мы находимся в этом».

Давай, скажи мне, что я ошибаюсь. Скажи мне, что ты никогда не слышал, чтобы кто-то из твоего отряда делал такое заявление. Вы никогда не видели, чтобы какой-нибудь разработчик попросил добавить сохраненный процесс, и он рефакторинг репозиториев будет его вызывать. Сомневаюсь, что вы сможете, потому что так думают многие. Зачем делать две мелочи со сверхнизким риском, когда я могу просто связать их вместе и получить от этого лишь немного больший риск? Это рассуждение, которому следуют десятки миллионов раз в день в миллионах ИТ-организаций, пресловутая смерть от тысячи сокращений одного и того же плохого решения, принимаемого снова и снова.

Я здесь, чтобы сказать вам или помочь вам сказать другим: прекратите. Это заблуждение, и оно постоянно подвергает риску вас и вашу кодовую базу.

Новое применение старой программной поговорке: девять беременных в течение месяца не могут родить ребенка

Для тех, кто не знаком, в мире программного обеспечения есть старая шутка, когда ваш начальник или супервайзер думают, что добавление дополнительных инженеров к вашему проекту обязательно повысит продуктивность.

«Если один разработчик может сделать это за три месяца, давайте возьмем еще двух разработчиков, и мы сделаем это за месяц!» - это ошибочный аргумент, который так часто выдвигается руководством, что получил свой шутливый ответ:

Девять беременных за месяц не родили ребенка

Это классическая шутка в мире информационных технологий. Смысл ясен: добавление большего количества людей в программный проект не ускоряет работу. Фактически, добавление людей в проект может значительно увеличить время, необходимое для выполнения части работы, из-за всех дополнительных переменных, лишних голов, которые могут ошибаться, и так далее. Чем больше людей вы добавите для работы над одной точкой в ​​вашем программном обеспечении, тем выше риск того, что один или несколько из них сделают то, о чем никто из остальных не думал.

Теперь я использую старую шутку для другой цели: размер изменений и риски, которые они несут.

Теория объединения двух изменений выглядит так:

  • У меня два изменения. Они оба представляют собой довольно низкий риск.
  • Я мог бы менять по одному, но это будут два набора изменений, которыми я должен управлять / обрабатывать / проталкивать через SDLC. Код, обзор, тестирование, запрос на включение, развертывание и т. Д.
  • Вместо этого я сложу их вместе и вытолкну их обоих, и мой риск лишь немного выше, чем если бы я делал их по одному.

Конечно, я понял. Черт, я сделал это. На самом деле, чаще, чем я хотел бы признаться. Я здесь, чтобы сказать вам, что это ложная экономия.

Почему мы это делаем: менталитет «больших изменений»

Я не могу сказать, почему все могут это сделать, но я попытаюсь выявить наиболее частые причины, по которым я вижу, что большие изменения происходят в запросе на вытягивание.

  1. Вы вкладываетесь в лень. Все эти лишние разветвления, кодирование, проверки, обзоры и т. д. кажутся скорее хлопотными, чем того стоит. Итак, вы объединяете две части работы вместе, чтобы избавить вас от всей этой «лишней работы».
  2. Вы под прицелом. Ваш заказ на поставку зависит от вас. У вас есть сроки, которые вы можете пропустить. Ранее на этой неделе вы пошли ва-банк, и теперь у вас нет времени успеть все сделать до того, как код заморозится.
  3. Вы мастер рефакторинга. Все мы знаем этого инженера. Инженер, который ничего не может поделать, кроме рефакторинга, выходящего за рамки той работы, которую он намеревался завершить, потому что у него было прозрение, как гораздо более элегантный способ соединить все это воедино. Приступая к добавлению нового картографа, вы в конечном итоге переписываете слой картографирования, чтобы соответствовать новому грандиозному видению картографии.
  4. Ваша история слишком велика. Ваш заказчик на поставку назначил вам историю, которая гласит: «Добавьте ведение журнала трассировки для всех контроллеров API». Вместо того, чтобы сопротивляться, говоря заказчику, что это эпос, а не история, вы делаете это и в итоге редактируете 40 исходных файлов. Это очень распространенная проблема, и вы должны следить за ней на каждом шагу. Истории должны быть небольшими, как изменения вашего кода.
  5. Кто-то пообещал то, чего не должен был. Специалисты по продажам в вашей компании пообещали потенциальному покупателю, что ваш продукт полностью поддерживает функции A, B, C, D и E, и все они будут производиться конец месяца. Никогда не пытаясь уточнить у кого-либо, прежде чем выписывать чеки, по которым их задница не может обналичить, теперь продавец заставляет вашу команду прикрыть свою задницу проблемой.
  6. Вы высокомерны. Вы настолько уверены в своих силах, что вам не нужно следовать правилам, например, вносить небольшие изменения. Ваш код проходит самотестирование, никогда не бывает ошибочным, всегда работает, потому что вы настолько умны. Если бы я получал пятак за каждый раз, когда видел это, я был бы очень богатым человеком.

Почему большие изменения - это плохо

Каковы бы ни были ваши причины, позвольте мне объяснить вам, почему эти большие перемены неизменно вредны для всех, и для вас в частности.

  • Большие изменения означают большую сложность. Каким бы маленьким ни было одно изменение в вашем большом изменении, все они вместе составляют большое изменение за один раз. Это означает увеличение сложности всего приложения. Чем больше файлов / строк кода вы добавляете или редактируете, тем сложнее вы вносите все сразу. Множество мелких изменений во многих местах на самом деле вносят еще большую сложность, потому что в процессе может быть сломано еще много вещей.
  • Возможно, ваши идеи не так хороши, как вы думаете. Вы только что внесли изменения в десятки и десятки файлов, и все это во имя вашего Большого изменения. Однако теперь вы передаете это на рассмотрение / PR, и один или несколько ваших коллег быстро указывают, почему то, что вы сделали, не самое лучшее. Хорошо, отлично. Так что вместо того, чтобы обращаться к нескольким файлам, вам, возможно, придется провести рефакторинг вашего массивного рефакторинга, что означает еще большее усложнение, поскольку вам придется менять курс в середине строительства кровавой супермагистрали. Чем меньше изменение, тем легче вам будет что-то изменить, если ваша грандиозная идея окажется не такой горячей, как вы сначала представляли.
  • Не забывайте обо всех этих тестах. Когда кто-то вносит 20 или 30 изменений в файлы кода, они часто забывают, что это также означает 20 или 30 изменений в модульных / компонентных тестах, охватывающих этот код. Теперь вместо 20 или 30 изменений вы можете получить более 20–30 изменений файлов для рефакторинга тестов.
  • Фактор пустого глаза. Все те файлы, которые вы изменили, могут показаться вам кристально ясными, но другие инженеры, которые проводят масштабную проверку кода или PR, не обращают внимания на масштаб внесенных вами изменений. Люди теряют сознание после точки. Их внимание ослабнет. Это фактор пустого глаза: люди, которые видят слишком много изменений в коде, постепенно откажутся от него, не смогут по-настоящему сосредоточиться на изменениях. Вот как проскальзывает плохой код, как штампуются отзывы и PR, потому что люди не могут понять все это. Держите его маленьким, и люди будут сосредоточены на том, чего вы хотите достичь.
  • Непрерывная доставка. Смысл непрерывной доставки заключается в том, чтобы регулярно и итеративно приносить пользу вашим клиентам. Это становится намного более рискованным, когда вы вносите массовые изменения в производство. Непрерывная доставка, если все сделано правильно, осуществляется с небольшими изменениями, так что любое отдельное изменение может быть отменено при необходимости. Это намного труднее сделать, когда у вас есть 200 изменений в кодовой базе одним большим взрывом.

Вы можете прочитать одну из лучших статей, которые я когда-либо читал, о том, почему большие изменения - это плохо.



Сохранение малого: что вы можете сделать

Итак, все это говорит о том, что теперь вы хотите, чтобы эти изменения кода были небольшими. Есть вещи, которые вы можете сделать, чтобы помочь в этом.

Маленькие истории = небольшие изменения кода

Как упоминалось выше, если вам нужно выполнить аморфную, всеобъемлющую историю, скорее всего, ваш код будет таким же. Если история кажется слишком большой, скорее всего, это так. Постарайтесь нарезать эти большие истории меньшими. Каждое небольшое изменение, которое вы делаете, добавляет ценности. Вместо того, чтобы добавлять ведение журнала трассировки ко ВСЕМ контроллерам API, создавайте истории меньшего размера, чтобы добавить трассировку к каждому контроллеру API. Добавьте немного ценности, разбивая свои истории как можно меньше. Добавьте минимальное количество ценности и продолжайте наращивать ее, используя серию функциональных веток.

Перестаньте все время думать о Full Stack

Конечно, люди любят прибавлять к названию это слово. «Я разработчик полного цикла». Это не значит, что вам нужно доказывать это каждым изменением, которое вы вносите. Необходимо добавить конечную точку API, которая извлекает и сохраняет некоторую модель в базе данных? Отлично. Разбейте его на каждый слой, чтобы каждый слой можно было многократно тестировать по мере продвижения. Каждый уровень - это свое собственное незаметное изменение, каждый в своей собственной ветке функций, поэтому вы выполняете небольшие, но четкие шаги для окончательной доставки функции.

  • Изменение 1: Контроллер API с контрактами и который возвращает / потребляет модели (с тестами)
  • Изменение 2: Служба приложений, которая взаимодействует с API, добавленным в изменение 1. (также с тестами)
  • Изменение 3: репозиторий, который взаимодействует со службой приложений (больше тестов)
  • Изменение 4: Подключите базу данных.

Это пример того, как разбивать ваши истории на более мелкие. Каждая из вышеперечисленных работ возвращает некоторую небольшую ценность, все из которых можно протестировать, и все они вносят минимальное количество изменений на каждом этапе.

Отодвиньте навязанные сроки

Неважно, кто это. Заказчик, продавец, начальник. Если кто-то устанавливает нереальные сроки, которые заставляют вас делать слишком много слишком быстро, вам следует отступить. Конечно, они могут оттолкнуть вас сильнее и вынудить вас произвести раздутые изменения. Вы и ваша команда должны объяснить, почему большие изменения опасны, почему дополнительное время, чтобы все делать правильно, снижает риск для бизнеса и повышает вероятность того, что любые непредвиденные ошибки будут обнаружены в небольших изменениях, а не в более крупных. .

Измените код, чтобы он был удобен для внесения небольших изменений

Может случиться так, что ваше приложение нелегко изменить с помощью небольших итеративных изменений. Это особенно верно в отношении старых приложений, которые превратились в скопище запутанной паутины.
Это произойдет не сразу, но вместе с вашей командой и вашими архитекторами необходимо со временем реорганизовать приложение, чтобы упростить внедрение. небольшие изменения, а не большие. Это амбициозная цель, которую нелегко достичь, но она того стоит. IoC, слабая связь, небольшие сервисы - все это хорошие шаблоны, которые вы можете начать использовать, чтобы довести свое приложение до места, где небольшое изменение кода может сразу показать ценность.

Надеюсь это поможет