Последние два десятилетия были революционными в разработке программного обеспечения. Объектно-ориентированное проектирование и анализ, паттерны проектирования, независимая и сервис-ориентированная архитектура и другие инновации дали разработчикам шаблоны и инструменты для технического совершенствования в каждом проекте.
Но это не значит, что agile-команды тратят массу времени на создание крупномасштабных конструкций в начале каждого программного проекта. Agile-разработчики приобретают большое количество навыков, помогающих им создавать хорошо спроектированный код. Они находятся в постоянном поиске дизайна и ошибок в коде и немедленно их исправляют. Если во время работы над проектом уделять немного больше внимания написанию надежного кода и исправлению ошибок, то можно создать надежную основу кода, которую можно легко поддерживать в будущем.
Команда проекта «Электронная книга» и их домочадцы наверняка бы оценили стабильные темпы работы. Но и сам проект должен получиться лучше. С самого первого дня команда была обречена работать сверхурочно, потому что просто не имела средств для создания реалистичного плана, который оставался бы точным полтора года спустя.
Еще хуже то, что в самом начале проекта команда заложила дизайн программного обеспечения и архитектуру для поддержания очень подробной спецификации. В итоге получился крайне сложный код, который трудно расширить. Это привело к большому количеству изменений в коде и к такому же числу «заплаток», которые запутывают код. Если бы команда придерживалась итеративного подхода и поставляла рабочее ПО на протяжении всего проекта, то могла бы планировать каждую итерацию для сохранения стабильного темпа работы. Упрощенный подход just-in-time («точно вовремя») к архитектуре позволил бы создать более гибкий и расширяемый дизайн.
Давайте представим, что наша команда проекта «Электронная книга» применила эти принципы и сейчас они похожи на хорошо отлаженную машину по производству программного обеспечения. Они регулярно воспроизводят и поставляют работающее программное обеспечение и постоянно корректируют работу, чтобы быть уверенными в умении создавать ценное ПО. Члены команды хорошо коммуницируют, документируют только то, что им действительно нужно, используют методы проектирования и строительства, позволяющие создавать обслуживаемый код. И все это – без необходимости работать сверхурочно. Наша команда стала гибкой!
Но грозовые тучи уже сгущаются над следующим проектом. Новый менеджер просто разослал приглашения на общую встречу всем, кого смог найти. Участники приняли приглашения и начали бронировать номера, аргументы в пользу необходимых требований, которые нужно было задокументировать, витают в воздухе… и все в новоиспеченной agile-команде почувствовали, как у них засосало под ложечкой.
Команда понимает, что происходит. Первые из многочисленных спецификаций, планов и диаграмм Ганта только начинают циркулировать. Как убедиться, что следующий проект не попадет в ловушку, из которой они с таким трудом выбирались?
Постоянное совершенствование проекта и команды
Один из основных принципов проектирования не только программного обеспечения, но и во всем инженерном деле – это KISS[23] («чем проще, тем лучше»). Agile-команда живет по этому принципу, когда планирует проект, разрабатывает программное обеспечение и движется вперед.
Часто бывает довольно сложно добавить код в существующий проект, особенно если дописываемый код зависит от уже существующего. Зависимости между системами, объектами, услугами и прочим делают код более сложным и трудно изменяемым: зависимости повышают вероятность того, что одно изменение может привести к каскадным изменениям в другой части системы, которые, в свою очередь, вызовут изменения в третьей, создавая эффект домино с возрастающей сложностью для каждого изменения. При помощи итераций и создания минимальной документации в начале проекта команда может избежать поставки ненужного программного обеспечения.
Однако многие разработчики испытывают неловкость, когда впервые слышат фразы вроде «использование итеративной разработки» и «сделать минимальный объем планирования, необходимого для запуска проекта». Они чувствуют, что преждевременно писать код, пока не рассмотрены и не записаны разные варианты конструктивных и архитектурных решений. Иначе написанный сегодня код придется удалять завтра в процессе изменений в дизайне.
Это понятная реакция, ведь для многих проектов вне сферы разработки программного обеспечения такой подход не имеет смысла. Нередко программисты, только что вступившие в сферу agile-разработки, выдвигают возражения такого рода: «Если подрядчик ремонтирует мой дом, то первым делом я хочу видеть подробные чертежи. Я не допущу, чтобы, второпях поговорив со мной, он начал ломать стены».
Этот аргумент имеет смысл в ситуации с ремонтом дома. Дело в том, что в этом случае нет ничего более разрушительного, чем взять кувалду и сломать стену. Но программные проекты отличаются от домов и прочих физических объектов. Удаление кода не несет глобальных разрушений, потому что вы легко можете восстановить его из системы управления версиями. Самая разрушительная вещь для вашего проекта – это создать новый код, а затем другой, зависимый от первого, и так далее, как выстраивают костяшки домино. Получится до боли знакомый эффект каскадных изменений… И в итоге вы останетесь с неремонтопригодным, запутанным спагетти-кодом.
Максимальное увеличение объема работы не поможет избежать этой путаницы. Лучше создавать систему без большого количества зависимостей и ненужного кода. Наиболее эффективный способ создания максимально полезного и ценного программного обеспечения – это работа с клиентами и заинтересованными сторонами. Если функция не является ценной, то в долгосрочной перспективе для компании дешевле не создавать ее вовсе. Потому что расходы на содержание дополнительного кода выше, чем стоимость самой разработки. Когда команды пишут код, они могут хранить свои несложные проекты программного обеспечения, создавая дизайн ПО на базе небольших автономных единиц (например, классов, модулей, сервисов и т. д.), которые делают только одну вещь – помогают избежать эффекта домино[24].
Слишком сложные конструкции характерны для команд, которые уделяют чересчур много внимания планированию. Неудивительно, если задуматься об этом. Вернемся к главе 2 и рассмотрим картину водопадного процесса. В водопадной методологии выделяют целые этапы, посвященные разработке требований, дизайну и архитектуре. Наиболее тщательно выполненные работы на этапе дизайна и архитектуры предполагают создание самой удивительной структуры, которую команда только может придумать. Работающие таким образом интуитивно воспринимают небольшое количество требований и простой дизайн как недоработанный проект. Стоит ли удивляться, что они возвращаются с большим списком требований и сложной архитектурой? Конечно, нет, потому что это именно то, что они просят сделать. Ведь им известно: в водопадном подходе каждый этап должен быть подкреплен соответствующей документацией.
Но самоорганизующаяся команда не имеет явных требований или фаз разработки. Ее члены совместными усилиями планируют проект (вместо того чтобы полагаться на одного человека, «владельца» плана) и регулярно его пересматривают. Такие команды, как правило, разбивают проект на пользовательские истории или другие мелкие части и начинают работать с наиболее ценными для компании частями. Только после этого подходит очередь подробных требований, дизайна и архитектуры.
Это делает работу традиционного архитектора программного обеспечения сложнее, но и приятнее. Обычно программный архитектор сидит в кабинете с закрытой дверью и абстрактно рассуждает о проблемах, которые нужно решать. Конечно, бывают исключения, но для них типично отдаляться от повседневной работы остальной группы.