Правила ХР (Часть 2)
Парное программирование
Весь код для продукционной системы (а это значит за исключением пробных решений) пишется парами. Два разработчика сидят рядом. Один набирает, другой смотрит. Время от времени они меняются. Не разрешается работать в одиночку. Если по какой-то причине второй из пары пропустил что-то (болел, отходил и т.п.) он обязан просмотреть все изменения сделанные первым.
Звучит необычно, но XP утверждает что после небольшого периода адаптации большинство людей прекрасно работают в парах. Им даже нравится, поскольку работа делается заметно быстрее. Действует принцип “Одна голова хорошо, а две лучше”. Пары обычно находят более оптимальные решения. Кроме того существенно увеличивается качество кода, снижается число ошибок и ускоряется обмен знаниями между разработчиками.
Безжалостно Рефакторить!
Мы, программисты, склонны держаться за дизайн долго после того как он становится неуклюжим. Мы продолжаем повторно использовать неудобный в сопровождении код поскольку он все еще как-то работает и мы боимся испортить его. Но действительно ли это выгодно? XP принимает точку зрения что это невыгодно. Когда мы убираем избыточность, улучшаем устаревший дизайн убираем неиспользуемые куски - мы делаем рефакторинг. Рефакторинг в конечном итоге экономит время и улучшает качество продукта.
Безжалостно пересматривайте любой код для того, чтобы сохранять дизайн простым по мере разработки. Сохраняйте код ясным и понятным чтобы его было легко понять, модифицировать и расширять. Удостоверьтесь что все написано один и только один раз. В конечном итоге, это занимает меньше времени чем доводить до ума запутанную систему.
***
Медленно и со скрипом начинаем рефакторить нашу систему. Дело осложняет огромное количество старого кода который в большинстве не имеет никаких UnitTest-ов.
Часто разработчики не понимают что рефакторить - не значит переписывать заново. В результате, вместо маленьких понятных изменений, сохраняющих работоспособность системы в любой момент, разработчик переписывает код заново, а потом проводит полдня в отладчике, а потом исправляет все ошибки, которые уже были исправлены в старом некрасивом коде.
Уже сейчас видно, что когда мы отрефакторим всю нашу систему, мы выбросим от 30% до 50% всего кода, сохранив ту же самую функциональность. При это система будет ясной, понятной и надежной.
План Релиза
План Релиза разрабатывается на собрании по планированию Релиза. Релиз План-ы описывают взгляд на весь проект и используются в дальнейшем для планирования итераций.
Важно чтобы технические люди делали технические решения и люди бизнеса - бизнес решения. Планирование Релиза определяет набор правил которые позволяют всем принимать свои решения. Эти правила определяют метод выработки удовлетворяющего всех плана работ.
Сущность собрания по планированию релиза для команды разработчиков в том, чтобы оценить каждую User Story в идеальных неделях. Идеальная неделя - это сколько по-вашему займет время выполнение задачи если ничто больше вас не будет отвлекать. Ни зависимостей, ни дополнительных задач, но включая тесты. Заказчик затем решает какие задачи наиболее важны или имеют более высокий приоритет.
User Stories записываются на карточках. Разработчики и Заказчик вместе тасуют карточки на столе пока не получится набор User Stories которые вместе будут составлять первый (или следующий) Релиз. Всем хочется выпустить как можно раньше полезную систему которую можно протестировать.
Релиз можно планировать по времени или по обьему. Для того чтобы определить сколько User Stories могут быть реализованы к конкретной дате или сколько реального времени займет данный набор задач используют скорость проекта. Если планируете по времени, умножте количество итераций на скорость проекта для того чтобы узнать сколько User Story может быть реализовано. При планировании по обьему, разделите общее количество идеальных недель необходимых для всех User Stories на скорость проекта и вы получите количество итераций необходимых для окончания релиза.
Если менеджмент не устраивают сроки завершения, может появиться соблазн уменьшить оценки обьема работ. Вы никогда не должны этого делать. Заниженные оценки обязательно создадут множество проблем позже. Вместо этого ведите переговоры с менежерами, разработчиками и заказчиками пока не выработает приемлемый для всех план релиза.
***
Собственно планирование не представляет проблем, спасибо книге Planning Extreme Programming. Бизнесмены (в нашем случае отдел Маркетинга и Продаж) кажется привыкли и уже не требуют всего сразу и вчера.
Частые Релизы
Разработчики должны выпускать версии системы пользователям (или бета-тестерам) как можно чаще.
Планирование Релиза используется для поиска небольших функциональных фрагментов имеющих значимый бизнес-смысл и которые могут быть выпущены в реальное окружение на ранних стадиях разработки. Это критично для получения полезных отзывов во время чтобы иметь возможность влиять на процесс разработки. Чем больше вы задерживаете выпуск важной части системы тем меньше у вас будет времени исправить ее.
***
Ежедневные билды позволяют иметь полную инсталляцию каждый день без дополнительных усилий. То есть показать что-нибудь мы можем в любой момент.
С выдачей релиза у нас проблема - не все тесты еще автоматизированы и цикл тестирования перед выпуском релиза занимает две-три недели. Таким образом, пока нецелесообразно выпускать релизы чаще чем раз в два-три месяца. Но эта ситуация исправляется, так что вскоре мы сможем давать обновленные версии избранным пользователям каждый месяц.
Пробное решение
Создавайте пробные решения для ответа на сложные технические вопросы, для обоснования тех или иных технологических решений. При принятии любого технологического решения существует риск и пробные решения призваны уменьшить его.
Сделайте программу которая воспроизводит исследуемую проблему и игнорирует все остальное. Большинство пробных решений не предназначены для последующего использования так что ожидайте что они будут выброшены. Цель их создания - уменьшить риск принятия неправильного технического решения или более точная оценка времени на реализацию User Story.
***
Это требование несложно выполнить и оно очень помогает. Многие любят экспериментировать, особенно когда не надо тратить время на качество кода. Менеджеру стоит следить чтобы пробные решения не превращались в код системы, потому что обычно это не очень хороший код, написанный в одиночку и не имеющий никаких тестов.
Собрание стоя
Каждое утро проводится собрание для обсуждения проблем, их решений и для усиления концентрации команды. Собрание проводится стоя для избежания длительных дискуссий не интересных всем членам команды.
В типичном собрании большинство участников ничего не вносят, просто участвуют чтобы послушать что скажут другие. Большое количество времени людей тратится чтобы получить небольшое количество коммуникации. Поэтому участие всех людей в собраниях уводит ресурсы из проекта и создает хаос в планировании.
Для такого рода коммуникаций и нужно собрание стоя. Намного лучше иметь одно короткое обязательное собрание, чем множество длинных на которых большинство разработчиков должно все равно присутствовать.
Если у вас проводяться ежедневные собрания стоя, то все остальные собрания должны посещать только те люди, которые необходимы и будут что-либо привносить. Более того, имеется возможность даже избежать некоторых собраний. С ограничением участников, большинство собраний может быть проведено спонтанно перед монитором, где обмен идеями намного более интенсивен.
Ежедневное утреннее собрание это не еще одна трата времени. Оно позволит вам избежать многих других собраний и сэкономит больше времени, чем на него затрачено.
***
Это правило нормально внедрилось. На первых порах стоит следить чтобы собрания не затягивались. Часто даже стоя разработчики начинают обсуждать детали, которые они могут обсудить в паре во время работы.
Unit Test-ы
Unit тесты играют ключевую роль в XP. Они позволяют быстро менять код не боясь наделать новых ошибок. Unit тест пишется для каждого класса, тест должен проверять все аспекты работы класса - тестировать все что может не работать.
Хитростью здесь является то, что тест для класса должен быть написан раньше самого класса. Это значит, что как только вы выпустите первый работающий результат, он будет поддерживаться системой тестирования. Для проведения тестов пишется специальная система тестирования со своим интерфейсом.
Unit тест для класса хранится в общем репозитории вместе с кодом класса. Никакой код не может быть выпущен без Unit теста. Перед отдачей кода разработчик должен удостовериться что все тесты проходят без ошибок. Никто не может отдать код если все не прошли 100%. Другими словами поскольку до ваших изменений все тесты проходили, то если вы имеете ошибки, то это результат ваших изменений. Вам и исправлять. Иногда бывает неправильным или неполным код теста. В таком случае надо исправлять его.
Огромным искушением является сэкономить на Unit тестах когда мало времени. Но этим Вы только обманываете себя. Чем сложнее написать тест, тем больше времени он потом сэкономит. Это доказано практикой.
Unit тесты позволяют осуществить коллективное владение кодом. Они позволяют относительно легко пересматривать плохой код. Также Unit тесты позволяют в любой момент иметь стабильно работающую систему.
***
Сложно начинать писать UnitTest-ы когда уже есть система на 400000 строк. Но можно. Так что пишем. Правило такое - если меняешь код, для которого нет UnitTest-а - напиши сначала тест. Для нового кода все делается по правилам.
Как результат мы имеем заметно более качественный код. Цикл стабилизации системы перед выпуском сократился с полутора месяцев до двух-трех недель. Это при том что Unit тестами покрыто менее половины системы.
Наличие UnitTest-ов позволяет рефакторить систему. Также само написание теста обычно ведет к тому, что структура обьеков становится проще. Часто сначал приходится тестировать всю подсистему, поскольку невозможно выделить один обьект из-за запутанных взаимосвязей. Потихоньку клубок распутывается и все становится ясно и красиво.
User Story
User Story (что-то типа рассказа пользователя) - это описание того как система должна работать. Каждая User Story написана на карточке и представляет какой-то кусок функциональности системы, имеющий логический смысл с точки зрения Заказчика. Форма - один-два абзаца текста понятного пользователю (не сильно технического).
User Story пишется Заказчиком. Они похожи на сценарии использования системы, но не ограничиваются пользовательским интерфейсом. По каждой истории пишутся функциональные тесты, подтверждающие что данная история корректно реализована - их еще называют приемочными (Acceptance tests).
Каждой User Story дается приоритет со стороны бизнеса (пользователь, заказчик, отдел маркетинга) и оценка времени выполнения со стороны разработчиков. Каждая история разбивается на задачи и ей назначается время когда ее начнут реализовывать.
User Stories используются в XP вместо традиционных требований. Главное отличие User Story от требований (requirements) - уровень детализации. User Story содержит минимум информации, необходимой для обоснованной оценки того, сколько времени надо на ее реализацию.
Типичная User Story занимает 1-3 недели идеального времени. История требующая менее 1 недели слишком детализирована. История требующая более 3 недель может быть разбита на части - отдельные истории.
***
Поскольку наш продукт скорее коробочный чем заказной, то Заказчик для нас - это член команды который знает что надо сделать (роль сходная с Program Manager в Microsoft, или с Постановщиком Задач в советской схеме работы). Другими словами, если невозможно иметь реального Заказчика в своей команде - заведите человека, который будет играть такую роль.
Скорость проекта
Скорость Проекта (или просто скорость) это мера того, как быстро выполняется работа в вашем проекте.
Чтобы измерить скорость проекта, вы просто должны посчитать обьем User Stories, или как много (по времени) задач было выполнено за итерацию. Просто посчитайте суммарное время оценки обьема работы (идеальное время).
Во время планирования релиза скорость проекта используется для оценки того сколько User Stories может быть сделано.
Во время планирования итерации, скорость проекта в предыдущей итерации используется для определения того сколько User Stories надо планировать в текущую итерацию.
Этот простой механизм позволяет разработчикам восстановиться после трудной итерации. Если у вас после восстановления остается свободное время - идете к заказчику и просите еще User Story. В результате скорость опять возрастет.
Не надо использовать этот параметр как абсолютный. Он не подходит для сравнения продуктивности двух проектов, поскольку каждая команда имеет свои особенности. Этот параметр важен только для команды чтобы держать ее на “ровном киле”.
Вы должны ожидать небольшие изменения скорости проекта во время работы. Но если скорость изменяется сильно, необходимо провести перепланирование релиза. Как только новая система уходит к пользователям, ожидайте изменения скорости проекта, так как у вас появятся задачи по поддержке.
***
Все нормально работает как описано. Стоит только заметить что равномерность работы всех команд существенно повышает предсказуемость планов.
Например, у нас был случай когда одна User Story (из-за ошибок планирования) тянулась незаконченной на протяжении трех итераций. Потом тестировщики были заняты автоматизацией и начали тестировать новые фичи только через неделю. В результате команда почти всю итерацию была занята багами и не закончила то что планировала.
Когда обнаружена ошибка
Если обнаруживается ошибка, то создается тест, чтобы предотвратить его повторное появление. Ошибка, произошедшая в рабочей системе (уже установленной), требует написания функционального теста. Создание функционального теста непосредственно перед диагностикой ошибки позволяет заказчикам четко описать проблему и довести эту проблему до разработчиков.
Невыполнившийся функциональный тест требует создания Unit Test. Это помогает сфокусировать усилия по отладке и четко показывает когда ошибка исправлена.
***
Пока мы к этому еще не пришли. В настоящий момент у нас есть около пятисот тестов которые описаны, из них 100 автоматизировано, из них около 20 проходит без ошибок. Постепенно все функциональные тесты будут автоматизированы.
Найденные ошибки пока стараемся воспроизводить в UnitTest-ах. Это получается, хотя и требует дисциплины.
Вам это не понадобится
Воздержитесь от заполнения системы вещами, которые понадобятся вам в будущем. Только 10% от ожидаемого действительно понадобится вам в первоначальном виде, то есть 90% вашего времени будет потрачено впустую.
Всегда есть искушение добавить функциональность сейчас а не потом, потому что мы видим как сейчас добавить ее и чувствуем что система будет намного лучше. Но мы всегда должны напоминать себе что это нам никогда не понадобится. Дополнительная функциональность только замедляет прогресс и сьедает ресурсы. Забудьте про будущие требования и дополнительную гибкость. Сконцентрируйтесь на том, что необходимо сделать сейчас.
***
Пытаемся. Не всегда получается. Мешает гений Супер Архитектора сидящий в каждом. Особенно в тех, кто обладает властью (т. н. Начальство). Часто оброненное высказывание типа “А неплохо было бы если система могла …” выливается в концептуальные разработки которые не несут никакой реальной пользы заказчику. Поэтому, всегда решайте только те проблемы которые есть сейчас и решайте в первую очередь самые важные из них.
Простейшее решение работающее сейчас - вот что нужно Заказку.
thalion.kiev
Март
23,
2008
— Рубрика: Практика
Метки: User Story, ошибка, релизы, скорость, тесты
