Преодоление Барьеров Понимания: Специфицирование Примером и Гибкое Приемочное Тестирование

Мы предлагаем вам перевод отдельных отрывков книги Гойко Аджича (Gojko Adzic) "Преодоление барьеров понимания: специфицирование примером и гибкое приемочное тестирование" ("Bridging The Communication Gap: Specification by Example and Agile Acceptance Testing") с разрешения, любезно предоставленого автором.

Автор перевода: Александр Якима

Глава 1.2. Императивные требования очень легко неправильно понять.

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

История с серией экспериментов, которые проводил Лоуренс Шэтток (Lawrence G. Shattuck) с четырьмя регулярными батальонами Армии Соединенных Штатов (ссылка: http://www.au.af.mil/au/awc/awcgate/milreview/shattuck.pdf – прим. переводчика), приведенных также в книге Гари Клейна «Источники силы» (Gary Klein, “Sources of Power”), иллюстрирует эту проблему как нельзя лучше. Исследователи в рамках эксперимента присутствовали на военных учениях и просто слушали, в то время как командиры отдавали приказы своим солдатам. В продолжение учений они записывали все, что делали подразделения. Потом они обсудили фактические действия подразделений с их командирами. В результате эксперимента выяснилось, что действия солдат на полигоне полностью соответствовали тому, что подразумевалось их командирами, всего в 34% случаев. Читая об этом, я удивлялся, насколько эта история похожа на мой ранний опыт в разработке программного обеспечения. Командиры – это заказчики или бизнес-аналитики, приказы – это требования или спецификации, а солдаты – это разработчики и тестировщики. Мы все садимся в одной комнате, внимательно слушаем заказчика, договариваемся об определенном наборе требований и спецификаций, а потом удаляемся и разрабатываем что-то, что совсем не соответствует тому, чего хотел заказчик. Мне не известно о каких-либо подобных экспериментах, которые бы проводились с командами разработчиков, однако я не сильно удивлюсь, если результат окажется таким же. В некотором смысле вся эта история о том, что подобное происходит в Армии США, обнадеживает, так как из этого вытекает, что мы не единственные, кому досаждает неправильное понимание требований и некорректные предположения. К сожалению, это чувство быстро проходит, если на секунду задуматься о том, что у этих ребят самые большие пушки в мире, и при этом они неправильно понимают приказы в двух случаях из трех.


Глава 3.4. Определение важных примеров.

В Agile-разработке возможности системы инкрементально наращиваются посредством добавления функциональности от итерации к итерации. Майк Скотт (Mike Scott, из частной переписки автора) рекомендует концентрироваться вначале на «главной истории», содержащей основную суть отдельной возможности системы (иными словами – «фичи» - прим. переводчика), а потом добавлять дополнительные детали и исключения в последующих итерациях. Планирование проектов и разбиение отдельно взятой возможности системы на части, реализуемые в рамках нескольких итераций, выходит за рамки нашего текущего обсуждения, но я все же слегка коснусь этих вопросов в главе 9. Сейчас же хочу просто отметить, что мы сфокусируемся на работе с примерами, важными для отдельно взятого промежутка разработки, как бы он ни был запланирован. Нам следует, безусловно, учитывать будущее развитие функциональности, чтобы не зайти в тупик с разработкой, но при этом важно не переусердствовать, излишне усложнив процесс или увязнув в чрезмерном анализе всех возможных вариантов.

Итак, нам хотелось бы собрать достаточно много репрезентативных примеров, чтобы пройтись по всем вариантам и важным случаям для отдельно взятой возможности системы в рамках текущей итерации. Можем начать с того, что возьмем описание некоторой будущей функциональности системы, например, use-case сценарий, пользовательскую историю или любую другую «единицу» разработки, которую используем для планирования, и зададим заказчику вопрос: «как нам удостовериться, что эта функциональность реализована полностью и корректно?». Иной вопрос, который я часто применяю, звучит так: «представьте, что эта будущая функциональность чудесным образом уже реализована; тогда как именно вы бы ее тестировали?». Вот эти примеры нам и нужно будет записать и детально обсудить.

Затем нам следует определить «крайние случаи», негативные сценарии, а также сценарии, в которых не все идет согласно плану, и включить их в обсуждение. Слишком уж часто я встречал представителей бизнеса, обеспокоенных только сценариями, в которых все идет правильно, в то время как негативные варианты приходится разбирать уже самим разработчикам. Опять-таки, вы же не хотите, чтобы разработчики принимали решение о вашей бизнес-модели. Дональд Гоз (Donald Gause) и Джеральд Винберг (Gerald Weinberg) в книге «Exploring Requirements: Quality Before Design», ст. 251-252, выделяют следующие три категории, которые должны учитываться при создании тестов для отдельного требования (в гибком приемочном тестировании они соответствуют примерам):

1. нормальное использование функциональности

2. непредусмотренное, но разумное использование

3. непредусмотренное и нерациональное использование

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

Члены команды часто знакомы с крайними случаями и потенциальными проблемами и знают даже, как их можно бы решить, но им еще как-то необходимо их правильно донести. Если бы команда в свое время сообщила о своих проблемах и опасениях, то самолет, о котором пойдет речь в главе «Разрушение Духа Канзаса» на странице 21, мог бы все еще летать. Чтобы в нашем программном обеспечении избежать дорогостоящих дефектов подобного рода, нам всем следует сконцентрироваться на рассмотрении как можно большего числа именно таких «нерациональных» случаев. В обязанности тестировщиков как раз входит находить примеры, которые рано выявляли бы проблемные ситуации, являющиеся обычно предметом проверки на более поздней стадии. В следующей главе я ознакомлю читателей с концепцией воркшопа по специфицированию, способствующего такого рода обсуждениям.

Если в отдельно взятом примере фигурируют числовые данные, то я часто добавляю крайние значения, чтобы как-то «встряхнуть» систему требований, и посмотреть, что интересного из этого получится. Можно немного уменьшить значения чисел в примере, или же рассмотреть очень малые, а также весьма большие значения. Это не обязательно приведет к иному сценарию обработки данных, но вполне может подвести вас к видению того, что было с самого начала упущено. Примерами вышесказанного могли бы послужить транзакция размером в 0.01 при обмене валюты, 999 кликов в баннерной системе или приобретение видео-файла за $9.50. При обсуждении же крайне малых или больших значений, стоит спросить себя, насколько они вообще реалистичны. Следует иметь в виду, что существует разница между нерациональными и нереальными значениями. Очевидно, что нет особого смысла тратить время на рассмотрение мнимых данных, не представляющих для системы особой важности.


Различия в похожих примерах


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

Обратите внимание на следующие примеры для интернет-магазина цветов, предлагающего многоразовые ваучеры на бесплатную доставку для VIP-клиентов, если те делают разовую покупку на сумму более чем $50:

• Марк является VIP-клиентом. Он формирует заказ в корзине на $50 и переходит к оплате. На этапе оплаты ему предлагается бесплатная доставка, поскольку он проживает в США.
• У Марка осталось неиспользованное предложение на бесплатную доставку. Он формирует свой заказ на $30 и переходит к оплате. На этапе оплаты ему предлагается бесплатная доставка.
• У Марка нет предыдущих неиспользованных предложений по бесплатной доставке. Он формирует заказ на $30 и переходит к оплате. На этапе оплаты ему предлагается только доставка на общих условиях.
• Люси – VIP-клиент из Великобритании. Она формирует заказ на $50 и переходит к оплате, но получает только доставку на общих условиях, поскольку проживает в Великобритании. Мы не предлагаем бесплатной доставки за пределами США. Вместо этого мы даем ей бесплатный подарочный ваучер.
• Том не является VIP-клиентом. Он формирует заказ на $50 и переходит к оплате. На этапе оплаты ему предлагается только доставка на общих условиях.

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



Если выписать все подобным образом, то сразу становится проще заметить другие случаи, интересные для обсуждения. Очевидно, мы могли бы записать пример для VIP-клиента из Великобритании, сформировавшего заказ на $30. Но здесь присутствуют и такие пробелы в спецификации, которые заметить будет посложнее; но наша таблица помогает выявить также и их. К примеру, что мы делаем, если у кого-то есть неиспользованный ваучер на бесплатную доставку, но он также является VIP-клиентом и делает заказ на более чем $50? Переносим ли мы ваучер по доставке на следующий раз? А что если клиент в этот раз решит не пользоваться бесплатной доставкой – позволим ли мы ему перенести на будущее целых два ваучера или только один? Что будет, если вдруг каким-то образом окажется, что клиент из Великобритании обладает таким ваучером? Как такое вообще может произойти (возможно, система позволяет пользователю изменить адрес, но при этом оставить за собой ваучер), и стоит ли нам блокировать такую возможность? В идеальном случае нам хотелось бы успеть пробежаться по этим важным примерам, имея в распоряжении время экспертов в бизнес-области.


Таблицы упрощают обнаружение различий

Те, кто уже имел дело с системой FIT, уже наверняка успели заметить непосредственное соответствие между вышеупомянутыми таблицами и приемочными тестами в FIT (мы обсуждаем FIT детально в главе 10). Пока же, давайте просто пренебрежем тем, что мы знаем о FIT или любой другой подобной системе, включая и то, что нам нравится, и то, что нет. Если даже средство тестирования, которое вы используете, не поддерживает работу с таблицами, не стоит из-за этого отказываться от ценного метода. Смотрите на таблицы, как на отличный механизм, способствующий эффективному обсуждению требований. Рик Магридж (Rick Mugridge) и Ворд Каннингем (Ward Cunningham) отмечают, что таблицы предоставляют как раз такую необходимую структуру, чтобы эффективно организовать информацию, и при этом не усложнить ситуацию излишней формализацией данных (Fit for Developing Software: Framework for Integrated Tests, ст. 28). Таблицы уже активно использовались для эффективных обсуждений и качественного определения требований задолго до появления приемочного Agile-тестирования или изобретения метода разработки через тесты. Дэвид Парнас (David Parnas) применял их на проекте под названием A-7 для Военно-морской исследовательской лаборатории армии США еще в 1977 году. Он написал о своей работе в 1996 (Реляционные методы в компьютерных науках: табличное представление в реляционных документах, ст. 184-196):

Табличное представление информации весьма полезно в подобных случаях. Сначала определяется структура таблицы, так, чтобы ее колонки подходили под всевозможные случаи, а потом концентрируем усилия на заполнении отдельных строк таблицы. Задача может растянуться на недели или даже месяцы; применение табличного формата помогает удостовериться, что мы не пропустили ни единого важного случая.

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

* * *

Обсудить книгу можно в LinkedIn-группе

No comments:

Post a Comment

 
Powered by Blogger