Статьи
А вы завершили свою задачу?
30 Август
Я думаю, что вопрос «А ты завершил свою задачу?» вы слышали и сами задавали неоднократно. К сожалению, понятие завершенности у всех разное. Это может причинить большие проблемы в процессе разработки. Задачи, закрытые с разным уровнем завершенности, зачастую становятся причиной найденных ошибок, проблемного кода, неверных дизайнерских решений и других неприятностей. Чтобы избежать такого рода ситуаций команде стоит собраться и обсудить командное определение завершенности (Definition of Done). Для разного типа задач такое определение может отличаться. Лучше всего оформить определение завершенности и поместить его в общедоступное место: на доску задач, на WiKi, на стол каждому члену команды. После определения критерия завершенности задача может считаться законченной только в случае полного удовлетворения всем пунктам критерия. Каждая команда может включать свои пункты, которые зависят от языка программирования, специфики проекта, состава команды и других факторов. Вот один из примеров определения завершенности:
- Код написан и добавлен в систему контроля версий
- Все части задачи выполнены и логика работы кода соответствует требованиям
- Весь код прошел обязательную процедуру Code Review
- Код не имеет проблем, найденных статическими анализаторами кода
- Unit-тесты для кода написаны в полном объеме
- Код и тесты прошли процедуру Refactoring и не содержат явных проблем
- Интеграционные тесты написаны
- Сборка с запуском всех тестов на Continuous Integration сервере завершилась успешно
- …
Но это еще далеко не все! В Agile подходах используется итеративный и инкрементальный стили разработки. Это значит, что заказчик в праве ожидать некоего набора завершенной функциональности к концу каждой итерации. Но ваше понимание завершенности может очень сильно отличаться от понимания заказчика. Чем больше разница, тем больше накапливается недоделанной работы. Очень хорошо, если вы демонстрируете завершенные задачи в конце каждой итерации, причем демонстрируете так, как просит вас заказчик. В этом случае проблема очень быстро вылезет наружу. Для того, чтобы избежать проблем, нужно добавить в определение завершенности пункты от заказчика (синхронизировать список с ним). В этом случае заказчик знает чего он в праве ожидать и как он может проверить готовность функционала.
Давайте рассмотрим небольшой пример. Ваша команда имеет отличный, продуманный критерий завершенности задач, но туда не входит интеграция и установка задач на рабочий сервер, а также регрессионное тестирование. Итерация заканчивается и вы радостно показываете новый функционал заказчику на специальном тестовом сервере. Все проходит отлично и заказчик задает вопрос: «Ну что с завтрашнего дня пользователи смогут оценить новую функциональность, а мы – получить больше прибыли?». В ответ вы чешете голову и отвечаете, что нужно еще неделю для того, чтобы установить все на рабочий сервер, написать скрипты обновления базы данный, мигрировать данные с нескольких старых табличек, прогнать все регрессионные тесты. Естественно это может расстроить вашего заказчика и обмануть его ожидания. Синхронизация критерия завершенности на ранних этапах разработки поможет построить доверительные отношения и убережет от многих неприятностей.
Критерий завершенности можно использовать еще для одной интересной цели – выделение стадий, через которые проходит ваша задача. Это позволяет построить более правильную Kanban доску задач и расставить ограничения на объем работ, выполняемый одновременно. К примеру, можно придти к таким колонкам: «Написание приемочных тестов», «Реализация», «Code Review», «Тестирование», «Установка на сервер». В этом случае у команды и заказчика будет общее понимание почему нужны все эти стадии и как далеко конкретная задача находится от состояния завершения. Гораздо легче отслеживать прогресс и анализировать проблемы.
Всегда старайтесь закончить задачу так, чтобы вы могли собой гордиться!
Успешная разработка продукта с помощью Agile подходов
28 Август
В последнее время появляется все больше и больше новых методологий разработки, технических инструментов, языков программирования и библиотек компонентов, которые позволяют разрабатывать быстрее, надежнее и с меньшими усилиями. Но это не помогает ответить на главный вопрос: «Что разрабатывать?». Какой функциональностью должен обладать продукт? Для кого он будет предназначен? Как продукт будет конкурировать на рынке? С появлением Agile подходов и их быстрым распространением большая часть команд хотят сразу начинать разрабатывать и «приносить прибыль» заказчику. Тем более что в большинстве Agile методологий не уделяется должного внимания анализу и исследованию разрабатываемого продукта. Концепция пользовательских историй (User Stories) слишком проста и не помогает в процессе планирования продукта в полной мере. Намекаю ли я на то, что нужно вернуть стадию анализа из классических методологий или генерировать огромное количество артефактов перед фазой реальной разработки? Вовсе нет. Вместо этого стоит использовать более легковесные подходы и практики. Самое главное не забывать о том, что данная предварительная фаза нужна и поможет в будущем разработать «правильный продукт». Инженерные практики, итеративная и инкрементальная разработка, методологии и прочие инструменты помогут разработать «продукт правильно». Только сочетание этих двух целей (разработать «правильный продукт» и разработать «продукт правильно») приведет к успеху.
Данная тема давно меня интересовала и на конференции Agile Base Camp я выступил с докладом «Путь Agile проекта до первой итерации». Я постарался рассказать о том, какие активности необходимы в Agile проекте до начала реальной разработки и каким образом эти активности могут быть организованы. Правильная подготовка к разработке продукта может помочь сэкономить средства, избежать реализации никому не нужной функциональности, начать использовать продукт на ранних стадиях и получать от него прибыль. Слайды доклада доступны в разделе ресурсов на нашем сайте.
Jeff Patton – один из представителей Agile сообщества, который уделяет теме исследования и анализа продукта много времени в своей практике. Именно он придумал подход Story Mapping для сбора и управления требованиями, неоднократно выступал на различных конференциях с концепцией Pragmatic Personas и делился опытом того, как избежать неопределенностей в Agile проектах. Недавно я посмотрел еще одно его выступление на тему использования идей Agile для успешной разработки продукта. Jeff рассматривает пример проваленного проекта, в котором вроде бы все было сделано правильно, но владелец недостаточно инвестировал в исследование продукта. Из выступления вы сможете узнать зачем нужна фаза исследования продукта, какие практики и инструменты помогают организовать ее максимально эффективно и добиться успеха в последующей разработке.
Agile подходы не помогут вам разработать правильный продукт, если вы не будете инвестировать свои усилия в его исследование и анализ на протяжении всего процесса разработки. Использование идей и принципов Agile может облегчить процесс анализа продукта и его эффективность, а в сочетании с Agile методологиями разработки позволит добиться успеха.
Опасные игры
25 Март
Игры и симуляции зачастую применяются на тренингах и конференциях для лучшего усваивания предлагаемой концепции. Они позволяют людям на собственном опыте попробовать некоторые вещи и осознать материал более глубоко. Но в симуляциях таится ряд скрытых недостатков. Разделим все игровые симуляции на два типа. Одни визуализируют некую проблему или плохую практику, другие предлагают решение проблемы. Иногда одна игра совмещает в себе оба типа. С визуализацией проблем все работает очень неплохо, что в принципе логично. Если проблема возникает даже в простой игровой ситуации, то в реальной жизни все может быть еще хуже. Поэтому можно обыграть различные аспекты и вариации проблемы достаточно просто и доступно. Игры, которые призваны продемонстрировать решение проблемы, попросту вводят многих в заблуждение. Люди начинают думать, что в жизни проблема разрешится так же просто. Вместо того чтобы просто заставить задуматься над путями решения реальных проблем, такие симуляции часто воспринимаются как уже готовые решения. К сожалению, часто это делается для того, чтобы продемонстрировать преимущества определенного подхода или методологии. Тем самым завоевываются новые сторонники, которые начинают внедрять подходы на практике. Вот тут и может наступить разочарование, потому что реальные жизненные ситуации гораздо сложнее и запутаннее, чем игровые. Некоторые решения внедрить не удается, что автоматически вызывает цепную реакцию и разочарование переходит на методологию или подход в целом. В более тяжелом случае решение все-таки внедряется, но прямолинейно и неправильно, без учета реальной жизненной ситуации. В результате страдают проекты, команды и целые компании. Поэтому будьте бдительны и помните, что любая игровая стимуляция служит поводом для размышлений и толчком к поиску реальных решений. Не стоит обманываться простотой и пытаться перенести игровое решение на реальную жизнь без дополнительного анализа. Тренерам стоит всегда делать акцент на этом перед проведением игровых симуляций такого типа. Это убережет участников от неправильного восприятия и последующих ошибок.
Agile в больших командах
18 Март
Очень часто поднимается вопрос о применении Agile в больших командах размером более 30 человек. Как известно, Agile методологии рекомендуют работать небольшой командой, желательно расположенной в одном месте. Это очень сильно упрощает коммуникации и позволяет успешно применять большую часть Agile практик. Но при разработке действительно большой системы не всегда можно справиться маленькой командой. Есть проекты с командами более 100 человек. Можно провести аналогию с программированием больших систем. Если у нас есть небольшая по функциональности система, к которой нет жестких требований по расширяемости и отказоустойчивости, то логично реализовать ее единым модулем. При этом возможно разделение на слои для облегчения тестирования и разделения логики. Архитектуры подобных систем очень простые и похожи друг на друга. Это очень напоминает работу небольшой команды. Когда же нам нужно разработать систему с серьезной бизнес логикой, работающую с внешними сервисами, имеющую высокие требования к расширяемости и отказоустойчивости, интегрирующуюся с различными устройствами и обрабатывающую огромные потоки информации, то все значительно усложняется. Тут на помощь приходит компонентная архитектура, асинхронное общение между компонентами, сервисно-ориентированный подход и т.д. Архитектура такого рода систем достаточно непроста и требует тщательного анализа, чтобы не только удовлетворять текущим требованиям, но быть достаточно гибкой и расширяемой. Именно из такого рода архитектур можно позаимствовать приемы организации работы больших команд.
Первый прием для построения компонентной архитектуры – это выделение полноценных компонентов. В случае большой команды такими компонентами являются маленькие подкоманды. Каждая подкоманда имеет все необходимое для независимого существования. У нее есть все нужные ресурсы, как человеческие, так и технические. В такой подкоманде можно сравнительно легко использовать любой понравившийся Agile процесс разработки. Для того, чтобы компонентная архитектура работала, у каждой компоненты должна быть четко очерченная зона ответственности. В случае подкоманды речь идет о части разрабатываемой системы. Для правильного выделения подкоманде ее зоны ответственности необходимо учесть, что компоненты должны быть максимально независимыми.
Это сразу делает проигрышным разделение по слоям (база данных, уровень доступа к данным, сервисная логика, пользовательский интерфейс). В этом случае зависимости слишком сильные, что влияет на коммуникации, планирование и остальные части процесса разработки. Разделение по слоям работает в проектах среднего размера, когда из-за специализации членов команд и их распределения тяжело выделить полнофункциональные подкоманды. В этом случае команды в каждой итерации анализируют точки соприкосновения и выделяют интерфейсы взаимодействия. В процессе разработки функционала используются техники заглушек и простых реализаций для обеспечения ранней интеграции. Второй вариант – это разделение по архитектурным компонентам системы. Этот вариант возможен при хорошей архитектуре самой системы, но таит в себе скрытые опасности. К таким опасностям относятся локализация архитектурных знаний, узкая специализация команд, распределенное планирование и т.д.
Второй прием – это обеспечение коммуникации между компонентами. Компоненты в архитектуре должны общаться только со своими ближайшими соседями, причем протокол может быть синхронный или асинхронный. В случае с синхронным протоколом (когда компоненты достаточно сильно зависят друг от друга) может применяться совместное планирование итерации, ежедневная синхронизация посредством проведения собрания представителей команд (Scrum of Scrum в методологии Scrum). В случае асинхронного протокола можно использовать Kanban подход. Если одной подкоманде необходимо, чтобы определенный функционал был реализован другой подкомандой, она помещает запрос на эту функциональность в очередь ожидания. Эта очередь может позволять управление приоритетами. Статус заявки можно отслеживать на Kanban доске по мере прохождения всех стадий разработки. Замеряя время цикла от постановки задачи в очередь до ее выполнения, можно добиться более точного планирования для зависимых задач.
Кардинально другой способ взаимодействия компонентов применяется в событийной архитектуре. Каждый компонент, в том числе и заказчик, может генерировать события определенных типов (задачи на реализацию определенного функционала). Все задачи поступают на общую шину. Это может быть система управления задачами или же физический инструмент визуализации (в отсутствии проблем с распределенной командой). Каждый компонент способен обрабатывать определенные типы задач, что зависит от его роли в системе. Таким образом, подкоманда всегда берет из шины задачи с максимальным приоритетом, которые она способна делать. Как только задача закончена, ее результаты публикуются в общедоступном месте либо же попадают обратно в шину в качестве задачи другого типа.
Анализируя возможности и ограничения работы в конкретном проекте, с помощью аналогий из мира архитектуры можно придти к стройному и продуктивному Agile процессу в большой команде. Ниже приведен пример такого рода процесса:

Как видно из приведенных примеров, архитектуры современных систем таят в себе очень много интересных идей, которые можно использовать для организации процесса разработки в большой Agile команде. Ведь многие из существующих больших систем действительно работают! Я готовлю детальный доклад на эту тему, с которым планирую выступить на ближайшей конференции. Надеюсь с помощью идеи поиска аналогий в архитектуре вы сможете улучшить свой процесс разработки.
Есть ли смысл в приемочном тестировании?
3 Март
Это первая запись в разделе статей и я хотел бы посвятить ее приемочному тестированию. В последнее время идет очень много споров по поводу проблем приемочного тестирования и нужно ли приемочное тестирование вообще, стоит ли его автоматизировать или есть альтернативы. Эта тема очень мне близка, так как я долгое время веду тренинги по автоматизации приемочного тестирования. Для того, чтобы лучше разобраться в этих вопросах я разобью приемочное тестирование на две активности: подготовка приемочных тестов и автоматизация приемочных тестов.
На этапе подготовки приемочных тестов происходит выяснение и детальное обсуждение приемочных критериев (критериев готовности) для всех элементов функциональности. В этом процессе, в зависимости от особенностей проекта и структуры команды, могут участвовать заказчик, представитель заказчика, аналитик, тестировщик, менеджер проекта, программист и все остальные, имеющие отношение к проекту. Важно, чтобы на данном этапе возник диалог между стороной заказчика и стороной команды. Этот диалог будет детальным, потому что для написания приемочных тестов нужно не только понять основные приемочные критерии, что само по себе очень непросто, но и снабдить их данными и набором действий. Это детальное обсуждение как раз и является самым ценным элементом первого этапа. Оно позволяет не только синхронизировать видение функционала с обеих сторон, но и затронуть все мелкие вопросы, в которых обычно возникает недопонимание и построение догадок во время разработки. В качестве дополнительных артефактов от этой активности появляется набор тестов и повышение уровня доверия со стороны заказчика. Доверие появляется от осознания факта, что вроде бы все функциональные требования поняты командой, а значит будут реализованы именно так, как хочет заказчик.
Таким образом первый этап приемочного тестирования несет немало преимуществ и пользы процессу разработки. Даже если вы не собираетесь проводить автоматизацию полученных тестов, то определенных проблем вам уже удалось избежать. В этом случае сохраните все полученные тесты вместе с приемочными критериями в вашей системе для хранения требований. Они пригодятся вам для проведения ручного приемочного тестирования и при работе над реализацией функциональных требований.
Второй этап использует тесты, созданные на первом этапе, для автоматизации приемочных критериев. В том, что их было бы неплохо автоматизировать, никто не сомневается. Вопрос лишь в инструментах и техниках автоматизации. Тут и начинается самое интересное. Можно использовать специализированный инструмент как FitNesse или Concordion. Преимуществ у такого рода инструментов три. Первое преимущество заключается в том, что с ними могут работать не только программисты. Конечно же помощь программистов понадобится на каком-то этапе, но можно произвести разделение процесса создания тестов. То есть появляется отделение процесса создания тестов от непосредственно программирования. Сторонним эффектом является то, что при изменениях в приложении не будут меняться сами тесты. Вместо этого будет изменяться программный код для соединения этих тестов с приложением. Второе преимущество заключается в том, что данные инструменты заставляют вас разработать DSL (доменный язык) для вашего приложения. Разработка этого языка позволяет вам писать новые тесты без привлечения разработчиков, а также дает представление о имеющихся возможностях системы. Последнее преимущество заключается в возможности хранить тесты вместе с требованиями и запускать их прямо из требований. Это приближает нас к мечте об «исполняемой спецификации».
Но эти же преимущества могут превратиться в недостатки при определенных условиях. Первое преимущество является таковым только тогда, когда тесты должен иметь возможность создавать человек, не имеющий отношения к программированию. Таким человеком может быть кто-то со стороны заказчика или совершенно не технический тестировщик. Если же таких людей нет, то время на поддержку связывающего кода становится пустой тратой времени. Если тесты создаются и поддерживаются только командой, то трата времени на поддержку никому не нужных возможностей просто неуместна. Второе преимущество разбивается благодаря тому, что большая часть инструментов предоставляют очень бедный функционал для создания доменного языка. Конечно же есть исключения, к примеру Twist, в которые этому аспекту уделяется достаточно внимания. К сожалению, последнее преимущество тоже достаточно спорное. Дело в том, что для хранения требований большая часть компаний использует специализированные инструменты. Это может быть Wiki в Trac, Confluence, Google Docs и многие другие. Эти инструменты упрощают процесс управления требованиями и делают его удобным. Реализация подобного рода функционала в инструментах для приемочного тестирования значительно уступает, поэтому успешное использование их для хранения требований возможно только на сравнительно небольших проектах.
Таким образом использование специализированных средств для написания и управления приемочными тестами очень сильно зависит от контекста вашего проекта. Но для того, чтобы сделать осознанный выбор, вы должны знать о существовании и функционале подобных инструментов, а также анализировать ситуацию на проекте. На каждом тренинге по автоматизации приемочного тестирования или тестированию веб приложений с Selenium я упоминаю о том, что возможен и другой подход. В этом подходе доменный язык создается самими программистами в языке программирования с использованием инструментов тестирования. Тестировщики понимают этот доменный язык, пишут на нем и помогают его развивать, расширяя тем самым тестовый инструментарий. При этом тесты организовываются таким образом, чтобы их мог понять даже далекий от программирования человек. При правильном подходе такие тесты через некоторое время становится писать все легче и легче, а поддержка не вызывает особых проблем. Используются эти тесты по большей части для команды, чтобы быть уверенной в том, что весь функционал работает именно так, как хотел заказчик. Также эти тесты помогают осуществлять регрессионное тестирование и разработку по ATDD.
В заключении хочу сказать, что приемочное тестирование – великолепный инструмент для расширения коммуникации и построения доверительных отношений между заказчиком и командой. Автоматизация приемочного тестирования возможна и ее успех зависит от понимания принципов и инструментов, а также от желания участников проекта. Надеюсь вы сможете улучшить ваш процесс с помощью этой практики. Удачи!



