Файл: Руководство по стилю программирования и конструированию по.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 30.11.2023
Просмотров: 772
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
ГЛАВА
5 Проектирование при конструировании
109
Процесс «разделяй и властвуй» итеративен в двух аспектах. Во-первых, потому, что, выполнив один этап декомпозиции, разработчики обычно не останавливаются, а выполняют еще несколько этапов. Во-вторых, потому, что дело обычно не огра- ничивается одной попыткой декомпозиции. Вы выполняете декомпозицию одним способом. На разных этапах декомпозиции у вас будут разные варианты разделения подсистем, формирования дерева наследования и группирования объектов. Вы делаете выбор и смотрите, что происходит. Затем вы возвращаетесь, выполняете декомпозицию иначе и смотрите, что работает лучше. После нескольких попыток вы получите хорошее представление о том, чт у
будет работать и почему.
До каких пор продолжать декомпозицию программы? До тех, пока вам не покажется, что вместо декомпозиции следующего уровня его было бы проще закодировать.
До тех, пока очевидность и простота проекта не станут вас в каком-то смысле раздражать. В этот момент все готово. Если что-то неясно, продолжите декомпо- зицию. Если сейчас решение кажется вам хоть чуть-чуть хитрым, для любого, кто будет работать над ним позднее, оно станет головоломкой.
Аргументы в пользу восходящего проектирования
Иногда нисходящий подход настолько абстрактен, что его трудно начать. Если вам нужно работать с чем-то более реальным, попробуйте восходящий подход к проектированию. Спросите себя: «Какие функции эта система должна выполнять?»
Несомненно, вы сможете ответить на этот вопрос. Вы можете определить несколько низкоуровневых аспектов ответственности, которые можно назначить конкретным классам. Так, вы можете знать, что система должна форматировать конкретный отчет, вычислять данные для отчета, центрировать его заголовки, отображать на экране, печатать на принтере и т. д. Определив несколько низкоуровневых аспектов ответственности, вы скорее всего почувствуете себя достаточно подготовленным, чтобы еще раз взглянуть на вершину.
В других случаях основные атрибуты проекта могут быть продиктованы низкоуров- невыми факторами, такими как особенности взаимодействия с оборудованием.
Вот некоторые рекомендации, о которых следует помнить при выполнении вос- ходящей композиции:
쐽
спросите себя, какие функции должна выполнять система;
쐽
опираясь на этот вопрос, определите конкретные объекты и их сферы ответ- ственности;
쐽
определите общие объекты и сгруппируйте их, организовав в подсистемы или пакеты, с помощью композиции или наследования (выберите самый подходя- щий вариант);
쐽
поднимитесь на следующий уровень или вернитесь на вершину и попробуйте еще раз начать нисходящее проектирование.
Никакого конфликта нет
Главное различие между нисходящей и восходящей стратегиями в том, что одна является стратегией декомпозиции, а вторая — композиции. В первом случае вы начинаете работу с общей проблемы, разбивая ее на управляемые фрагменты, во втором вы начинаете с управляемых фрагментов, составляя из них общее реше-
110
ЧАСТЬ
II
Высококачественный код ние. Оба подхода имеют достоинства и недостатки, которые следует рассмотреть в контексте конкретной проблемы.
Сила нисходящего подхода — в простоте. Люди (особенно программисты) пре- красно умеют делить что-то крупное на меньшие компоненты.
Еще одно достоинство в том, что нисходящее проектирование позволяет отложить работу над деталями конструирования. Изменения аспектов конструирования
(таких как структура файлов или формат отчетов) часто сказываются на всей системе, поэтому лучше заранее знать, что эти детали следует скрыть в классах на нижних уровнях иерархии.
Одно достоинство восходящего подхода объясняется тем, что он обычно приводит к раннему определению вспомогательной функциональности, что способствует созданию компактного, хорошо факторизованного проекта системы. Если похожая система уже создавалась, восходящий подход позволяет начать проектирование новой системы с рассмотрения и повторного использования фрагментов старой системы.
Восходящая композиция имеет и недостатки: во-первых, ее трудно использовать без применения других подходов. Большинство людей находят разбиение круп- ной концепции на меньшие части более легким, чем объединение небольших концепций в более крупную. Это напоминает старую проблему, связанную с кон- структорами: модель кажется готовой, но почему в коробке остались детали? К счастью, никто не заставляет проектировать программы, применяя исключительно восходящий подход.
Во-вторых, при восходящем проектировании иногда оказывается, что из исходных фрагментов создать программу невозможно. Никто не сможет собрать самолет из кирпичей. Чтобы узнать, какие фрагменты понадобятся на нижних уровнях, иногда нужно сначала получить общее представление о системе.
Подведем итог: нисходящее проектирование обычно начинается с простого, но иногда низкоуровневые сложности прорываются на вершину, и это может при- водить к усложнению системы, которого можно было избежать. Восходящее про- ектирование начинается со сложных аспектов, но определение этой сложности на ранних этапах позволяет лучше спроектировать высокоуровневые классы.... если к этому моменту сложность не потопит всю систему!
В конечном счете это не конкурирующие стратегии — они дополняют друг друга.
Проектирование — эвристический процесс, а значит, универсальных решений не существует. Проектирование содержит элементы метода проб и ошибок. Пробуйте разные подходы, пока не найдете тот, что вас устроит.
Экспериментальное прототипирование
Иногда адекватность конкретного проекта невозможно оценить, не имея дополнительных сведений о деталях реа- лизации. Вы можете не знать, приемлема ли конкретная ор- ганизация базы данных, пока не узнаете, будет ли она удовлетворять конкретным требованиям к производительности. Вы можете не знать, приемлем ли проект http://cc2e.com/0599
ГЛАВА
5 Проектирование при конструировании
111
конкретной подсистемы, пока не будут выбраны конкретные библиотеки GUI. Это примеры существенной «грязи» при проектировании ПО: вы не можете полностью определить проблему проектирования, пока не решите ее хоть частично.
Хорошо известен недорогой способ получить ответы на эти вопросы — экспери- ментальное прототипирование. В слово «прототипирование» люди вкладывают разный смысл (McConnell, 1996). В данном контексте оно означает написание абсолютно минимального объема подлежащего выбрасыванию кода, нужного для ответа на отдельный вопрос проектирования.
Если разработчики недисциплинированно относятся к написанию
абсолютно
минимального объема кода, нужного для ответа на вопрос, прототипирование работает плохо. Допустим, вопрос проектирования таков: «Может ли выбранная нами организация базы данных поддерживать нужный объем транзакций?» Для ответа не нужно писать полноценный код, который можно было бы использовать в готовой системе. Вы можете даже не знать специфику базы данных. Вам лишь нужна информация, достаточная для аппроксимации проблемной области: число таблиц, число элементов в таблицах и т. д. Далее вы можете написать простой про- тотипный код, использующий таблицы и столбцы с именами вроде
Table1, Table2 и
Column1, Column2, заполнить таблицы фиктивными данными и протестировать производительность.
Прототипирование также работает плохо, если задача недостаточно
конкретна.
Вопрос «Будет ли эта организация базы данных работать?» недостаточно хорошо определяет направление прототипирования. В то же время вопрос «Будет ли эта организация базы данных поддерживать 1000 транзакций в секунду при условиях
X, Y и Z?» предоставляет более прочную основу для прототипирования.
Наконец, еще один фактор риска возникает, если разработчики не рассматривают код как
подлежащий выбрасыванию. Я обнаружил, что люди не могут написать аб- солютно минимальный объем кода, нужный для ответа на вопрос, если думают, что код в конечном счете войдет в итоговую версию системы. Из-за этого они вместо прототипирования занимаются реализацией системы. Настроившись на то, что, как только ответ на вопрос будет получен, код будет выброшен, вы сведете этот риск к минимуму. Избежать этой проблемы можно, если создавать прототипы и основную программу, используя разные технологии. Вы можете создать прототип проекта Java на языке Python или смоделировать пользовательский интерфейс в
Microsoft PowerPoint. Если вы все-таки создаете прототипы, используя ту же тех- нологию, пусть имена прототипичных классов и пакетов начинаются с префикса
prototype. Это хотя бы заставит программиста дважды подумать, прежде чем он решит расширять прототипный код (Stephens, 2003).
При дисциплинированном применении прототипирование — эффективный способ борьбы с «грязнотой» проектирования. В противном случае оно делает проектирование еще более грязным.
112
ЧАСТЬ
II
Высококачественный код
Совместное проектирование
Обычно при проектировании две головы лучше, чем одна, организованы они формально или неформально. Сотрудни- чество может принимать любую из следующих форм:
쐽
вы подходите к столу коллеги и просите его обсудить с вами некоторые идеи;
쐽
вы с коллегой идете в конференц-зал и рисуете на доске варианты проекта;
쐽
вы с коллегой садитесь перед клавиатурой и выполняете детальное проекти- рование на выбранном языке программирования, т. е. вы можете использовать парное программирование (см. главу 21);
쐽
вы назначаете собрание для обсуждения своих идей с одним или несколькими коллегами;
쐽
вы назначаете формальную инспекцию, включающую все аспекты, описанные в главе 21;
쐽
никто не может провести обзор вашей работы, поэтому вы выполняете неко- торый объем работы, сохраняете ее и возвращаетесь к ней через неделю — вы забудете достаточно, чтобы самостоятельно провести довольно хороший обзор своей же работы;
쐽
вы обращаетесь за помощью к людям, не работающим в вашей компании: от- правляете вопросы в специализированный форум или группу новостей.
Если целью является гарантия качества, тогда по причинам, описанным в главе
21, я рекомендую наиболее структурированную методику обзора — формальные инспекции. Но если цель состоит в содействии творчеству и увеличении числа предлагаемых вариантов проекта, а не в простом нахождении ошибок, лучше при- менять менее структурированные подходы. После выбора определенного варианта проекта может оказаться уместным переход к более формальным инспекциям, что определяется конкретной ситуацией.
Какую степень проектирования считать достаточной?
Иногда перед началом кодирования создается только самый общий набросок архитектуры. В других случаях группы создают проекты с таким уровнем подробностей, что коди- рование становится практически механическим занятием.
Насколько детально выполнять проектирование до начала кодирования?
Родственный вопрос заключается в том, насколько формаль- ным делать проект. Нужны ли вам формальные, тщательно выполненные диаграммы проекта системы или цифровых снимков нескольких рисунков на доске будет достаточно?
Принятие решения о том, какую часть проектирования выполнять до начала пол- номасштабного кодирования и насколько формально документировать проект системы, трудно назвать точной наукой. При этом следует учитывать опыт груп- пы, ожидаемый срок службы системы, желательный уровень надежности, мас- штаб проекта и число членов группы. Влияние этих факторов на подход к про- ектированию отражено в табл. 5-2.
Мы пытаемся решить проблему, максимально ускоряя процесс проектирования, чтобы в кон- це работы над системой у нас осталось достаточно времени для нахождения ошибок, до- пущенных из-за слишком бы- строго проектирования.
Гленфорд Майерс
(Glenford Myers)
Перекрестная ссылка О совмест- ной разработке ПО см. главу 21
ГЛАВА
5 Проектирование при конструировании
113
Табл. 5-2. Необходимые уровни формальности и детальности проекта
Уровень
детальности
проекта,
нужный
перед началом
Уровень формальности
Фактор конструирования
документации
Члены группы проектирования/
Низкий
Низкий конструирования имеют большой опыт работы в прикладной области.
Члены группы проектирования/
Средний
Средний конструирования имеют большой опыт, но плохо знакомы с прикладной областью.
Члены группы проектирования/
Средний — высокий
Низкий — средний конструирования неопытны.
Для группы проектирования/конст- Средний
—
руирования характерен средний — высокий уровень текучести.
От приложения будет зависеть
Высокий
Высокий безопасность людей.
Приложение предназначено
Средний
Средний — высокий для решения ответственных задач.
Проект небольшой.
Низкий
Низкий
Проект крупный.
Средний
Средний
Предполагается, что ПО будет
Низкий
Низкий использоваться недолго
(недели или месяцы).
Предполагается, что ПО будет
Средний
Средний использоваться длительное время (месяцы или годы).
При создании конкретной системы могут иметь место сразу несколько факторов, подталкивающих к разным решениям: скажем, опытная группа может разраба- тывать ПО, от которого будет зависеть безопасность людей. Тогда вам, вероятно, следует отдать предпочтение более высокой детальности и формальности проекта.
Вообще в подобной ситуации нужно оценить роль каждого фактора и решить, какой из них важнее.
Если разработчики выполняют какую-то часть проектирования индивидуально, то при снижении проектирования до уровня задачи, которая уже была решена ранее, или до уровня простого изменения или расширения такой задачи, проектирование, вероятно, можно прекратить и начать кодирование.
Если я не могу решить, насколько детальным должен быть проект программы перед началом кодирования, я предпочитаю разрабатывать его более детально.
Самые крупные ошибки проектирования возникали, когда я думал, что выполнил проектирование в достаточной степени, но позднее оказывалось, что я заблуж- дался и не учитывал дополнительные проблемы. Иначе говоря, самые серьезные проблемы проектирования обычно были связаны не с теми областями, которые я считал сложными и спроектировал неудачно, а с теми, которые я считал легки- ми и не спроектировал вообще. Мне редко встречаются проекты, страдающие от чрезмерного проектирования.