Руководство по стилю программирования и конструированию по
Скачать 7.6 Mb.
|
ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 37 Как вы помните, исследования, проведенные во многих организациях, сви- детельствуют о том, что при работе над крупными проектами исправле- ние ошибки в требованиях, обнаруженной на этапе проектирования ар- хитектуры, обычно обходится втрое дороже, чем исправление аналогичной ошибки, найденной на этапе выработки требований (табл. 3-1). Такая же ошибка, обнару- женная при кодировании, обходится дороже уже в 5–10, при тестировании сис- темы — в 10, а после выпуска программы — в 10–100 раз. В менее крупных про- ектах с меньшими административными расходами последний показатель ближе к 5–10, чем к 100 (Boehm and Turner, 2004). Как бы то ни было, думаю, что допол- нительные расходы нужны вам меньше всего. Адекватное определение требований — одно из важнейших условий успеха про- екта, возможно, даже более важное, чем использование эффективных методов конструирования (рис. 3-6). Определению требований посвящены многие хоро- шие книги, поэтому в нескольких следующих разделах я не буду рассказывать, как правильно определять требования, — вместо этого я расскажу, как узнать, хоро- шо ли они определены, и как выжать максимум из имеющихся требований. Рис. 3-6. Не имея грамотно определенных требований, вы можете правильно представлять общую проблему, но упустить из виду ее специфические аспекты Миф о стабильных требованиях Стабильные требования — Святой Грааль разработки ПО. При стабильных требованиях смена этапов разработки ар- хитектуры, проектирования, кодирования и тестирования приложения происходит упорядоченно, предсказуемо и спокойно. Это просто рай для разработчиков! Вы можете точно планировать расходы и совсем не волнуетесь о том, что реализация какой- то функции обойдется в 100 раз дороже из-за того, что клиенту она придет в го- лову только после отладки. Всем нам хотелось бы надеяться, что, как только клиент утвердил требования, никаких изменений не произойдет. Однако чаще всего клиент не может точно сказать, что ему нужно, пока не будет написан некоторый код. Проблема не в том, что клиенты — более низкая форма жизни. Подумайте: чем больше вы работаете над проектом, тем лучше вы его понимаете; то же относится и к клиентам. Про- Требования подобны воде. Опи- раться на них легче, если они заморожены. Аноним 3 8 ЧАСТЬ 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. 4 0 ЧАСТЬ I Основы разработки ПО вы работаете над крупным формальным проектом, вам, наверное, следует от- ветить на каждый вопрос. Специфические функциональные требования Определены ли все способы ввода данных в систему с указанием источни- ка, точности, диапазона значений и частоты ввода? Определены ли все способы вывода данных системой с указанием назна- чения, точности, диапазона значений, частоты и формата? Определены ли все форматы вывода для Web-страниц, отчетов и т. д.? Определены ли все внешние аппаратные и программные интерфейсы? Определены ли все внешние коммуникационные интерфейсы с указанием протоколов установления соединения, проверки ошибок и коммуникации? Определены ли все задачи, в выполнении которых нуждается пользователь? Определены ли данные, используемые в каждой задаче, и данные, являю- щиеся результатом выполнения каждой задачи? Специфические нефункциональные требования (требования к качеству) Определено ли ожидаемое пользователем время реакции для всех необхо- димых операций? Определены ли другие временные параметры, такие как время обработки данных, скорость их передачи и пропускная способность системы? Определен ли уровень защищенности системы? Определена ли надежность системы, в том числе такие аспекты, как след- ствия сбоев в ее работе, информация, которая должна быть защищена от сбоев, и стратегия обнаружения и исправления ошибок? Определены ли минимальные требования программы к объему памяти и свободного дискового пространства? Определены ли аспекты удобства сопровождения системы, в том числе способность системы адаптироваться к изменениям специфических функ- ций, ОС и интерфейсов с другими приложениями? Включено ли в требования определение успеха? Или неудачи? Качество требований Написаны ли требования на языке, понятном пользователям? Согласны ли с этим пользователи? Нет ли конфликтов между требованиями? Определено ли приемлемое равновесие между параметрами-антагониста- ми, такими как устойчивость к нарушению исходных предпосылок и коррект- ность? Не присутствуют ли в требованиях элементы проектирования? Согласован ли уровень детальности требований? Следует ли какое-нибудь требование определить подробнее? Менее подробно? Достаточно ли ясны и понятны требования, чтобы их можно было передать независимой группе конструирования? Согласны ли с этим разработчики? Каждое ли требование релевантно для проблемы и ее решения? Можно ли проследить каждое требование до его источника в проблемной среде? ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 41 Можно ли протестировать каждое требование? Можно ли будет провести независимое тестирование, которое позволит сказать, выполнены ли все требования? Определены ли все возможные изменения требований и вероятность каж- дого изменения? Полнота требований Указаны ли недостающие требования, которые невозможно определить до начала разработки? Полны ли требования в том смысле, что если приложение будет удовлетво- рять всем требованиям, то оно будет приемлемо? Не вызывают ли какие-нибудь требования у вас дискомфорта? Исключили ли вы требования, которые не поддаются реализации и были включены лишь для успокоения клиента или начальника? 3.5. Предварительные условия, связанные с разработкой архитектуры Архитектура — это высокоуровневая часть проекта прило- жения, каркас, состоящий из деталей проекта (Buschman et al., 1996; Fowler, 2002; Bass Clements, Kazman 2003; Clements et al., 2003). Архитектуру также называют «архитектурой си- стемы», «высокоуровневым проектом» и «проектом высокого уровня». Как прави- ло, архитектуру описывают в единственном документе, называемом «специфика- цией архитектуры» или «высокоуровневым проектом». Некоторые разработчики проводят различие между архитектурой и высокоуровневым проектом: архитек- турой называют характеристики всей системы, тогда как высокоуровневым про- ектом — характеристики, описывающие подсистемы или наборы классов, но не обязательно в масштабе всей системы. Так как эта книга посвящена конструированию, прочитав этот раздел, вы не уз- наете, как разрабатывать архитектуру ПО, — вы научитесь определять качество имеющейся архитектуры. Однако разработка архитектуры на один шаг ближе к конструированию, чем выработка требований, поэтому архитектуру мы рассмот- рим подробнее, чем требования. Почему разработку архитектуры следует рассматривать как предваритель- ное условие конструирования? Потому что качество архитектуры опре- деляет концептуальную целостность системы, которая в свою очередь определяет итоговое качество системы. Продуманная архитектура предоставляет структуру, нужную для поддержания концептуальной целостности в масштабе си- стемы. Она предоставляет программистам руководство, уровень детальности ко- торого соответствует их навыкам и выполняемой работе. Она позволяет разделить работу на части, над которыми отдельные разработчики и группы могут трудить- ся независимо. Хорошая архитектура облегчает конструирование. Плохая архитектура делает его почти невозможным. Другую проблему, связанную с плохой архитектурой, иллю- стрирует рис. 3-7. Перекрестная ссылка О проек- тировании на всех уровнях см. главы 5–9. 4 2 ЧАСТЬ I Основы разработки ПО Рис. 3-7. Не имея хорошей архитектуры, вы можете решать правильную проблему, но прийти к неправильному решению. Успешное конструирование может оказаться невозможным Внесение изменений в архитектуру при конструировании и на последу- ющих этапах обходится недешево. Время, необходимое для исправления ошибки в архитектуре ПО, сопоставимо со временем, нужным для исправ- ления ошибки в требованиях, т. е. превышает временные затраты на исправление ошибки в коде (Basili and Perricone, 1984; Willis, 1998). Изменения архитектуры похожи на изменения требований еще и тем, что кажущиеся небольшими изме- нения могут иметь далеко идущие последствия. Чем бы ни были обусловлены изменения архитектуры — исправлением ошибок или внесением улучшений, — чем раньше вы осознаете их необходимость, тем лучше. Типичные компоненты архитектуры Удачные архитектуры имеют много общего. Если всю систе- му вы создаете самостоятельно, работа над архитектурой будет перекрываться с более детальным проектированием. В этом случае вам следует по крайней мере обдумать каждый компонент архитектуры. Если вы работаете над системой, архитектура которой была разработана кем-то другим, вы должны уметь определять ее важные компоненты без охотничьей собаки и увеличительного стекла. Как бы то ни было, далее приве- ден список компонентов архитектуры, на которые следует обратить внимание. Организация программы В первую очередь архитектура должна включать общее опи- сание системы. Без такого описания вам будет трудно со- ставить согласованную картину из тысячи деталей или хотя бы десятка отдельных классов. Если бы система была моза- икой из 12 фрагментов, ее мог бы с легкостью собрать и го- довалый ребенок. Головоломку из 12 подсистем собрать труд- нее, но, если вы не сможете сделать этого, вы не поймете, какой вклад вносит в систему разрабатываемый вами класс. Архитектура должна включать подтверждения того, что при ее разработке были рассмотрены альтернативные варианты, и обосновывать выбор окончательной организации системы. Никому не хочется разрабатывать класс, если его роль в системе не кажется хорошо обдуманной. Описывая альтернативные варианты, Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не пони- маете. Альберт Эйнштейн Перекрестная ссылка О низко- уровневом проектировании про- граммы см. главы 5–9. ГЛАВА 3 Семь раз отмерь, один раз отрежь: предварительные условия 43 архитектура обосновывает организацию системы и показывает, что роль каждо- го класса была тщательно рассмотрена. В одном обзоре методик проектирования было обнаружено, что обоснование проекта программы не менее важно для ее сопровождения, чем сам проект (Rombach, 1990). Архитектура должна определять основные компоненты программы. В зависимости от размера программы ее ком- понентами могут быть отдельные классы или подсистемы, состоящие из нескольких классов. Каждый компонент яв- ляется классом или набором классов/методов, которые в совокупности реализуют высокоуровневые функции про- граммы, такие как взаимодействие с пользователем, отображение Web-страниц, интерпретация команд, инкапсуляция бизнес-правил или доступ к данным. За каждую функцию приложения, указанную в требованиях, должен отвечать хотя бы один компонент. Если функцию реализуют несколько компонентов, они дол- жны сотрудничать, а не конфликтовать. Архитектура должна четко определять ответственность каж- дого компонента. Компонент должен иметь одну область ответственности и как можно меньше знать об областях ответственности других компонентов. Сведя к минимуму объем сведений, известных компонентам о других компо- нентах, вы сможете локализовать информацию о проекте приложения в отдельных компонентах. Архитектура должна ясно определять правила коммуника- ции для каждого компонента. Она должна описывать, какие другие компоненты данный компонент может использовать непосредственно, какие косвенно, а ка- кие вообще не должен использовать. Основные классы Архитектура должна определять основные классы приложе- ния, их области ответственности и механизмы взаимодей- ствия с другими классами. Она должна описывать иерархии классов, а также изменения состояний и время существова- ния объектов. Если система достаточно велика, архитектура должна описывать орга- низацию классов в подсистемы. Архитектура должна описывать другие рассматривавшиеся варианты организации классов и обосновывать итоговый вариант. Не все классы системы нужно описы- вать в спецификации архитектуры. Ориентируйтесь на правило 80/20: описывайте 20% классов, которыми на 80% определяется поведение системы (Jacobsen, Booch, and Rumbaugh, 1999; Kruchten, 2000). Организация данных Архитектура должна описывать основные виды формата файлов и таблиц. Она должна описывать рассмотренные аль- тернативы и обосновывать итоговые варианты. Если при- ложение использует список идентификаторов клиентов и разработчики архитектуры решили реализовать его при помощи списка с после- Перекрестная ссылка Об ис- пользуемых при проектирова- нии компонентах разных уров- ней см. подраздел «Уровни про- ектирования» раздела 5.2. Перекрестная ссылка Миними- зация объема сведений, извес- тных компонентам друг о дру- ге, — главный аспект сокрытия информации. Подробности см. в подразделе «Скрывайте сек- реты (к вопросу о сокрытии информации)» раздела 5.3. Перекрестная ссылка О проек- тировании классов см. главу 6. Перекрестная ссылка Об ис- пользовании переменных см. главы 10–13. 4 4 ЧАСТЬ I Основы разработки ПО довательным доступом, в документации должно быть сказано, почему этот вид списка лучше, чем список с произвольным доступом, стек или хэш-таблица. Эта информация окажет вам неоценимую помощь во время конструирования и со- провождения программы, подсказав, чем руководствовались разработчики архи- тектуры. Без нее вы будете чувствовать себя зрителем, который смотрит иност- ранный фильм без субтитров. Прямой доступ к данным обычно следует предоставлять только одной подсисте- ме или классу; исключения возможны при использовании классов или методов доступа, обеспечивающих доступ к данным, контролируемым абстрактным обра- зом. Подробнее об этом см. подраздел «Скрывайте секреты (к вопросу о сокры- тии информации)» раздела 5.3. Архитектура должна определять высокоуровневую организацию и содержание всех используемых БД. Архитектура должна объяснять, почему одна БД предпочтитель- нее, чем несколько (или наоборот), почему БД предпочтительнее, чем однород- ные файлы, определять возможные типы взаимодействия приложения с другими программами, использующими те же данные, объяснять, как будут отображаться данные, и т. д. Бизнес-правила Архитектура, зависимая от специфических бизнес-правил, должна определять их и описывать их влияние на проект системы. Возьмем для примера бизнес-прави- ло, согласно которому информация о клиентах должна устаревать не более чем на 30 секунд. В данном случае в спецификации архитектуры должно быть указа- но, как это правило повлияло на выбор метода обеспечения актуальности данных и их синхронизации. Пользовательский интерфейс Пользовательский интерфейс (GUI) часто проектируется на этапе выработки тре- бований. Если это не так, его следует определить на этапе разработки архитекту- ры. Архитектура должна описывать главные элементы формата Web-страниц, GUI, интерфейс командной строки и т. д. Удобство GUI может в итоге определить по- пулярность или провал программы. Архитектура должна быть модульной, чтобы GUI можно было изменить, не зат- ронув бизнес-правил и модулей программы, отвечающих за вывод данных. Напри- мер, архитектура должна обеспечивать возможность сравнительно легкой заме- ны группы классов интерактивного интерфейса на группу классов интерфейса командной строки. Такая возможность весьма полезна; во многом это объясняет- ся тем, что интерфейс командной строки удобен для тестирования ПО на уровне блоков или подсистем. Проектирование GUI заслуживает отдельной книги, и мы его рассматривать не будем. Управление ресурсами Архитектура должна включать план управления ограниченными ресурсами, такими как соединения с БД, потоки и дескрипторы. При разработке драйверов, встро- енных систем и других приложений, которые будут работать в условиях ограни- http://cc2e.com/0393 |