Что пишут в блогах

Подписаться

Онлайн-тренинги

Конференции

Что пишут в блогах (EN)

Разделы портала

Про инструменты

Лучшие вакансии

.
Почему мы пишем программы такого низкого качества?
09.04.2020 00:00

Автор оригинала: Jake Voytko


Проектировщики самолёта отвечают на вопрос о его безопасности:
— Ничто не вечно, но современные авиалайнеры невероятно устойчивы, а самолёт — самый безопасный транспорт в мире.
Инженеры-строители отвечают о безопасности лифтов:
— Лифты защищены множеством отказоустойчивых механизмов. Их практически невозможно уронить в свободное падение.
Программисты отвечают на вопрос об электронном голосовании:
— Это просто ужасно.
— Серьёзно?
— Абсолютно. Не доверяйте программам для электронного голосования и не верьте никому, кто уверяет в их надёжности.
— Почему?
— Не совсем знаю, как это выразить, но вся наша область плоха в том, что мы делаем, и если вы будете полагаться на нас, то все умрут.
— Говорят, что надёжность гарантируется технологией под названием «блокчейн».
— А-а-а-а-а!!! Что бы они ни говорили, не прикасайтесь к этому! Закопайте поглубже. Не забудьте перчатки!

Источник: XKCD, лицензия Creative Commons 2.5


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

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

По твиттеру пошла волна хэштегов #app и #problems, а инженеры-программисты ссылались на КДПВ. Я тоже так думал. Слова с этой карикатуры хорошо резюмируют общее ощущение происходящего: «Не совсем знаю, как это выразить, но вся наша область плоха в том, что мы делаем, и если вы будете полагаться на нас, то все умрут». Инженеры-программисты не говорят это прямо. Но звучит очень похоже. Что мы имеем в виду?

Вот что мы имеем в виду: мы хорошо делаем программное обеспечение при условии, что последствия неудачи не имеют значения. В среднем программы достаточно хороши, чтобы как-то работать. Тем не менее, мы не особо удивляемся ошибкам в большинстве программ. Это не какие-то редкие инциденты. Многие распространённые практики в программной инженерии исходят из предположения, что сбои являются нормой, а главное — новые функции. Неудача действительно стоит дёшево. Если онлайн-сервис от одной из крупнейших компаний полностью отключится на два часа, об этом забудут уже через неделю. Это предположение воплощается в распространённых мантрах: «Двигайся быстро и всё ломай» (Move fast and break things), «Выкатывай и повторяй цикл» (launch and iterate).

Рынок щедро вознаграждает за такое «безответственное» поведение. Во многих веб-компаниях небольшая прибыль с одного пользователя умножается на миллионы (или миллиарды!) пользователей. Это выгодно для компаний с потребительскими приложениями или веб-сайтами. Реализация дорогостоящая, но стоимость конечна, а распространение почти бесплатное. Индустрия потребительского ПО нашла компромисс: мы снижаем скорость внедрения ровно настолько, чтобы поддерживать наш уровень дефектов умеренно низким, но не слишком.

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

Но, как я уже говорил, «мы хорошо делаем программное обеспечение при условии, что последствия неудачи не имеют значения». Такой подход приводит к ужасным провалам, если последствия не обходятся дёшево, как в Айове. Распространённая практика разработки программного обеспечения выросла из экономической модели интернета, а когда допущения этой модели нарушаются, инженеры-программисты плохо справляются со своей работой.


Как работает программирование в веб-компаниях?

Представим гипотетическую компанию QwertyCo. Это ориентированная на потребителя софтверная компания, которая зарабатывает 100 миллионов долларов в год. Мы можем оценить размер QwertyCo, сравнивая с другими компаниями. WP Engine, WordPress-хостинг, достиг $100 млн ARR в 2018 году. Blue Apron выручил за год $667 млн. Таким образом, QwertyCo — это компания среднего размера. У неё от нескольких десятков до нескольких сотен инженеров и она не выпускала акции в публичное обращение.

Во-первых, рассмотрим экономику управления проектами в QwertyCo. Руководители узнали, что вы не хотите мгновенно объявить о появлении новой функции. У вас компромисс между качеством программного обеспечения, дедлайном и скоростью реализации.

Насколько важно для них качество программного обеспечения? Не особо. Если веб-сайт QwertyCo не работает в течение 24 часов в год, они оценивают потерю всего в $273 972 (предполагая, что время безотказной работы линейно коррелирует с доходом). Говорят, что сайт часто отключается на 15 минут, и никого это особо не волнует. Если функция выведет сайт из строя, они откатят её обратно и повторят попытку позже. Повторные попытки дёшево стоят.

Насколько ценна новая функция для QwertyCo? Основываясь на моих личных наблюдениях, один месяц работы одного инженера способен изменить доход оптимизированного сайта в пределах от −2% до 1%. Это ежемесячный шанс получить 1 миллион долларов дополнительного дохода QwertyCo для каждого инженера. Такие методы, как A/B-тестирование, даже смягчают ошибки: в течение нескольких недель вы можете обнаружить негативные или нейтральные изменения и удалить эти функции. Плохие характеристики стоят дёшево — они активны конечное количество времени. Выигрыш же получается навсегда. Даже невысокий процент выигрышных ставок приносит прибыль QwertyCo.

С учётом плюсов и минусов, когда QwertyCo должна выпустить функцию? Экономический расчёт показывает, что даже высокорискованные функции следует запускать, если они иногда приносят прибыль. Соответственно, каждый проект превращается в оптимизационную игру: «Сколько можно реализовать к этой дате?», «Сколько времени требуется для реализации всего проекта? Что, если убрать из него X? Что, если убрать X и Y? Как ускорить реализацию определённой части?»

Теперь рассмотрим программный проект с точки зрения инженера-программиста.

У него основным ресурсом является время. Безопасная разработка программного обеспечения отнимает много времени. Как только продукт пересекает некоторый порог сложности, у него появляется несколько этапов разработки (даже если они не проходят в рамках явного процесса). Их следует планировать с помощью менеджера по продукту. Продукт преобразуется в технический проект или план, если это необходимо, делится на подзадачи. Затем пишется код с тестами, производится код-ревью, записывается статистика, продукт интегрируется с информационными панелями и оповещениями. Если необходимо, выполняется ручное тестирование. Кроме того, у кодирования часто есть дополнительный оверхед, известный как рефакторинг: изменение существующей системы, чтобы облегчить реализацию новой функции. В реализации «маленькой» функции непосредственно кодирование может занять всего 10-30% времени.

Как разработчики теряют время? Чаще всего это сбои системы. Во время простоя сайта все включаются в работу. Самые опытные инженеры останавливают текущие проекты, чтобы вернуть сайт в строй. Но время, потраченное на тушение пожара, — это время, когда они не приносят дополнительной пользы компании. Их проекты отстают от графика. Как уменьшить время простоя? Письменные тесты, мониторинг, автоматические уведомления и ручное тестирование — всё это снижает риск, что произойдут катастрофические события.

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

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

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

Как это влияет на управление проектами? Менеджеры и разработчики разделяют проект на небольшие задачи. Время выполнения проекта зависит от количества задач и количества инженеров. Чаще всего проект занимает слишком много времени — и его корректируют путём удаления функций. Затем инженеры выполняют поставленные задачи. Реализация задачи часто выполняется внутри «спринта». Если время спринта составляет две недели, то у каждой задачи неявный двухнедельный таймер. Однако задания часто занимают больше времени, чем вы думаете. Инженеры принимают жёсткие решения о приоритизации, чтобы закончить вовремя: «Я могу сделать это к концу спринта, если напишу базовые тесты и если я пропущу этот рефакторинг, который планировал». Спринты оказывают постоянное давление, подгоняя разработчика. Это означает, что инженер может либо пойти на компромисс по качеству, либо признать неудачу на следующей планёрке.

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

Установив такие стимулы, руководитель получает то, что хотел: он может назвать функцию и будущую дату, а менеджмент и разработчики обсудят, как это сделать. «Я хочу, чтобы вы в течение двух месяцев реализовали покупки в один клик без заведения аккаунта». Менеджеры и разработчики выпишут все задачи на две недели и будут сокращать список до тех пор, пока не смогут запустить функцию под названием «покупки в один клик». У неё будет умеренный риск сбоя и, вероятно, она заработает только через несколько итераций. Но сбой временный, а функция — навсегда.

Что произойдёт, если нарушены допущения такой экономической модели?

Как я уже говорил, мы хорошо делаем программное обеспечение при условии, что последствия неудачи не имеют значения. На это указывают лозунги «Двигайся быстро и всё ломай», «Выкатывай и повторяй». Но каждый может представить ситуацию, когда переделка обходится дорого или вообще невозможна. В крайнем случае, обрушение здания может убить тысячи людей и нанести ущерб на миллиарды долларов. Съезд фракций в Айове 2020 года — более мягкий пример. Если мероприятие провалится, вечером все разойдутся по домам живыми. Но партия не может организовать эти собрания во второй раз… не потратив много времени, денег и сил.

Краткое примечание: в этом разделе я употребляю фразу «высокорискованные» как сокращение для «ситуаций с невозможностью повторной попытки» и «ситуаций с дорогостоящей возможностью повторной попытки».

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

Во-первых, инженерная логистика: вы должны написать как приложение для Android, так и приложение для iPhone. Отчётность является центральным требованием, поэтому необходим сервер. Запутанные правила собрания должны быть закодированы как в клиенте, так и на сервере. Система должна сообщать о результатах конечному пользователю; это ещё один интерфейс, который необходимо запрограммировать. Демократическая партия, вероятно, имеет требования к проверке и отчётности, которые вы должны записать в приложение. К тому же, будет весьма некстати, если во время собрания выйдет из строя сервер, поэтому нужно внедрить какую-то систему мониторинга.

Далее, как проверять приложение? Один из вариантов — тестирование у пользователей. Вы показываете картинки гипотетического приложения потенциальным пользователям — и задаёте вопросы типа «Как вы думаете, что делает этот экран?» и «Если вы хотите добраться до $a_thing, куда вы нажмёте?» Дизайн всегда требует нескольких итераций, поэтому высокого качества разумно ожидать после нескольких раундов такого тестирования. Крупные компании часто проводят несколько раундов перед внедрением важных функций. Иногда даже отменяют функции после получения обратной связи, прежде чем написать хоть строчку кода. Пользовательское тестирование обходится дёшево. Разве трудно найти пять человек, которые уделят анкете 15 минут, получив в подарок подарочную карту за пять долларов? В нашем деле самое сложное — составить репрезентативную выборку, которая соответствует демократическим представителям штата Айова.

Затем нужно проверить приложение в деле: установить и настроить его на смартфоне. Демократическая партия должна понять, как получить результаты. В случае сбоя нужен план резервного копирования. Хороший тест может включать проведение «пробного собрания», где несколько членов Демократической партии Айовы загружают приложение и в заданную дату сообщают о результатах на центральный сервер. Это позволит выявить проблемы и обрисует общую ситуацию. Проверку можно проводить поэтапно по мере внедрения отдельных частей продукта.

Далее, в интернете полно негодяев. Например, российские группы широко распространяли дезинформацию через социальные медиа, такие как Facebook, Reddit и Twitter. Поэтому нужно убедиться, что не вмешается никто посторонний. Как проверить аутентичность результатов? Кроме негодяев, в интернете полно шутников, которые готовы сорвать любое мероприятие просто по приколу. Насколько наша система противостоит DDoS-атакам? Если нет, то есть ли запасной план? Кто несёт ответственность за введение запасного плана, сообщив об этом на собраниях? Что произойдёт, если учётные записи участников взломают? Если в компании нет экспертов по безопасности, вполне вероятно, что приложение должно пройти независимый аудит.

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

Ладно, прекратим перечислять проблемы. Понятно одно: требуется куча времени и ресурсов, чтобы убедиться, что всё работает.

Создателям приложения Iowa Caucus дали $60 000 и два месяца. У них было четыре программиста. Этой суммы недостаточно для зарплаты четырёх хороших программистов и остальных расходов. Деньги нельзя обменять на время. Помощи извне практически нет.

Представим, что вы применяете общепринятую практику удаления задач из проекта до тех пор, пока сроки не станут реально выполнимы. Вы сделаете всё возможное, чтобы сэкономить время. Предварительный обзор для каталога приложений часто занимает меньше дня, но в худшем случае может растянуться на неделю, а приложение могут отклонить. Так что давайте пропустим это: члены Демократической партии будут загружать приложение через ссылки для бета-тестирования. Даже с бесплатной проверкой безопасности потребуется слишком много времени, чтобы выполнить все их рекомендации. Поэтому отказываемся от проверки безопасности. Возможно, во время разработки бэкенда вы заплатили дизайнеру $1000 за создание макета приложения и логотипа. Вы планируете один раунд пользовательского тестирования (но затем пропустите его, когда сроки выйдут). Выкатывай быстро и повторяй цикл! Всё всегда можно исправить.

А программирование всегда занимает больше времени, чем ожидалось! Вы столкнётесь с затыками. Во-первых, правила проведения собраний не совсем ясные. Это всегда выясняется, когда цифровое решение накладывают на аналоговый мир. Реальный мир может смириться с неоднозначностью и непоследовательностью, а цифровой мир — нет. В ответ на ваши вопросы комитет Демократической партии подготовит разъяснения. Это задержит вас. Комитет также может изменить правила в последнюю секунду. Это приведёт к тому, что вы измените приложение перед самым дедлайном. Далее, у вас несколько разработчиков, что означает оверхед на координацию. Каждый ли кодер на 100% разбирается и в мобильной, и в серверной разработке? Все ли они в совершенстве владеют React Native? JS? Typescript? Клиент-серверными коммуникациями? Какие именно фреймворки и библиотеки вы выбрали? Каждое «Нет» добавляет времени на разработку, чтобы учесть координацию и обучение. Все ли довольны тестовыми фреймворками, которые вы используете? Просто шучу. Какие там тесты… Да, сначала написали пару тестов, но приложение так быстро изменилось, что их удалили.

Время не ждёт. Два месяца истекли — вы из последних сил добираетесь до финиша и выпускаете финальный релиз.

Исходя из экономической модели веб-сайта, финишировать впопыхах — это хорошо. В конце концов, спешка не имеет значения, ведь вы пересекли финишную черту! Все проблемы можно решить в течение нескольких недель, а затем перейти к следующему проекту.

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

Выводы

Это эссе помогло лично мне сделать вывод: при планировании проекта нужно формализовать стоимость переделки. Я интуитивно делал это в прошлом, но её следует внятно конкретизировать. Такая формализация помогает понять, какие задачи нельзя провалить ни в коем случае. Это как было у меня в мобильной робототехнике: там длинные циклы внедрения, а ущерб от сбоя мог зашкаливать. Мы тратили много времени на разработку мониторинга и создание надёжных способов подавления и остановки вышедших из-под контроля систем. Я также в течение десяти лет работал с потребительскими веб-сервисами, где последствия неудачи ниже. Здесь выше готовность брать краткосрочные долги и продвигаться вперёд с риском временного сбоя, особенно когда откат обходится дёшево, а потеря данных маловероятна. По крайней мере, стимулы подталкивают именно к такому поведению. В нашей отрасли есть специальные методики для предотвращения подобных проблем. Одна из них — расследование воображаемых сбоев (pre-mortem). Нужно почаще этим заниматься.

У айовского провала есть и положительный результат. Некоторые не имеющие отношения к IT поняли, что в программах бывают ошибки. В ближайшие годы спонсоры разработки приложений для политических партий начнут спрашивать: «Какие гарантии, что не повторится ситуация со Съездом фракций в Айове?» Возможно, они познакомятся с литературой, которая пытается научить менеджеров, как правильно работать с инженерами. Например, у Министерства обороны США есть руководство под названием «Как распознать липовые проекты Agile», которое описывает подозрительные признаки при заключении контракта. На форумах для стартаперов полно нетехнарей, которые просят (и получают) советы по найму разработчиков.

IT-индустрия ничему не научилась. Съезд фракций в Айове дал шанс изучить, как предположение о «высокой стоимости ошибки» изменит наши основные процессы. Но мы не воспользовались этой возможностью и ничего из неё не извлекли. Индустрия потребительского ПО не обращает внимания на риски ошибок. Фактически, мы даже радуемся ошибкам. Если внешний мир заинтересован в повышении качества нашего кода в определённых областях, то они должны регулировать эти области. Это будет не первый случай. Закон Сарбейнза — Оксли и HIPAA — вот примеры регулирования в сфере разработки с экономической моделью веб-сайта. Регулирования недостаточно, но может оказаться, что оно необходимо.

Вот что мы имеем в виду, когда говорим: «Не совсем знаю, как это выразить, но вся наша область плоха в том, что мы делаем, и если вы будете полагаться на нас, то все умрут». Наша индустрия формировалась в условиях, когда неудачи обходятся дёшево. А мы заинтересованы в быстром прогрессе. Если переделка невозможна или слишком дорого обойдётся, то наши привычные процессы работают плохо.

Обсудить в форуме