Главная страница
Навигация по странице:

  • Почему бы просто не «отказаться от изменений»

  • Масштабирование и эффективность

  • Плохо масштабируемые политики

  • Хорошо масштабируемые политики

  • Пример: обновление компилятора

  • Основа для принятия решений

  • Пример: распределенная сборка

  • Пример: выбор между временем и масштабированием

  • Пересмотр решений, совершение ошибок

  • Программная инженерия и программирование

  • Делай как вGoogle


    Скачать 5.77 Mb.
    НазваниеДелай как вGoogle
    Дата31.05.2022
    Размер5.77 Mb.
    Формат файлаpdf
    Имя файлаDelay_kak_v_Google_Razrabotka_programmnogo_obespechenia_2021_Tom.pdf
    ТипДокументы
    #559735
    страница4 из 69
    1   2   3   4   5   6   7   8   9   ...   69
    29
    роких пределах) временем жизни, можно определить стили программирования: код, зависящий от хрупких и недокументированных особенностей, скорее всего, будет классифицирован как «хакерский» или «хитрый», тогда как код, следующий передовым практикам и учитывающий возможность развития в будущем, вероят- но, будет считаться «чистым» и «удобным для сопровождения». Оба стиля имеют свои цели, но выбор одного из них во многом зависит от ожидаемого срока службы кода. Мы привыкли использовать термин программирование, если характеристика
    «хитрый» — это комплимент, и программная инженерия, если слово «хитрый» имеет отрицательный оттенок.
    Почему бы просто не «отказаться от изменений»?
    Все наше обсуждение времени и реакции на изменения связано с неизбежностью изменений. Верно?
    Как и все остальное, о чем говорится в книге, принятие решения об обновлении зависит от обстоятельств. Мы готовы подтвердить, что «в большинстве проектов, существующих достаточно долго, рано или поздно возникает необходимость обнов- ления». Если у вас есть проект, написанный на чистом C и не имеющий внешних зависимостей (или имеющий только зависимости, гарантирующие стабильность в течение долгого времени, такие как стандарт POSIX), вы вполне можете избежать рефакторинга или сложного обновления. Разработчики языка С прикладывают значительные усилия, чтобы обеспечить его стабильность.
    Но большинство проектов подвержены изменениям в базовой технологии. В основ- ном языки программирования и среды выполнения меняются активнее, чем язык C.
    Даже библиотеки, реализованные на чистом C, могут меняться для поддержки новых функций и тем самым влиять на пользователей. Проблемы безопасности есть во всех технологиях, от процессоров до сетевых библиотек и прикладного кода. Каж-
    дый элемент технологии может стать причиной критической ошибки и уязвимости безопасности, о которых вы не узнаете заранее. Если вы не применили исправления для Heartbleed (
    http://heartbleed.com
    ) или не смягчили проблемы с упреждающим вы- полнением, такие как Meltdown и Spectre (
    https://meltdownattack.com
    ), потому что по- лагали (или были уверены), что ничего не изменится, последствия будут серьезными.
    Повышение эффективности еще больше осложняет картину. Мы стараемся оснастить вычислительные центры экономичным оборудованием, разумно использующим процессоры. Но старые алгоритмы и структуры данных на новом оборудовании работают хуже: связанный список или двоичное дерево поиска продолжают рабо- тать, но растущий разрыв между скоростями работы процессора и памяти влияет на «эффективность» кода. Со временем ценность обновления аппаратного обеспе- чения может уменьшаться в отсутствие изменений в архитектуре ПО. Обратная совместимость гарантирует работоспособность старых систем, но не гарантирует эффективности старых оптимизаций. Нежелание или неспособность воспользоваться новыми аппаратными возможностями чреваты большими издержками. Подобные

    30
    Глава 1. Что такое программная инженерия?
    проблемы сложны: оригинальный дизайн может быть логичным и разумным для своего времени, но после эволюции обратно совместимых изменений предпочти- тельным становится новый вариант (ошибок не было, но время сделало изменения ценными и востребованными).
    Подобные проблемы объясняют, почему в долгосрочных проектах необходимо уде- лять внимание устойчивости независимо от того, влияют ли они непосредственно на нас или только на технологии. Изменения — это не всегда хорошо. Мы не должны меняться только ради перемен, но должны готовиться к изменениям и инвестировать в их удешевление. Как известно каждому системному администратору, одно дело — знать, что есть возможность восстановить данные с ленты, и совсем другое — знать, как это сделать и во что это обойдется. Практика и опыт — это двигатели эффектив- ности и надежности.
    Масштабирование и эффективность
    Как отмечается в книге Бетси Бейер и др. «Site Reliability Engineering. Надежность и безотказность как в Google» (СПб.: Питер, 2019) (далее Site Reliability Engineering —
    SRE), производственная система в компании Google относится к числу самых слож- ных систем, созданных человеком. Формирование такой машины и поддержание ее бесперебойной работы потребовали бесчисленных часов размышлений, обсуждений и проектирования с участием экспертов со всего мира.
    Большая часть этой книги посвящена сложностям, связанным с масштабированием в организации, которая производит такие машины, и процессам поддержания этой машины в рабочем состоянии в течение долгого времени. Давайте снова вернемся к понятию устойчивости кодовой базы: «База кода организации является устойчи-
    вой, если вы можете без опаски изменять то, что нужно, в течение срока ее службы».
    В данной формулировке под возможностями также понимаются издержки: если обновление чего-либо сопряжено с чрезмерными затратами, оно, скорее всего, будет отложено. Если со временем затраты растут сверхлинейно, это значит, что выпол- няемая операция не масштабируется
    1
    и наступит момент, когда изменения станут неизбежными. Когда проект вырастет вдвое и понадобится выполнить эту операцию снова, окажется ли она вдвое более трудоемкой? Найдутся ли человеческие ресурсы для ее выполнения в следующий раз?
    Люди — не единственный ограниченный ресурс, который необходимо наращивать.
    Само ПО должно хорошо масштабироваться в отношении традиционных ресурсов, таких как вычислительная мощность, память, объем хранилища и пропускная способ- ность. Разработка ПО также должна масштабироваться с точки зрения количества участвующих в ней людей и объема вычислительных ресурсов. Если стоимость вы-
    1
    Всякий раз, когда в этой главе мы используем слово «масштабируемость» в неформальном контексте, мы подразумеваем «сублинейное масштабирование в отношении человеческих возможностей».

    Масштабирование и эффективность
    31
    числений на тестовом кластере растет сверхлинейно и на каждого человека в квар- тал приходится все больше вычислительных ресурсов, это значит, что положение неустойчиво и скоро придется что-то изменить.
    Наконец, самый ценный актив организации, производящей ПО, — кодовая база — тоже нуждается в масштабировании. При сверхлинейном росте системы сборки или системы управления версиями (VCS, version control system) (возможно, в результате увеличения истории изменений) может наступить момент, когда работать с ней станет невозможно. Многим аспектам, таким как «время для полной сборки», «время для получения новой копии репозитория» или «стоимость обновления до новой языко- вой версии», не уделяется должного внимания из-за того, что они меняются очень медленно. Но они с легкостью могут превратиться в метафорическую сварившуюся лягушку (
    https://oreil.ly/clqZN
    ): медленно накапливающиеся проблемы слишком легко усугубляются и почти никогда не проявляются в виде конкретного момента кризиса.
    Только имея полное представление об организации в целом и стремясь к масштаби- рованию, вы, возможно, сможете оставаться в курсе этих проблем.
    Все, что организация использует для производства и поддержки кода, должно быть масштабируемым с точки зрения издержек и потребления ресурсов. В частности, все операции, которые организация должна выполнять снова и снова, должны быть масштабируемыми относительно человеческих усилий. С этой точки зрения многие распространенные политики не могут считаться хорошо масштабируемыми.
    Плохо масштабируемые политики
    Даже небольшой опыт разработки позволяет легко определять политики, плохо поддающиеся масштабированию, чаще всего по изменению объема работы, прихо- дящемуся на одного инженера, при расширении компании. Если организация уве- личится в 10 раз, увеличится ли в 10 раз нагрузка на одного инженера? Увеличится ли объем работы, которую он должен выполнять, при увеличении кодовой базы?
    Если на какой-то из этих вопросов будет дан положительный ответ, найдутся ли механизмы для автоматизации или оптимизации работы этого инженера? Если нет, значит, в организации есть явные проблемы с масштабированием.
    Рассмотрим традиционный подход к устареванию (подробнее об устаревании в гла- ве 15) в контексте масштабирования. Представьте, что принято решение использовать новый виджет вместо старого. Чтобы мотивировать разработчиков, руководители проекта говорят: «Мы удалим старый виджет 15 августа, не забудьте перейти к ис- пользованию нового виджета».
    Такой подход хорошо работает в небольших проектах, но быстро терпит неудачу с увеличением глубины и широты графа зависимостей. Команды зависят от посто- янно растущего числа виджетов, и любое нарушение в сборке может повлиять на рост компании. При этом вместо перекладывания хлопот, связанных с миграцией нового кода, на клиентов команды могут сами внедрить все необходимое, используя преимущества экономии от масштабируемого решения.

    32
    Глава 1. Что такое программная инженерия?
    В 2012 году мы начали смягчать проблему обновления и поручили командам, отвеча- ющим за инфраструктуру, переводить внутренних пользователи на применение новых версий или выполнять обновление на месте с обеспечением обратной совместимости.
    Эта стратегия, которую мы назвали «правилом обновления», хорошо масштабиру- ется: зависимые проекты перестали тратить все больше и больше усилий, чтобы просто не отстать. Мы также выяснили, что специальная группа экспертов внедряет обширные изменения намного лучше, чем пользователи: эксперты некоторое время изучают всю глубину изменения, а затем применяют полученные знания в каждой подзадаче. Внедрение изменений пользователем вызывает замедление в работе: он вынужден решать проблему непосредственно у себя, а затем выбрасывать ставшие бесполезными знания. Опыт экспертов масштабируется лучше.
    Еще один пример плохо масштабируемой политики — традиционное использование ветвей разработки. Если слияние крупных изменений с главной ветвью дестаби- лизировало продукт, можно сделать вывод: «Нужно более жесткое управление слиянием. Слияния должны производиться реже!» и для каждой команды (или функциональной возможности) создать отдельные ветви разработки. Когда такая ветвь достигнет конечной точки разработки, она будет протестирована и объединена с главной ветвью, из-за чего другие инженеры, работающие над другими ветвями, будут вынуждены повторно синхронизировать репозитории и проводить тесты.
    Такой способ управления ветвями можно использовать в небольшой организа- ции, где одновременно разрабатывается 5–10 подобных ветвей. Но по мере роста организации (и количества ветвей) этот подход увеличивает накладные расходы на многократное выполнение одной и той же задачи. Более эффективный подход обсудим в главе 16.
    Хорошо масштабируемые политики
    Какие политики помогают оптимизировать затраты по мере роста организации?
    Точнее, какие виды политики можно внедрить, чтобы обеспечить суперлинейный рост ценности при росте организации?
    Одна из наших любимых внутренних политик позволяет командам поддержки инфра- структуры безопасно вносить изменения в инфраструктуру. «Если в работе продукта есть сбои или другие проблемы после изменений в инфраструктуре, но их причины не выявлены тестами в системе непрерывной интеграции (CI, continuous integration), значит, эти причины не связаны с изменениями». Другими словами: «Если вам что-то понравилось, добавьте соответствующий тест в систему непрерывной интеграции».
    Мы называем это «правилом Бейонсе»
    1
    . С точки зрения масштабирования прави- ло Бейонсе подразумевает, что сложные одноразовые специализированные тесты, которые не запускаются системой непрерывной интеграции, не нужно учитывать:
    1
    Это отсылка к популярной песне «Single ladies», в которой рефреном звучит фраза: «If you liked it then you shoulda put a ring on it». («Если я тебе нравилась, так надел бы мне на палец колечко».)

    Масштабирование и эффективность
    33
    инженер инфраструктурной команды может найти другую команду, добавившую код, и спросить, как этот код тестировать. Это удобно, когда в команде сто инженеров, но со временем нам пришлось расширить эту стратегию.
    Мы обнаружили высокую эффективность форумов для общения в крупных органи- зациях. Когда инженеры обсуждают вопросы на форумах, знания быстро распростра- няются, и новые специалисты набираются опыта. Если у вас есть сотня инженеров, пишущих на Java, то один опытный эксперт по Java, готовый ответить на их вопро- сы, вскоре даст вам сотню инженеров, пишущих лучший код на Java. Знания — это вирусы, а эксперты — их носители. Более подробно коснемся этой темы в главе 3.
    Пример: обновление компилятора
    Рассмотрим сложную задачу обновления компилятора. Теоретически обновление компилятора не должно вызывать сложностей, учитывая, сколько усилий прилага- ют разработчики языков, чтобы сохранить обратную совместимость. Но насколько простым является это обновление на практике? Если прежде вам никогда не прихо- дилось выполнять такое обновление, как бы вы оценили его совместимость с вашей базой кода?
    По нашему опыту, обновление языка и компилятора — тонкая и сложная задача, даже если ожидается, что новая версия сохранит обратную совместимость. Обновление компилятора почти всегда приводит к незначительным изменениям в его поведении и требует исправления ошибок компиляции, настройки флагов оптимизации или других ранее не выявленных изменений. Как оценить исправность всей кодовой базы, учитывая все потенциальные проблемы обновления компилятора?
    Самое сложное обновление компилятора за всю историю Google было проведено в 2006 году. На тот момент мы уже несколько лет имели в штате тысячи инженеров и не обновляли компиляторы около пяти лет. Большинство инженеров не имели опыта смены компилятора, а большая часть кода компилировалась только одной версией компилятора. Обновление стало трудной и утомительной задачей для
    (в основ ном) добровольцев, которая в конечном итоге свелась к поиску коротких пу- тей обхода изменений с проблемами адаптации
    1
    . Внедрение изменений происходило болезненно: многие проблемы, согласно закону Хайрама, проникли в кодовую базу и углубили его зависимости от конкретной версии компилятора, сломать которые было очень трудно. Инженеры пошли на риск и применили изменения, четко не представляя последствия и не зная правила Бейонсе и вездесущей системы непре- рывной интеграции.
    Этот опыт не был чем-то необычным. Инженеры многих компаний могут расска- зать похожие истории. Необычность заключается в нашем осознании сложности
    1
    В частности, на интерфейсы из стандартной библиотеки C++ нужно было ссылаться с ис- пользованием пространства имен std
    , а изменения в оптимизациях для std::string отри- цательно повлияли на производительность кода, что потребовало искать дополнительные обходные пути.

    34
    Глава 1. Что такое программная инженерия?
    задачи. Благодаря тому опыту мы стали уделять больше внимания изменениям в технологиях и организации, чтобы потом менее болезненно преодолевать про- блемы масштабирования и находить в нем преимущества. Мы стали развивать автоматизацию (чтобы один человек мог сделать больше), согласованность (чтобы ограничить влияние проблем на низком уровне) и обмен опытом (чтобы несколько человек могли сделать больше).
    Чем чаще вы вносите изменения в инфраструктуру, тем меньше проблем они вы- зывают. Мы обнаружили, что в большинстве случаев код, переживший обновление, становится менее хрупким и его легче обновлять в будущем. В экосистеме, где боль- шая часть кода прошла несколько обновлений, он перестает зависеть от нюансов ба- зовой реализации и начинает зависеть от фактических абстракций, гарантированных языком программирования или ОС. Независимо от того, что именно обновляется, первое обновление всегда будет обходиться базе кода значительно дороже, чем по- следующие, даже с учетом других факторов.
    Мы выявили множество факторов, влияющих на гибкость кодовой базы.
    Опыт
    Мы знаем, как это сделать. Для некоторых языков мы провели сотни обновлений компиляторов на множестве платформ.
    Стабильность
    Благодаря регулярному обновлению версий нам приходится вносить меньше изменений. Для некоторых языков мы внедряем обновления компиляторов раз в 1–2 недели.
    Согласованность
    Объем кода, не прошедшего обновление, постоянно уменьшается, опять же благо- даря регулярным обновлениям.
    Осведомленность
    Поскольку обновления происходят достаточно регулярно, мы можем выявить избыточные операции в процессе обновления и попытаться их автоматизировать.
    Это в значительной степени совпадает со взглядом SRE на рутину
    1
    Стратегия
    У нас есть процессы и политики, такие как правило Бейонсе, применяя которые мы делаем обновления выполнимыми. Команды поддержки инфраструктуры беспокоятся не о каждом неизвестном случае использования, а только о том, что видно в системе непрерывной интеграции.
    Мы осознали не частоту или сложность обновления компилятора, а необходимость обновлений и проводим их с постоянным числом инженеров даже при постоянном
    1
    Site Reliability Engineering. Надежность и безотказность, как в Google, глава 5 «Избавляемся от рутины». — Примеч. пер.

    Масштабирование и эффективность
    35
    росте кодовой базы
    1
    . Если бы мы решили, что эта задача слишком дорогостоящая и ее следует избегать в будущем, мы могли бы до сих пор использовать версию ком- пилятора десятилетней давности и из-за упущенных возможностей оптимизации заплатить за вычислительные ресурсы на 25 % больше. А наша центральная инфра- структура могла бы подвергнуться значительным рискам безопасности, поскольку компилятор 2006 года, безусловно, не смягчил бы уязвимости упреждающего вы- полнения. Стагнация — это вариант, но не самый разумный.
    Сдвиг влево
    Одна из общих истин, которую мы считаем верной, заключается в том, что выявле- ние проблем на ранних этапах разработки обычно снижает издержки. Рассмотрим временную шкалу разработки некоторой функциональной возможности (рис. 1.2).
    Процесс разработки движется слева направо — от обсуждения идеи и проектирования к реализации, проверке, тестированию, фиксации и канареечному развертыванию до развертывания в производственной среде. Сдвиг момента выявления проблемы влево на этой временной шкале удешевляет ее устранение.
    Идея Проектирование Разработка Тестирование Фиксация Интеграция Эксплуатация в репозитории
    Цена ошибк и
    Рис. 1.2. Временная шкала процесса разработки
    Это утверждение основано на аргументе, что решение проблем безопасности не должно откладываться до конца процесса разработки, поскольку если она будет об-
    1
    По нашему опыту, средний инженер-программист производит относительно постоянное количество строк кода за единицу времени. В фиксированной группе программистов база кода растет линейно — пропорционально количеству человеко-месяцев. Если ваши задачи требуют усилий, объем которых зависит от количества строк кода, переоценить влияние совместной работы будет трудно.

    36
    Глава 1. Что такое программная инженерия?
    наружена после выпуска продукта в производство, ее исправление обойдется очень дорого. В противном случае для ее устранения могут потребоваться значительные усилия, но конечная цена исправлений будет ниже. Если проблему удастся выявить до того, как разработчик отправит уязвимый код в репозиторий, ее исправление обойдется совсем дешево: разработчик понимает, как работает код, и исправит про- блему с меньшими затратами, чем кто-то другой.
    В этой книге много раз повторяется один и тот же основной паттерн. Исправление ошибок, обнаруженных статическим анализом и проверкой кода перед его отправ- кой в репозиторий, обходится намного дешевле устранения проблем, возникающих в ходе эксплуатации кода. Использование инструментов и методов, подтверждающих качество, надежность и безопасность на ранних этапах разработки, является общей целью для наших команд поддержки инфраструктуры. Никакой отдельный процесс или инструмент не может быть идеальным, поэтому мы должны использовать под- ход эшелонированной защиты, который, надеемся, поможет выявить большинство дефектов в левой части шкалы.
    Компромиссы и затраты
    Если вы умеете программировать, знаете, как долго будет служить ПО и как его поддерживать с увеличением штата инженеров, производящих и сопровождающих новые функциональные возможности, вам остается только научиться принимать правильные решения. Очевидно, что в программной инженерии, как и везде, хо- роший выбор ведет к хорошим результатам. Однако на практике эту истину легко упустить из виду. В Google неприемлема фраза: «Потому что я так сказал». В любом нашем обсуждении по любой теме участвуют человек, принимающий решения, и люди, не согласные с этими решениями. Наша цель — согласие, а не единогласие.
    Это нормально, и я привык слышать фразу: «Я не согласен с вашими метриками/
    оценками, но я понимаю, как вы могли прийти к такому выводу». В основе этого подхода лежит идея, что всему должна быть причина, а аргументы «просто потому»,
    «потому что я так сказал» или «потому что все так делают» — это признаки плохих решений. Мы всегда должны уметь объяснить и обосновать выбор между затратами двух инженерных решений.
    Что мы подразумеваем под затратами? Не только деньги, а сумму издержек, вклю- чающую любые или все следующие факторы:
    y финансовые затраты (например, деньги);
    y затраты ресурсов (например, процессорное время);
    y затраты на персонал (например, инженерный труд);
    y операционные издержки (например, стоимость принятых мер);
    y издержки упущенных возможностей (например, стоимость непринятых мер);
    y социальные издержки (например, влияние нашего выбора на общество в целом).

    Компромиссы и затраты
    37
    Традиционно легче всего игнорировать социальные издержки. Тем не менее Google и другие крупные технологические компании сегодня могут с уверенностью раз- вертывать продукты с миллиардами пользователей. Масштаб этих продуктов не только открывает возможности, но и усиливает последствия даже небольших про- блем в удобстве использования, доступности, справедливости, особенно в отношении маргинализованных групп. ПО проникает во многие аспекты общества и культуры, поэтому с нашей стороны полезно осознавать как достоинства, так и недостатки продукта и его технической стороны при его обсуждении (глава 4).
    Затраты также зависят от предубеждений: стремления сохранить текущее по- ложение дел, нежелания что-то потерять и др. Оценивая затраты, мы должны иметь в виду все перечисленные факторы. Здоровье организации — это не толь- ко наличие денег в банке, но также осознание ее сотрудниками своей ценности и продуктивности. В творческих и прибыльных областях, таких как программная инженерия, в первую очередь нужно оценивать не финансовые затраты, а затраты на персонал. Увеличение эффективности труда от того, что инженеры довольны, сосредоточены и вовлечены, требует контроля, потому что показатели сосредо- точенности и продуктивности настолько изменчивы, что легко представить себе разницу от 10 до 20 %.
    Пример: маркеры
    Во многих организациях простые маркеры для белой доски считаются ценным това- ром. Их распределение жестко контролируются, и они всегда в дефиците. Практи- чески всегда половина маркеров рядом с любой доской уже высохла и непригодна.
    Вы часто присутствовали на встречах, прерванных из-за отсутствия маркера? Часто теряли ход мыслей, когда маркер заканчивался? Случалось, что все маркеры просто пропадали, например когда их забирала другая команда? А ведь этот товар стоит меньше доллара.
    В Google, как правило, есть открытые шкафы, полные канцелярских принадлеж- ностей, включая маркеры. Достаточно просто послать уведомление, чтобы полу- чить десятки маркеров различных цветов. В этом смысле мы пошли на очевидный компромисс: гораздо важнее обеспечить беспрепятственный мозговой штурм, чем разбираться, кому маркер сейчас нужнее.
    Мы стремимся открыто и честно взвешивать компромиссы между затратами и вы- годой, от канцелярских принадлежностей и льгот для сотрудников до обмена опытом между разработчиками и всеобщей поддержки во всем. Мы часто говорим:
    «Google — это культура, основанная на данных». На самом деле это упрощение: даже в отсутствие данных могут существовать доказательства, прецеденты и аргументы.
    Принятие правильных инженерных решений — это взвешивание всех доступных входных данных и выбор компромиссов. Мы можем основать решение на интуиции или общепринятой практике, но только после применения подходов, основанных на измерениях или оценках истинных затрат.

    38
    Глава 1. Что такое программная инженерия?
    В конце концов, выбор решения в группе инженеров должен сводиться к одному из двух вариантов:
    y мы будем делать так, потому что обязаны (по требованиям законодательства или клиента);
    y мы будем делать так, потому что это лучший вариант (как определено кем-то, наде- ленным правом решения), в чем можно убедиться, основываясь на текущих данных.
    Решения не должны обосновываться фразой: «Мы будем делать так, потому что я так сказал»
    1
    Основа для принятия решений
    Оценивая данные, мы используем два основных сценария:
    y
    Все учитываемые величины измеримы или, по крайней мере, могут быть оценены.
    Обычно это означает возможность оценки компромиссов между процессорами и сетью, деньгами и оперативной памятью или двумя неделями труда инженеров и экономией N процессоров в вычислительных центрах.
    y
    Некоторые величины незначительны или мы не знаем, как их измерить. На- пример, иногда «мы не знаем, сколько времени нужно инженерам». Работать с такими величинами иногда сложнее, чем «оценить затраты на разработку плохо спроектированного API» или «оценить влияние выбора продукта на общество».
    В первом случае не должно быть недостатка в исходных данных. Любая организация, занимающаяся разработкой ПО, может и должна контролировать текущие затраты на вычислительные ресурсы, трудозатраты инженеров и др. Если вы не хотите пу- бликовать точные суммы финансовых затрат, создайте таблицу для пересчета: какое количество процессоров стоит столько же, сколько стоит данный объем ОЗУ или данная пропускная способность сети.
    Имея согласованную таблицу пересчета, каждый инженер сможет провести соб- ственный анализ: «Если я потрачу две недели на преобразование связного списка в структуру с более высокой производительностью, то использую на 5 ГБайт боль- ше оперативной памяти, но сэкономлю две тысячи процессоров. Стоит ли овчинка выделки?» Ответ на этот вопрос зависит не только от относительной стоимости оперативной памяти и процессоров, но и от затрат на персонал (две недели под- держки инженера-программиста) и стоимости упущенных возможностей (что еще этот инженер мог бы произвести за две недели?).
    Выбрать решение во втором случае сложнее. Обсуждая трудноизмеримые величины, мы полагаемся на опыт, лидерство и прецедент и вкладываем средства в исследования, которые помогут количественно оценить то, что трудно поддается количественной
    1
    Это не означает, что решения должны приниматься единогласно или широким консенсусом.
    Кто-то должен взять на себя ответственность за принятие решения. Мы описали сам процесс принятия решений.

    Компромиссы и затраты
    39
    оценке (глава 7). Главное, осознавать, что не все измеримо или предсказуемо, и под- ходить к решениям с осторожностью. Часто трудноизмеримые величины не менее важны, чем измеримые, но сложнее в управлении.
    Пример: распределенная сборка
    Рассмотрим пример сборки. Согласно ненаучным опросам в Twitter, 60–70 % раз- работчиков выполняют сборку ПО (даже большого и сложного) на локальном ком- пьютере. Это стало предметом множества шуток, как в комиксе «Compiling» (
    https://
    xkcd.com/303
    ). Сколько рабочего времени вы теряете в ожидании окончания сборки?
    Сравните это с затратами на использование чего-то вроде distcc в небольшой группе или с затратами на создание маленькой сборочной фермы для большой группы.
    Сколько недель/месяцев потребуется, чтобы эти затраты окупились?
    Еще в середине 2000-х сборка (проверка и компиляция кода) в Google выполнялась исключительно на локальных компьютерах. Да, были огромные локальные ком- пьютеры (позволяющие собирать Google Maps!), но с ростом кодовой базы время компиляции все росло и росло. Неудивительно, что увеличивались затраты на пер- сонал (из-за потерянного времени), а также на ресурсы (из-за закупки более мощных локальных машин). Затраты на ресурсы были особенно заметны, поскольку большую часть времени высокопроизводительные машины простаивали. Мы посчитали не- правильным вкладывать деньги в невостребованные ресурсы.
    Так в Google была создана своя система распределенной сборки. Разумеется, разработ- ка этой системы потребовала определенных затрат: инженерам понадобилось время на разработку, изменение привычек и рабочих процессов, освоение новой системы, и, ко- нечно, были задействованы дополнительные вычислительные ресурсы. Но общая эко- номия того стоила: сборка ускорилась, трудозатраты на разработку окупились, а инве- стиции в оборудование были направлены на общую инфраструктуру (подмножество нашего производственного парка), а не на приобретение все более мощных настоль- ных компьютеров. Подробнее о нашем подходе к распределенной сборке в главе 18.
    Итак, мы создали новую систему, внедрили ее в производство и ускорили процесс сборки для всех. Можно ли назвать это счастливым концом истории? Не совсем: со временем распределенная сборка стала замедляться, поскольку в граф сборки стали бесконтрольно проникать лишние зависимости. Раньше каждый отдельный инженер страдал от неоптимальной сборки, был заинтересован в ее ускорении и стремился что-то улучшить. Избавив инженеров от проблемы оптимизации процесса сборки, мы создали ситуацию, в которой потребление ресурсов вышло из-под контроля. Это было похоже на парадокс Джевонса
    1
    (
    https://oreil.ly/HL0sl
    ): потребление ресурса может
    увеличиться в ответ на повышение эффективности его использования.
    В целом затраты, связанные с внедрением распределенной системы сборки, намного перевесили расходы, связанные с ее созданием и обслуживанием. Но мы не преду-
    1
    https://ru.wikipedia.org/wiki/Парадокс_Джевонса.
    Примеч. пер.

    40
    Глава 1. Что такое программная инженерия?
    смотрели расходов, обусловленных ростом потребления. Забегая вперед, скажу, что мы оказались в ситуации, когда нам пришлось переосмыслить цели и ограничения системы и особенности ее использования, определить оптимальные подходы (неболь- шое число зависимостей, машинное управление зависимостями) и финансировать создание инструментов для обслуживания новой экосистемы. Даже относительно простой компромисс в виде «мы потратим вот столько на вычислительные ресурсы, чтобы окупить время инженера» имел непредвиденные последствия.
    Пример: выбор между временем и масштабированием
    Часто темы, связанные со временем и масштабированием, пересекаются и допол- няют друг друга. Хорошо масштабируемые стратегии, такие как правило Бейонсе, помогают управлять ситуацией с течением времени. Изменение интерфейса ОС одинаково влияет на все проекты, поэтому мелкие изменения в проектах, вызванные изменениями в ОС, хорошо масштабируются.
    Но иногда время и масштабирование вступают в конфликт, и особенно четко это про- является в базовом вопросе: лучше добавить зависимость или создать (заимствовать) новую ветвь, чтобы удовлетворить локальные потребности?
    Этот вопрос может возникнуть на разных уровнях стека, поэтому обычно инди- видуальное решение для узкой предметной области бывает эффективнее более общего решения. Ветвление действующего решения и его подгонка под свои нужды упрощает добавление новых возможностей и дает больше уверенности при его опти- мизации, будь то микросервис, кеш в памяти, подпрограмма сжатия или что-то еще в программной экосистеме. При этом вы получаете контроль: изменения в базовых зависимостях не будут определены другой командой или сторонним поставщиком, и вы сами решите, как и когда реагировать на возникающую необходимость перемен.
    С другой стороны, если вместо повторного использования каждый разработчик будет создавать новые версии всего, что нужно проекту, пострадают масштабируемость и устойчивость. Реагирование на проблему безопасности в базовой библиотеке пере- станет быть вопросом обновления отдельной зависимости: оно потребует определить все уязвимые версии этой зависимости и их пользователей.
    И снова программная инженерия не дает универсального ответа, что выбрать. Если проект имеет небольшую продолжительность жизни или ветвление имеет ограничен- ный объем, применение ветвления уместно. Но избегайте ветвления интерфейсов, которые могут жить дольше проекта (структур данных, форматов сериализации, сетевых протоколов). Согласованность имеет большое значение, но она тоже имеет цену, и часто выгоднее создавать свои решения, если делать это осторожно.
    Пересмотр решений, совершение ошибок
    Одним из недооцененных преимуществ приверженности культуре, основанной на данных, является возможность признавать ошибки. Представьте решение,

    Программная инженерия и программирование
    41
    основанное на имеющихся данных (вероятно, достоверных) и нескольких пред- положениях, неявно выведенных из этих данных. По мере поступления новых данных, изменения контекста или исключения предположений может выясниться, что решение было ошибочным или потеряло актуальность. Такая ситуация харак- терна для организаций, работающих много лет: со временем меняются не только технические зависимости и программные системы, но и данные, используемые для принятия решений.
    Мы твердо верим в решения, основанные на данных, но понимаем, что данные со временем меняются. Поэтому время от времени в течение срока службы системы решения должны пересматриваться. Для долгоживущих проектов важно иметь воз- можность менять направление после принятия первоначального решения, и лица, принимающие решения, должны иметь право на ошибки. Вопреки стереотипам лидеры, способные признавать ошибки, пользуются большим уважением.
    Опирайтесь на доказательства, но имейте в виду, что даже то, что невозможно из- мерить, может иметь ценность. Если вы лидер, придерживайтесь суждения, что нет ничего маловажного. Подробнее о лидерстве в главах 5 и 6.
    Программная инженерия и программирование
    Узнав, по каким признакам мы различаем программную инженерию и программи- рование, вы можете спросить, есть ли у нас какие-то внутренние суждения об их ценности. Можно ли сказать, что программирование хуже программной инженерии?
    Или утверждать, что проект, который, как ожидается, будет развиваться сотнями людей в течение десятилетий, ценнее проекта, который просуществует месяц и будет создан двумя людьми?
    Конечно нет. Мы не считаем, что программная инженерия лучше программирования.
    Это две разные предметные области с разными ограничениями, ценностями и мето- дами. Мы осознаем, что некоторые инструменты хороши в одной области и непри- годны в другой. Едва ли имеет смысл внедрять интеграционные тесты (глава 14) и непрерывное развертывание (continuous deployment, глава 24) в проект, который просуществует несколько дней. Точно так же наши достижения в области семанти- ческого управления версиями (SemVer) и управления зависимостями в программной инженерии (глава 21) не применимы к краткосрочным проектам, в которых можно смело использовать все, что доступно.
    Научитесь различать схожие термины «программирование» и «программная ин- женерия». Большая часть их различий заключается в подходах к управлению кодом, влиянии времени на масштабирование и особенностях принятия решений.
    Программирование — это непосредственный акт создания кода. Программная ин- женерия — это набор стратегий, методов и инструментов, помогающих сохранить полезность кода в течение всего времени его использования и обеспечить возмож- ность совместной работы в команде.

    42
    Глава 1. Что такое программная инженерия?
    Заключение
    В этой книге обсуждаются политики как для организаций, так и для отдельных про- граммистов, оценка и совершенствование методов, а также инструменты и технологии, используемые в ПО, удобном для сопровождения. Компания Google немало потруди- лась, чтобы получить устойчивые кодовую базу и культуру. Мы не считаем свой подход единственно верным, но он наглядно показывает, чего можно добиться. Надеемся, что он послужит полезной основой для размышлений об общей проблеме: как правильно поддерживать код, чтобы он работал столько времени, сколько понадобится.
    Итоги
    y
    «Программная инженерия» более широкое понятие, чем «программирование».
    Программирование — это создание кода. Программная инженерия добавляет к этому понятию обслуживание кода для увеличения срока его использования.
    y
    Продолжительность жизни короткоживущего и долгоживущего кода может от- личаться как минимум в 100 000 раз. Было бы неправильно полагать, что одни и те же практики применимы на обоих концах спектра.
    y
    ПО устойчиво, если в течение ожидаемого срока его службы мы сохраняем способ- ность реагировать на изменения в зависимостях, технологиях или требованиях к продукту. Мы можем ничего не менять, но должны быть готовы к изменениям.
    y
    Закон Хайрама: при достаточно большом количестве пользователей API не имеет значения, что вы обещаете в контракте: любое наблюдаемое поведение системы будет зависеть от чьих-то действий.
    y
    Каждая задача, которую организация должна выполнять снова и снова, должна масштабироваться (линейно или еще лучше) в отношении участия человека. По- литики — прекрасный инструмент для масштабирования процесса.
    y
    Проблемы, обусловленные неэффективностью процесса, и некоторые другие имеют свойство накапливаться медленно. Они с легкостью могут превратиться в метафорическую сварившуюся лягушку.
    y
    Опыт окупается особенно быстро в сочетании с экономией за счет масштабиро- вания.
    y
    «Потому что я так сказал» — это плохое обоснование решения.
    y
    Принятие решений на основе данных — хорошее правило, но на практике боль- шинство решений основывается на сочетании данных, предположений, прецеден- тов и аргументов. Лучше всего, когда объективные данные составляют большую часть основы для принятия решений, но не всегда есть возможность опираться
    только на них.
    y
    Принятие решений на основе данных подразумевает необходимость изменения направления, если данные изменились или предположения были опровергнуты.
    Ошибки и пересмотр планов неизбежны.

    1   2   3   4   5   6   7   8   9   ...   69


    написать администратору сайта