В предыдущем посте мы рассказали о гибких методологиях разработки — Scrum и экстремальном программировании (если вы еще не читали о них — сделайте это!) Но на этом список Agile-методологий не заканчивается.
Бережливое производство подразумевает сокращение всех возможных потерь, экономичный и разумный подход к производственным ресурсам. Речь не только о потерях времени или растрате финансов и труда, но и нереализованном творческом потенциале сотрудников. Впервые эту систему использовала компания Toyota, а затем ее внедрили и многие другие производства.
Для разработки ПО эту методологию адаптировали в 2003 году программисты Мэри и Том Поппендик. Они написали книгу «Бережливое производство программного обеспечения» («Lean Software Development: An Agile Toolkit»), в которой изложили принципы и практики бережливой разработки.
Принципов всего семь:
- Ликвидировать потери.
- Встраивать качество.
- Создавать знание.
- Откладывать необратимые решения.
- Доставлять быстро.
- Уважать людей.
- Оптимизировать целое.
Рассмотрим их по порядку.
Исключайте потери
Понятие потерь появилось еще в производственной системе Toyota и подразумевало ненужные затраты финансов, времени, труда, а также брак, чрезмерные запасы, нерациональную транспортировку, бюрократию и даже потери из-за перепроизводства — ведь произведенную, но невостребованную продукцию нужно где-то хранить. Потери — это все, что не увеличивает потребительскую ценность продукта.
Эту схему можно применить и к разработке ПО. В ней тоже есть моменты, исключение которых делает продукт качественнее, его производство и доставку потребителю — быстрее, а разработчика — немного счастливее: поработает он меньше, а оплата труда возрастет.
В первую очередь затраты необходимо выявить. А для этого важно понимать, что в программном продукте представляет потребительскую ценность — то есть в чем именно нуждаются пользователи.
Любую функциональность, которая не требуется пользователю, можно отнести к потерям, как и задержки в выполнении работы.
В обычном производстве источником затрат становятся избыточные запасы деталей, запчастей и материалов. Их необходимо хранить, вести учет, перемещать. Они могут приходить в негодность, теряться или устаревать.
В IT аналог таких запасов — незаконченная работа. Код, который долго остается незавершенным, висит мертвым грузом, устаревая и теряя пригодность. Вложенные в его создание время, усилия и средства оказываются потраченными напрасно. Правило бережливой разработки — постоянный контроль за тем, чтобы незавершенного кода в программе не было: либо код дописан и работает, либо он не должен создаваться вообще.
Еще один источник потерь — усилия и время, затраченные на устранение ошибок и внесение изменений в созданную функциональность. Разумеется, если баг есть — его надо исправлять. Но лучше создавать код без ошибок или выявлять их как можно раньше.
Как все гибкие методологии, бережливая разработка внимательно относится к потребностям и пожеланиям пользователей, поэтому сами по себе переделки не всегда можно записать в потери. По данным Мэри и Тома Поппендик, от 30 до 50 % изначальных требований к продукту к концу разработки обычно меняются. Но бывают и иные ситуации.
Например, когда тестирование кода выполняется с задержкой. В результате дефект обнаруживается, когда уже разрабатывается новый участок программы. Разработчикам приходится возвращаться к старому коду. А если новая функциональность на нем основана, надо исправлять и ее.
Но самой серьезной проблемой авторы считают избыточные возможности. По статистике, лишь 20 % функциональности в типичной программе используется постоянно. Около ⅔ применяется редко или никогда. Получается, что до 66 % программного кода создается бесцельно. Можно представить, каких колоссальных затрат времени и труда можно избежать, если просто не создавать эту ненужную функциональность. Неиспользуемый код не только делает программу сложнее и медлительнее — он требует тестирования, документирования, технической поддержки, доработки.
Это может показаться странным, но исчерпывающее техзадание не решает эту проблему, а только усугубляет ее. Заказчик редко ясно представляет себе, как должно выглядеть итоговое решение, — и вписывает все, что может вообразить, на всякий случай.
Первая задача разработчика — понять, что именно нужно пользователю, а что ему не пригодится. Стоит определить основной набор функциональных возможностей, которые покроют 80 % потребностей заказчика, и лишь потом приступать к улучшениям и «наворотам» — только если без них действительно не обойтись.
Разрабатывайте через тестирование
Для чего проводится тестирование программного кода?
Большинство разработчиков ответят: чтобы выявить ошибки и исправить их!
И ошибутся.
Представим, что программист написал большой программный блок, который последовательно выполняет несколько этапов вычислений. Он передает его тестировщику, и тот обнаруживает на первом этапе ошибку. Дальнейшее тестирование невозможно, так как последующие этапы используют некорректно вычисленные данные. Код возвращается к программисту. Тот отвлекается от работы над следующим блоком и вносит исправления. Тестировщик снова запускает программу и обнаруживает, что первый этап отработал корректно, но теперь неправильные результаты получаются на втором.
Тестирование готового кода по такой схеме может растянуться на дни и недели. Выпуск очередной версии откладывается, пользователи негодуют.
Но есть и альтернативный взгляд: тестирование должно предотвращать дефекты в коде.
Цель бережливой разработки — не улучшить тестирование готового продукта, а повысить качество самого кода. То есть сделать так, чтобы ошибок не было изначально.
Для этого необходима дисциплина в коллективе и самодисциплина каждого члена команды — по принципам профессионализма в духе Agile. И тестирование следует интегрировать прямо в процесс разработки. Авторы методологии рекомендуют разработку через тестирование — Test driven development, или TDD. Автоматизированный тестовый модуль создается раньше участка кода, а разработка при этом разбивается на множество мелких фрагментов — и для каждого предусматривается собственный тест. Когда фрагмент создан, тестовый модуль запускается и проверяет, насколько результат работы соответствует ожидаемому. Такое тестирование выполняется максимально часто — каждый час или около того, — чтобы убедиться, что с момента прошлой проверки не появились ошибки. Если баг обнаруживается, код переделывают «по горячим следам», пока все не заработает идеально. В конце дня тестовая нагрузка запускается еще раз, а еженедельно выполняются более сложные комплексные тесты. Такая организация работы позволяет практически полностью исключить ошибки в программном коде. И финальная проверка при TDD проходит существенно быстрее.
Создавайте знание
Под знанием авторы методологии подразумевают комплекс всей информации, описывающей программный продукт и его разработку: техническое задание, спецификации, архитектуру, документацию, ожидания и потребности пользователей, а также все те подходы, методы, способы решения задач, которые используются при его создании. Сюда же входит и опыт разработчика, который при работе над продуктом должен совершенствоваться.
Практика показывает, что даже самое подробное техническое задание не страхует от сложностей и непредвиденных ситуаций при разработке. А так как ТЗ часто подготавливает человек, не знакомый с тонкостями программирования, риск становится еще больше.
Поэтому техзадание заказчик и разработчик должны создавать совместно — и не единовременно, а на протяжении всего срока разработки, небольшими частями, описывающими отдельные функциональные модули.
Быстрый выпуск новых рабочих версий, постоянная вовлеченность заказчика в работу, учет новых, актуальных требований пользователей — все это помогает сделать программу более эффективной и востребованной. А команда разработчиков получает новый опыт, основанный на понимании потребностей заказчика.
Откладывайте необратимые решения
Планирование — это прекрасная практика. Оно позволяет задавать перспективы развития программного продукта, продумывать расходование ресурсов и формировать бюджет проекта. Да и руководство зачастую требует от работников, чтобы результат их действий был предсказуемым.
Но жизнь не руководствуется нашими планами, а прогнозы становятся тем менее точными, чем более конкретный и сложный план мы выстроим. И методологии Agile не назывались бы гибкими, если бы каждый шаг в них был регламентирован.
Разработчику следует всегда быть готовым к тому, что планы могут внезапно и кардинально измениться. Хорошо, если пользователь просто попросит изменить детали интерфейса. Но может и потребоваться поменять всю концепцию большого и сложного модуля.
Разработчику порой приходится принимать глобальные решения, влияющие на весь дальнейший ход работы над продуктом. Иногда бывает, что эти решения нельзя пересмотреть и «откатиться» к исходной точке. Например, при выборе языка программирования, который станет основой проекта. Ведь от этого будет зависеть буквально все в программном продукте — его функциональные возможности, быстродействие, мультиплатформенность. И это решение невозможно изменить в середине разработки.
Время от времени такие ситуации возникают и на более поздних стадиях разработки. Вы можете обнаружить, что библиотека классов, приобретенная у стороннего разработчика, не полностью соответствует вашим потребностям — придется либо самостоятельно разрабатывать аналогичные, но более функциональные классы, либо переходить на альтернативную библиотеку. Оба варианта — это потери времени, усилий, финансов.
Принцип бережливой разработки — максимально откладывать необратимые решения. Собирать предварительно всю информацию, которая может пригодиться, взвесить все за и против, обдумать последствия, вероятные проблемы и способы их преодолеть. Решение должно быть принято тогда, когда само промедление уже грозит потерями и затратами.
Опытный руководитель должен развить интуитивное чутье, которое позволит принимать решения своевременно — не позже, но и не раньше ключевого момента.
Выбор языка программирования следовало бы сделать не ранее, чем будут обозначены и сформулированы все основные требования заказчика. Когда станет понятно, на каком оборудовании пользователи будут запускать программу, как собираются ее использовать, какое дополнительное программное обеспечение должно взаимодействовать с программой.
А внешние библиотеки следует приобретать и подключать к проекту не ранее, чем будут протестированы пробные версии, изучены спецификации и совместимость с вашим продуктом. А главное — когда появится реальная необходимость в использовании именно этих библиотек.
Доставляйте быстро
Программа, как пицца, должна быть доставлена пользователю с пылу с жару.
Представьте себе, что вы доставляете пиццу клиентам не за час, а в течение суток. За это время заказчик может захотеть другую начинку, суши или вообще наесться картошкой. Да и пицца успеет остыть и зачерстветь.
То же самое происходит, когда вы тянете с релизом. Функциональность, которая была жизненно необходима два месяца назад, сегодня может оказаться уже невостребованной. Следовательно, придется снова перекраивать код.
Но есть и другая крайность. Ускоряя процесс разработки, нельзя приносить в жертву качество. Клиенту было бы приятно получить пиццу через 15 минут после заказа — но если она окажется сырой, вряд ли он будет доволен. Программа с ошибками хуже любой задержки — ведь пользователь будет вынужден фиксировать сбои, сообщать о них разработчику, а затем ожидать новую версию и терять время.
Избежать этого сможет только коллектив мотивированных профессионалов, способных оперативно решать проблемы, не дожидаясь указаний сверху. Если процессы налажены, а разработчики заинтересованы в результате, то и продуктивность будет возрастать при сохранении качества.
Многие организации (в том числе работающие по принципам бережливой разработки) составляют планы, спецификации и стандарты для отдельных видов работ или разработки в целом. Это помогает поддерживать темп работы, но нужно помнить, что Agile-методологии отводят планированию и регламентации второстепенную роль: куда важнее гибкость и умение адаптироваться под изменяющиеся условия.
Уважайте сотрудников
Программист и IT-бизнесмен Джоэл Спольски в 1991 году, едва закончив колледж, устроился в Microsoft, где ему поручили разработать стратегию языка макросов на базе Basic для Excel. Он изучил требования и пожелания пользователей, но, составив спецификации, с удивлением обнаружил, что команда не спешит их выполнять. «Возможно, у них есть интересные мысли, и я должен это выяснить», — решил Спольски. Причины оказались прозаичнее: старшие и более опытные коллеги просто не хотели выслушивать мнение новичка. Один из руководителей проекта Excel, водивший дружбу с самим Биллом Гейтсом, даже организовывал совещания, на которых жаловался, что Спольски «вносит путаницу в создание стратегии макросов».
Более высокому руководству удалось разобраться в вопросе и понять, что предложенная вчерашним студентом стратегия будет отлично работать, а члены команды имеют слабое представление о том, что именно пользователям требуется от макросов. Спецификации Спольски были реализованы.
Уважать сотрудников — значит прислушиваться к их мнениям, давать оценку с точки зрения разумности и полезности, а не по регалиям или стажу. Даже самый заслуженный и опытный специалист, проработавший в компании многие годы, может проиграть в споре сотруднику, взятому пару месяцев назад прямо из вуза. Хороший руководитель всегда оценивает качество идей, а не сотрудников, которые их выдвигают.
Уважение также проявляется в том, насколько свободно каждый из специалистов может высказывать и отстаивать свое мнение. Было бы крайне неразумно сначала набрать в команду квалифицированных и талантливых специалистов, а затем навязывать им чужое мнение. Наиболее эффективный подход — обозначить коллективу задачу и ожидаемый результат, а затем предоставить свободу в поиске решения.
Руководитель, уважающий своих коллег и подчиненных, собирает вокруг себя думающих и увлеченных работников, способных сообща создавать успешные проекты. И напротив, коллективы, где мнение «заслуженных», «приближенных» или «избранных» ценится выше остальных, — погрязают во внутренних проблемах, а лучшие специалисты при первой возможности покидают такие команды.
Часто бывает так, что руководство вырабатывает стандарты работы, стремясь повысить продуктивность. Но они оказываются поверхностными и создают бюрократическую волокиту. Так случается, когда начальник не имеет реального представления о работе и не допускает мысли, что кто-то может лучше него знать, как ее улучшить.
Оптимизируйте целое
Мы часто рассматриваем сложные комплексные явления как набор более простых. Поэтому когда речь заходит об оптимизации процесса, чаще всего задумываемся, какие его этапы нуждаются в улучшении. На каком шаге затрачиваются лишние ресурсы, время или усилия? Где и как увеличить скорость работы?
Но практика показывает, что при оптимизации частностей процесс в целом зачастую замедляется и усложняется. Рассматривая отдельные элементы работы, мы оцениваем их эффективность в отрыве от целого. Разработчику важно всегда иметь в виду главную цель: создать программный продукт. И оптимизацию необходимо производить, начиная с процесса в целом.
В этом может помочь диагностический инструмент — карта потока создания ценности (value stream map). Это график работ, который начинается с получения заказа (технического задания на разработку программы) и заканчивается передачей пользователю готового решения. Таким образом, карта начинается с заказчика и заканчивается на нем, а между этими двумя точками располагаются в порядке выполнения все технологические этапы разработки. Для каждого указывается среднее время исполнения.
Карты позволяют быстро выявить те точки (процессы), которые вызывают потери времени. И вместо того чтобы ускорять конкретный процесс, разработчик может быстрее разобраться, что именно мешает работе.
Рассмотрим ситуацию, когда заказчику требуется оперативно внести изменения в функциональность программы. Составим карту потока создания ценности:

Чтобы сформулировать проблему и составить заявку, заказчику нужно всего пять минут. Он отправляет заявку на имейл диспетчеру, который мониторит почту в среднем каждые два часа и санкционирует выполнение задачи. Для этого ему нужно всего две минуты — просто убедиться, что вопрос нуждается в решении. Он перенаправляет письмо с заявкой ведущему разработчику для технической оценки. Тот тоже просматривает почту в среднем каждые два часа — следовательно, в самом неудачном случае на этом этапе будет потеряно еще 120 минут. Оценка проводится достаточно быстро, после чего ведущий разработчик определяет, кто из его свободных специалистов обладает нужными компетенциями и навыками, чтобы решить проблему. На это уходит еще час.
Разработка и оперативное тестирование занимают в общей сложности два часа. Готовая версия программы передается на финальную верификацию, а затем отправляется заказчику.
Запишем продолжительность каждого этапа, сразу отмечая время, потраченное непосредственно на создание ценности (в первой строчке) и на простои и ожидание (в нижней строке). Посчитаем: всего на создание ценности ушло 160 минут (причем большая часть — на разработку и тестирование). А вот потери превысили это время вдвое: 325 минут! На весь цикл потребовалось 8 часов — полный рабочий день, из которого лишь 2 часа 40 минут было затрачено на реальную работу.
В данном примере очевидно, что можно исключить из цепочки диспетчера, а обязанности по санкционированию передать ведущему разработчику. Это сэкономит в среднем два часа и повысит эффективность почти на 45 %.
Подобные карты можно составить для всех регулярных процессов. Исключение потерь не только ускоряет выполнение работы в целом, но и повышает качество продукта: ведь в итоге у разработчика останется больше времени на написание кода, а у тестировщика — на его проверку.
Инструментарий бережливого разработчика
Как и все Agile-методологии, бережливая разработка сконцентрирована на максимально быстром получении программного продукта, но добивается этого не за счет особых техник и методик, как экстремальное программирование, или строгой дисциплины, как Scrum, а благодаря сокращению затрат труда, времени и прочих ресурсов.
Тем не менее бережливая разработка взяла лучшее от методологий, существовавших до нее. Ее авторы рекомендуют:
- стандартизировать программный код (то есть использовать определенные заранее стандарты в наименовании переменных и классов, создании кода, файловых структурах и т. д.);
- использовать парное программирование;
- встраивать защиту от ошибок — создавать код и пользовательский интерфейс, которые исключают возможность случайно совершить опасные некорректные действия («защита от дурака»);
- автоматизировать рутинные задачи (например, создавать скрипты для автоматической сборки новых версий, выполнение сборок по расписанию);
- практиковать непрерывную интеграцию (то есть регулярное добавление измененного кода в общее пространство. Это позволяет каждому разработчику постоянно иметь доступ к наиболее свежей версии каждого фрагмента кода);
- И т. д.
Еще есть специальная техника бережливости, нацеленная на обустройство рабочего пространства сотрудников. Это «Пять S» (5S) — по первым буквам слов sort (сортировать), systematize (систематизировать), shine (чистить), standardize (стандартизировать) и sustain (поддерживать). Поскольку методология бережливого производства возникла в Японии, там аналогичные понятия обозначаются пятью японскими словами, которые тоже начинаются звуком «с».
Пять простых правил помогают обеспечивать идеальный порядок как на рабочем месте программиста, так и в компьютере, на серверах и в программном коде.
-
Сортировать — проведите инспекцию своего стола и жесткого диска. Удалите все ненужное: старые версии программы, неиспользуемый софт, устаревшие отчеты и документы (при необходимости можно создать резервную копию).
-
Систематизировать — разложите все «по полочкам», наведите порядок. Создайте удобную и логично устроенную структуру папок, которая позволит быстро находить нужные файлы. Ярлыки часто используемых программ и документов следует разместить на рабочем столе или закрепить в панели инструментов, редко используемые — переместить в меню «Пуск» или соответствующие подпапки. Придерживайтесь одной системы на всех компьютерах. Рабочая среда должна быть такой, чтобы каждый специалист из команды мог найти в ней необходимое, войдя в систему с любого компьютера.
-
Чистить — мусор надо отправлять в корзину, будь то бумажный стакан из-под кофе или временный файл с черновиком документа. Наброски алгоритмов и кода, сделанные на клочках бумаги, стоит перенести в файлы, а бумагу выбросить или подшить в папку (если нужно). И протереть монитор от пыли!
-
Стандартизировать — обеспечьте единую конфигурацию программных средств на всех рабочих станциях. У команды разработчиков, трудящихся над одним проектом, должна быть установлена одна версия среды разработки и программных средств — чтобы не было проблем с совместимостью. На всех машинах должен быть идентичный набор программного обеспечения.
-
Поддерживать. Навели порядок — соблюдайте его.
Бережливую разработку выгодно отличает от многих других методологий то, что здесь во главу поставлен сам процесс создания продукта и его результат. Все, что этому не способствует, должно быть исключено. Благодаря бережливой разработке команда может избавиться от бесполезной бумажной работы и бюрократических проволочек, от лишних и непродуктивных операций. Следуя принципам этой методологии, разработчики смогут сосредоточиться на работе, приносящей реальные результаты. В итоге сократятся затраты и время разработки, вырастет качество и прибыль.