Требования, которых нет — самая сложная ошибка

Как может получиться, что требований нет? Для этого надо, чтобы в процессе их сбора что-то пошло не так. Сбор требований состоит в определении задачи, которую предстоит решить. Возникает законный вопрос: «Как собирают требования?» Сбор требований нередко, но не всегда, представляет собой процесс взаимодействия одних людей с другими. Те, кто ставит задачу, – заказчики, пользователи или их «бизнес-аналитики» – опрашиваются представителями организации, разрабатывающей ПО.

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

Людей, выполняющих такой сбор требований, часто называют системными инженерами. Из-за большого разнообразия задач, с которыми могут столкнуться системные инженеры, попытки сделать процесс системного проектирования методологически выверенным (в смысле придания ему
установленного порядка) были малоуспешны, и хотя есть соответствующие курсы теоретической подготовки, содержание данной дисциплины остается относительно произвольным.
А теперь вспомните, какие документы создают системные инженеры. Один из путей составления программных требований для подобной системы состоит в тщательном изучении системных документов с отбором требований, которые формируют программную часть системы. А это тоже
процесс, весьма чреватый ошибками. Как может инженер-программист, к примеру, знать, какие системные требования в действительности влияют на будущую программную часть. Мой опыт говорит, что процесс сбора требований к ПО зачастую должен быть: а) итеративным (с первого взгляда трудно решить, какие требования существенны для ПО) и б) интерактивным (сборщики программных требований должны взаимодействовать со своими коллегами из других отраслей с целью разделить требования правильным образом).
Итак, мы видим, что системный анализ как процесс межличностного взаимодействия чреват ошибками. Мы также увидели, что системное проектирование как многоотраслевой процесс также чреват ошибками. По-этому неудивительно, что в глубине этих процессов созревают упущения.
И самое большое упущение – это полное отсутствие некоего технического условия.
Почему отсутствие требований так разрушительно сказывается на решении задачи? Потому что каждое требование вносит свой вклад в уровень сложности решения задачи, и взаимодействие всех этих требований приводит к быстрому увеличению сложности решения задачи. Упущение одного условия может привести к тому, что многие задачи не будут рассмотрены при проектировании решения.
Почему так трудно обнаружить и исправить недостающие требования? Потому что самая основная часть процесса устранения ошибок в программировании определяется техническими требованиями. Мы, в частности, определяем контрольные примеры, с помощью которых проверяем, все
ли требования были отражены в решении задачи. Если какое-либо требование отсутствует, оно не появится в спецификации, и потому не будет проверяться в ходе любой ревизии или инспекции, основанной на списке требований. Более того, не будут созданы контрольные примеры, позволяющие проверить его исполнение. Таким образом, основные методы устранения ошибок не смогут определить его отсутствие.

Основываясь на этом обстоятельстве, можно вывести такое следствие.

Самые живучие ошибки в программировании – те, что остаются незамеченными в процессе тестирования и доходят до этапа производства ПО, – это ошибки пропущенной логики. Отсутствующие требования приводят к пробелам в логике.

Несколько лет назад, озадаченный сложностью процесса устранения ошибок, я дал обещание изучить вопрос о том, какие ошибки наиболее существенны для программистских проектов. Я считал, что в чрезвычайно  сложном процессе усилия, потраченные на борьбу с серьезными ошибками, будут иметь большую ценность, чем потраченные на менее существенные ошибки.
Конечно, во всех программных проектах ошибкам назначают приоритеты, разделяя их по уровням серьезности. Эти категории варьируют от так называемых «шоу-стопперов» (show stoppers) – ошибок, делающих работу всей системы невозможной, до тривиальных, которые пользователи могут обойти так легко, что с их исправлением можно повременить. (Это важное разграничение. Несмотря на все голоса, агитирующие за ПО без ошибок, почти все сложные программные решения работают достаточно успешно при наличии известных ошибок. NASA, к примеру, может подсчитать количество ошибок в программах, сопровождавших успешные космические полеты. Между прочим, недавно Microsoft обнародовала количество ошибок в одной из своих систем, и когда ее недруги по всему миру запрыгали от радости, никто не сказал ни слова об этом нюансе и его значении.)
Однако приоритеты расставляются субъективно, из-за чего почти невозможно как-либо обобщить природу ошибок с высоким приоритетом, и потому почти невозможно изобрести подходы к борьбе с этими ошибками. Мне требовалось что-то, к чему можно было бы подойти более объективно.
Размышляя над этим, я пришел к выводу, что самыми критичными ошибками программирования, независимо от их природы и приоритета, являются ошибки, которые достигают серийной версии программного продукта. Безусловно, они вызывают больше неприятностей, чем те, которые обнаружены до стадии эксплуатации, хотя, как мы только что видели, и на стадии эксплуатации ошибки различаются по степени серьезности. Тогда я задался вопросом: а есть ли что-нибудь особенное в этих живучих ошибках? И стал думать, как это выяснить.

Оказалось, что нетрудно. В то время я работал на лидирующую аэрокосмическую компанию в научно-исследовательской организации, и у меня был доступ к тоннам данных об ошибках в проектах по разработке ПО. Я отделил ошибки стадии производства по указанной дате и для нескольких проектов начал собирать и систематизировать данные об ошибках.
По мере того как я анализировал данные, интрига нарастала. Я обнаружил, что среди живучих ошибок с большим отрывом лидировали ошибки, названные мной ошибками пропущенной логики. Эта категория доминировала в 30% случаев. В следующую по значению категорию входили регрессивные ошибки – новые ошибки, появившиеся в процессе сопровождения в результате исправления старых. На их долю приходилось 8,5% – намного меньше 30%. Интересно отметить, что третья категория живучих ошибок не содержала программных ошибок вовсе. Это были ошибки документации (8%), при этом считалось, что программный продукт отказал в работе, хотя этого не происходило.
Какие же ошибки относятся к ошибкам пропущенной логики? Например, отсутствие сброса данных в первоначальное значение после того, как они были использованы, но понадобятся позднее, или условные операторы с пропущенным одним и более условий. Эти ошибки возникали из-за
того, что программисты и проектировщики недостаточно глубоко продумывали свою задачу.
Почему эти ошибки сохранялись в серийной версии ПО? Потому что трудно проверять то, чего просто нет. Некоторые приемы тестирования, такие как анализ покрытия (coverage analysis), помогают нам убедиться, что все сегменты программы функционируют должным образом. Но если сегмента нет, то его отсутствие не может быть обнаружено с помощью методик покрытия. Аналогично эксперты, прекрасно умеющие отыскать ошибки в изучаемом коде, могут не заметить с такой же легкостью отсутствие необходимого кода.
Какое же это имеет отношение к отсутствующим требованиям? Очевидно, что отсутствующие требования приведут к пробелам в логике. Дело в том, что отсутствие требований сложно заметить по той же причине, по какой трудно заметить пропущенную логику.

(с) Роберт Гласс. Факты и заблуждения профессионального программирования. Факт №25.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *