Совершенный код. Совершенный код. Мастер-класс. Стив Макконнелл. Руководство по стилю программирования и конструированию по
Скачать 5.88 Mb.
|
ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 35 Определение проблемы — это просто формулировка сути проблемы без каких# либо намеков на ее возможные решения. Оно может занимать пару страниц, но обязательно должно звучать как проблема. Фраза «наша система Gigatron не справ# ляется с обработкой заказов» звучит как проблема и является хорошим ее опре# делением. Однако фраза «мы должны оптимизировать модуль автоматизирован# ного ввода данных, чтобы система Gigatron справлялась с обработкой заказов» — плохое определение проблемы. Оно похоже не на проблему, а на решение. Определение проблемы предшествует выработке детальных требований, которая является более глубоким исследованием проблемы (рис. 3#4). Будущие улучшения Тестирование системы Конструирование Проектирование архитектуры Выработка требований Определение проблемы Рис. 3'4. Определение проблемы — фундамент всего процесса программирования Проблему следует формулировать на языке, понятном пользователю, а сама про# блема должна быть описана с пользовательской точки зрения. Обычно проблему не следует формулировать в компьютерных терминах, потому что оптимальным ее решением может оказаться не компьютерная программа. Допустим, вы нужда# етесь в вычислении годовой прибыли. Вычисление квартальной прибыли вы уже компьютеризировали. Если вы застрянете на программировании, то решите, что в имеющееся приложение нужно просто добавить функцию вычисления годовой прибыли со всеми вытекающими отсюда последствиями: затратами на оплату труда разработчиков и т. п. Если же вы малость подумаете, то просто чуть поднимете зарплату секретарю, который будет один раз в год суммировать четыре числа на калькуляторе. Исключения из этого правила допустимы, если проблема связана с компьютера# ми: программы компилируются слишком медленно, или инструменты програм# мирования полны ошибок. В подобных случаях проблему можно сформулировать в компьютерных, привычных для программистов терминах. Не имея хорошего определения проблемы, можно потратить усилия на решение не той проблемы (рис. 3#5). 36 ЧАСТЬ I Основы разработки ПО Рис. 3'5. Прежде чем стрелять, убедитесь в том, что знаете, куда целитесь Неудачное определение проблемы грозит пустой тратой времени на ре# шение не той проблемы. Разумеется, нужную проблему вы при этом тоже не решите. 3.4. Предварительные условия, связанные с выработкой требований Требования подробно описывают, что должна делать программная система, а их выработка — первый шаг к решению проблемы. Выработка требований также известна как «разработка требований», «анализ требований», «анализ», «определение требований», «спецификация», «функциональная спецификация». Зачем нужны официальные требования? Важность явного набора требований объясняется несколькими причинами. Явные требования помогают гарантировать, что функциональность системы опре# деляется пользователем, а не программистом. Если требования сформулированы явно, пользователь может проанализировать и утвердить их. Если явных требова# ний нет, программисту обычно самому приходится вырабатывать их во время про# граммирования. Явные требования позволяют не гадать, чего хочет пользователь. Кроме того, наличие явных требований помогает избегать споров. Требования позволяют определить функциональность системы до начала программирования. Если вы не согласны с другим программистом по поводу каких#то аспектов про# граммы, вы можете разрешить споры, взглянув на написанные требования. Внимание к требованиям помогает свести к минимуму изменения сис# темы после начала разработки. Обнаружив при кодировании ошибку в коде, вы измените несколько строк, и работа продолжится. Если же во время кодирования вы найдете ошибку в требованиях, придется изменить про# ект программы, чтобы он соответствовал измененным требованиям. Возможно, при этом придется отказаться от части старого проекта, а поскольку в соответ# ствии с ней уже написан некоторый код, на реализацию нового проекта уйдет больше времени, чем могло бы. Вы также должны будете отказаться от кода и те# стов, на которые повлияло изменение требований, и написать их заново. Даже код, оставшийся нетронутым, нужно будет заново протестировать для гарантии того, что изменение не привело к появлению новых ошибок. ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 37 Как вы помните, исследования, проведенные во многих организациях, сви# детельствуют о том, что при работе над крупными проектами исправле# ние ошибки в требованиях, обнаруженной на этапе проектирования ар# хитектуры, обычно обходится втрое дороже, чем исправление аналогичной ошибки, найденной на этапе выработки требований (табл. 3#1). Такая же ошибка, обнару# женная при кодировании, обходится дороже уже в 5–10, при тестировании сис# темы — в 10, а после выпуска программы — в 10–100 раз. В менее крупных про# ектах с меньшими административными расходами последний показатель ближе к 5–10, чем к 100 (Boehm and Turner, 2004). Как бы то ни было, думаю, что допол# нительные расходы нужны вам меньше всего. Адекватное определение требований — одно из важнейших условий успеха про# екта, возможно, даже более важное, чем использование эффективных методов конструирования (рис. 3#6). Определению требований посвящены многие хоро# шие книги, поэтому в нескольких следующих разделах я не буду рассказывать, как правильно определять требования, — вместо этого я расскажу, как узнать, хоро# шо ли они определены, и как выжать максимум из имеющихся требований. Рис. 3'6. Не имея грамотно определенных требований, вы можете правильно представлять общую проблему, но упустить из виду ее специфические аспекты Миф о стабильных требованиях Стабильные требования — Святой Грааль разработки ПО. При стабильных требованиях смена этапов разработки ар# хитектуры, проектирования, кодирования и тестирования приложения происходит упорядоченно, предсказуемо и спокойно. Это просто рай для разработчиков! Вы можете точно планировать расходы и совсем не волнуетесь о том, что реализация какой# то функции обойдется в 100 раз дороже из#за того, что клиенту она придет в го# лову только после отладки. Всем нам хотелось бы надеяться, что, как только клиент утвердил требования, никаких изменений не произойдет. Однако чаще всего клиент не может точно сказать, что ему нужно, пока не будет написан некоторый код. Проблема не в том, что клиенты — более низкая форма жизни. Подумайте: чем больше вы работаете над проектом, тем лучше вы его понимаете; то же относится и к клиентам. Про# Требования подобны воде. Опи- раться на них легче, если они заморожены. Аноним 38 ЧАСТЬ I Основы разработки ПО цесс разработки помогает им лучше понять собственные потребности, что часто приводит к изменению требований (Curtis, Krasner and Iscoe, 1988; Jones 1998; Wiegers, 2003). Если вы планируете жестко следовать требованиям, на самом деле вы собираетесь не реагировать на потребности клиента. Какой объем изменений типичен? Исследования, проведенные в IBM и других компаниях, показали, что при реализации среднего проекта тре# бования во время разработки изменяются примерно на 25% (Boehm, 1981; Jones, 1994; Jones, 2000), на что приходится 70–85% объема повторной работы над типичным проектом (Leffingwell, 1997; Wiegers, 2003). Возможно, вы считаете, что «Понтиак Ацтек» — самый великолепный автомобиль из когда#либо созданных, являетесь членом Общества Верящих в Плоскую Землю и каждые четыре года совершаете паломничество в Розуэлл, штат Нью#Мексико, на место приземления инопланетян. Если это так, можете и дальше верить в то, что требования в ваших проектах меняться не будут. Если же вы уже перестали верить в Санта#Клауса или хотя бы прекратили признаваться в этом, вы можете кое#что предпринять, чтобы свести зависимость от изменений требований к минимуму. Что делать при изменении требований во время конструирования программы? Следующие действия позволяют максимально легко перенести измене# ния требований во время конструирования. Оцените качество требований при помощи контрольного списка, приведенного в конце раздела Если требования недостаточно хороши, прекра# тите работу, вернитесь назад и исправьте их. Конечно, вам может показаться, что прекращение кодирования на этом этапе приведет к отставанию от графика. Но если вы едете из Чикаго в Лос#Анджелес и видите знаки, указывающие путь в Нью# Йорк, разве можно считать изучение карты пустой тратой времени? Нет. Если вы не уверены в правильности выбранного направления, остановитесь и проверьте его. Убедитесь, что всем известна цена изменения требований Думая о новой функции, клиенты приходят в возбуждение. Кровь у них разжижается, перепол# няет продолговатый мозг, и они впадают в эйфорию, забывая обо всех собрани# ях, посвященных обсуждению требований, о церемонии подписания и всех до# кументах. Угомонить таких одурманенных новыми функциями людей проще всего, заявив: «Ого, это действительно прекрасная идея! Но ее нет в документе требова# ний, поэтому я должен пересмотреть график работы и смету, чтобы вы могли решить, хотите ли вы реализовать это прямо сейчас или позднее». Слова «график» и «смета» отрезвляют куда лучше, чем кофе и холодный душ, и многие требова# ния быстро превращаются в пожелания. Если руководители вашей организации не понимают важность предварительной выработки требований, укажите им, что изменения во время выработки требова# ний обходятся гораздо дешевле, чем на более поздних этапах. Используйте для их убеждения раздел «Самый веский аргумент в пользу выполнения предваритель# ных условий перед началом конструирования». ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 39 Задайте процедуру контроля изменений Если клиент никак не может успокоиться, подумайте об установлении стенда контроля изменений для рассмотрения вносимых предложений. В том, что клиенты изменяют точку зрения и понимают, что им нужны дополнительные возможности, нет ничего аномального. Проблема в том, что они вносят предложения так часто, что вы не поспеваете за ними. Наличие процедуры контроля изменений осчастливит всех: вы будете знать, что вам придется работать с изменениями только в опреде# ленные периоды времени, а клиенты увидят, что вам небезразличны их пожелания. Используйте те подходы к разработке, которые адап' тируются к изменениям Некоторые подходы к разра# ботке ПО позволяют особенно легко реагировать на изме# нения требований. Подход эволюционного прототипиро# вания (evolutionary prototyping) помогает исследовать тре# бования к системе до начала ее создания. Эволюционная поставка ПО подразу# мевает предоставление системы пользователям по частям. Вы можете создать фраг# мент системы, получить от пользователей отзывы, немного подкорректировать проект, внести несколько изменений и приступить к созданию другого фрагмен# та. Суть этого подхода — короткие циклы разработки, позволяющие быстро реа# гировать на пожелания пользователей. Оставьте проект Если требования особенно неудачны или изменчивы и никакой из предыдущих советов не рабо# тает, завершите проект. Даже если вы не можете на самом деле завершить его, подумайте об этом. Подумайте о том, насколько хуже он должен стать, чтобы вы от него отказа# лись. Если такая ситуация возможна, спросите себя, чем она отличается от текущей ситуации. Помните о бизнес'модели проекта Многие проблемы с требованиями исчезают при воспоминании о коммерче# ских предпосылках проекта. Требования, которые сначала казались прекрасными идеями, могут оказаться ужасными, когда вы оцените затраты. Программисты, которые прини# мают во внимание коммерческие следствия своих решений, ценятся на вес золота, и я был бы рад получить свою комис# сию за этот совет. Контрольный список: требования Следующий контрольный список содержит вопросы, позво- ляющие определить качество требований. Ни книга, ни этот список не научат вас грамотно вырабатывать требования. Используйте его во время конструирования для определения того, насколько прочна земля, на которой вы стоите. Не все вопросы будут актуальны для вашего проекта. Если вы работаете над неформальным проектом, над некоторыми вопросами даже не нужно задумы- ваться. Другие вопросы важны, но не требуют формальных ответов. Однако если Перекрестная ссылка Об итера- тивных подходах к разработке см. подраздел «Используйте итера- цию» раздела 5.4 и раздел 29.3. http://cc2e.com/0323 Перекрестная ссылка О том, что делать с изменениями проекта приложения и самого кода, см. раздел 28.2. Дополнительные сведения О под- ходах к разработке, поддержи- вающих гибкие требования, см. книгу «Rapid Development» (McConnell, 1996). Перекрестная ссылка О разли- чиях между формальными и не- формальными проектами (кото- рые часто объясняются разли- чиями размеров проектов) см. главу 27. 40 ЧАСТЬ I Основы разработки ПО вы работаете над крупным формальным проектом, вам, наверное, следует от- ветить на каждый вопрос. Специфические функциональные требования Определены ли все способы ввода данных в систему с указанием источни- ка, точности, диапазона значений и частоты ввода? Определены ли все способы вывода данных системой с указанием назна- чения, точности, диапазона значений, частоты и формата? Определены ли все форматы вывода для Web-страниц, отчетов и т. д.? Определены ли все внешние аппаратные и программные интерфейсы? Определены ли все внешние коммуникационные интерфейсы с указанием протоколов установления соединения, проверки ошибок и коммуникации? Определены ли все задачи, в выполнении которых нуждается пользователь? Определены ли данные, используемые в каждой задаче, и данные, являю- щиеся результатом выполнения каждой задачи? Специфические нефункциональные требования (требования к качеству) Определено ли ожидаемое пользователем время реакции для всех необхо- димых операций? Определены ли другие временные параметры, такие как время обработки данных, скорость их передачи и пропускная способность системы? Определен ли уровень защищенности системы? Определена ли надежность системы, в том числе такие аспекты, как след- ствия сбоев в ее работе, информация, которая должна быть защищена от сбоев, и стратегия обнаружения и исправления ошибок? Определены ли минимальные требования программы к объему памяти и свободного дискового пространства? Определены ли аспекты удобства сопровождения системы, в том числе способность системы адаптироваться к изменениям специфических функ- ций, ОС и интерфейсов с другими приложениями? Включено ли в требования определение успеха? Или неудачи? Качество требований Написаны ли требования на языке, понятном пользователям? Согласны ли с этим пользователи? Нет ли конфликтов между требованиями? Определено ли приемлемое равновесие между параметрами-антагониста- ми, такими как устойчивость к нарушению исходных предпосылок и коррект- ность? Не присутствуют ли в требованиях элементы проектирования? Согласован ли уровень детальности требований? Следует ли какое-нибудь требование определить подробнее? Менее подробно? Достаточно ли ясны и понятны требования, чтобы их можно было передать независимой группе конструирования? Согласны ли с этим разработчики? Каждое ли требование релевантно для проблемы и ее решения? Можно ли проследить каждое требование до его источника в проблемной среде? ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 41 Можно ли протестировать каждое требование? Можно ли будет провести независимое тестирование, которое позволит сказать, выполнены ли все требования? Определены ли все возможные изменения требований и вероятность каж- дого изменения? Полнота требований Указаны ли недостающие требования, которые невозможно определить до начала разработки? Полны ли требования в том смысле, что если приложение будет удовлетво- рять всем требованиям, то оно будет приемлемо? Не вызывают ли какие-нибудь требования у вас дискомфорта? Исключили ли вы требования, которые не поддаются реализации и были включены лишь для успокоения клиента или начальника? 3.5. Предварительные условия, связанные с разработкой архитектуры Архитектура — это высокоуровневая часть проекта прило# жения, каркас, состоящий из деталей проекта (Buschman et al., 1996; Fowler, 2002; Bass Clements, Kazman 2003; Clements et al., 2003). Архитектуру также называют «архитектурой си# стемы», «высокоуровневым проектом» и «проектом высокого уровня». Как прави# ло, архитектуру описывают в единственном документе, называемом «специфика# цией архитектуры» или «высокоуровневым проектом». Некоторые разработчики проводят различие между архитектурой и высокоуровневым проектом: архитек# турой называют характеристики всей системы, тогда как высокоуровневым про# ектом — характеристики, описывающие подсистемы или наборы классов, но не обязательно в масштабе всей системы. Так как эта книга посвящена конструированию, прочитав этот раздел, вы не уз# наете, как разрабатывать архитектуру ПО, — вы научитесь определять качество имеющейся архитектуры. Однако разработка архитектуры на один шаг ближе к конструированию, чем выработка требований, поэтому архитектуру мы рассмот# рим подробнее, чем требования. Почему разработку архитектуры следует рассматривать как предваритель# ное условие конструирования? Потому что качество архитектуры опре# деляет концептуальную целостность системы, которая в свою очередь определяет итоговое качество системы. Продуманная архитектура предоставляет структуру, нужную для поддержания концептуальной целостности в масштабе си# стемы. Она предоставляет программистам руководство, уровень детальности ко# торого соответствует их навыкам и выполняемой работе. Она позволяет разделить работу на части, над которыми отдельные разработчики и группы могут трудить# ся независимо. Хорошая архитектура облегчает конструирование. Плохая архитектура делает его почти невозможным. Другую проблему, связанную с плохой архитектурой, иллю# стрирует рис. 3#7. Перекрестная ссылка О проек- тировании на всех уровнях см. главы 5–9. 42 ЧАСТЬ I Основы разработки ПО Рис. 3'7. Не имея хорошей архитектуры, вы можете решать правильную проблему, но прийти к неправильному решению. Успешное конструирование может оказаться невозможным Внесение изменений в архитектуру при конструировании и на последу# ющих этапах обходится недешево. Время, необходимое для исправления ошибки в архитектуре ПО, сопоставимо со временем, нужным для исправ# ления ошибки в требованиях, т. е. превышает временные затраты на исправление ошибки в коде (Basili and Perricone, 1984; Willis, 1998). Изменения архитектуры похожи на изменения требований еще и тем, что кажущиеся небольшими изме# нения могут иметь далеко идущие последствия. Чем бы ни были обусловлены изменения архитектуры — исправлением ошибок или внесением улучшений, — чем раньше вы осознаете их необходимость, тем лучше. Типичные компоненты архитектуры Удачные архитектуры имеют много общего. Если всю систе# му вы создаете самостоятельно, работа над архитектурой будет перекрываться с более детальным проектированием. В этом случае вам следует по крайней мере обдумать каждый компонент архитектуры. Если вы работаете над системой, архитектура которой была разработана кем#то другим, вы должны уметь определять ее важные компоненты без охотничьей собаки и увеличительного стекла. Как бы то ни было, далее приве# ден список компонентов архитектуры, на которые следует обратить внимание. Организация программы В первую очередь архитектура должна включать общее опи# сание системы. Без такого описания вам будет трудно со# ставить согласованную картину из тысячи деталей или хотя бы десятка отдельных классов. Если бы система была моза# икой из 12 фрагментов, ее мог бы с легкостью собрать и го# довалый ребенок. Головоломку из 12 подсистем собрать труд# нее, но, если вы не сможете сделать этого, вы не поймете, какой вклад вносит в систему разрабатываемый вами класс. Архитектура должна включать подтверждения того, что при ее разработке были рассмотрены альтернативные варианты, и обосновывать выбор окончательной организации системы. Никому не хочется разрабатывать класс, если его роль в системе не кажется хорошо обдуманной. Описывая альтернативные варианты, Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не пони- маете. Альберт Эйнштейн Перекрестная ссылка О низко- уровневом проектировании про- граммы см. главы 5–9. |