Бьерн Страуструп (947334), страница 61
Текст из файла (страница 61)
нижней границы размера программы, начиная с которой имеет смысл заняться
проектированием прежде, чем начать писать программу. Однако все-таки есть нижняя
граница, начиная с которой можно использовать какие-либо методы
проектирования. Вопросы, связанные с размером, обсуждаются в $$11.4.2.
Труднее всего в программных проектах бороться с их сложностью.
Есть только один общий способ борьбы со сложностью: разделяй и
властвуй. Если задачу удалось разделить на две подзадачи, которые можно
решать в отдельности, то можно считать ее решенной за счет разделения
более, чем наполовину. Этот простой принцип применим для удивительно
большого числа ситуаций. В частности, использование модулей или классов
при разработке программных систем позволяет разбить программу на две
части: часть реализации и часть, открытую пользователю - которые
связаны между собой (в идеале) вполне определенным интерфейсом. Это
основной, внутренне присущий программированию, принцип борьбы со
сложностью.
Подобно этому и процесс проектирования программы можно разбить на
отдельные виды деятельности с четко определенным (в идеале)
взаимодействием между людьми, участвующими в них. Это основной,
внутренне присущий проектированию, принцип борьбы со сложностью и
подход к управлению людьми,занятыми в проекте.
В обоих случаях выделение частей и определение интерфейса между
частями - это то место, где требуется максимум опыта и чутья. Такое
выделение не является чисто механическим процессом, обычно оно требует
проницательности, которая может появиться только в результате доско-
нального понимания системы на различных уровнях абстракции (см.
$$11.3.3, $$12.2.1 и $$13.3). Близорукий взгляд на программу или на
процесс разработки программного обеспечения часто приводит к дефектной
системе. Отметим, что как программы, так и программистов разделить
просто. Труднее достигнуть эффективного взаимодействия между участниками
по обе стороны границы, не нарушая ее и не делая взаимодействие слишком
жестким.
Здесь предложен определенный подход к проектированию, а не полное
формальное описание метода проектирования. Такое описание выходит за
предметную область книги. Подход, предложенный здесь, можно применять
с различной степенью формализации, и он может служить базой для различных
формальных спецификаций. В тоже время нельзя считать эту главу
рефератом, и здесь не делается попытка рассмотреть каждую тему,
относящуюся к процессу разработки программ или изложить каждую точку
зрения. Это тоже выходит за предметную область книги. Реферат по этой
тематике можно найти в [2]. В этой книге используется достаточно
общая и традиционная терминология. Самые "интересные" термины, как:
проектирование, прототип, программист - имеют в литературе несколько
определений, часто противоречащих друг другу, поэтому предостерегаем вас
от того, чтобы, исходя из принятых в вашем окружении определений терминов,
вы не вынесли из книги то, на что автор совершенно не рассчитывал.
11.2 Цели и средства
Цель программирования - создать продукт, удовлетворяющий пользователя.
Важнейшим средством для достижении этой цели является создание
программы с ясной внутренней структурой и воспитание коллектива
программистов и разработчиков, имеющих достаточный опыт и мотивацию,
чтобы быстро и эффективно реагировать на все изменения.
Почему это так? Ведь внутрення структура программы и процесс, с
помощью которого она получена, в идеале никак не касаются конечного
пользователя. Более того, если конечный пользователь почему-то
интересуется тем, как написана программа, то что-то с этой программой
не так. Почему, несмотря на это, так важны структура программы и люди,
ее создавшие? В конце концов конечный пользователь ничего об этом
не должен знать.
Ясная внутренняя структура программы облегчает:
- тестирование,
- переносимость,
- сопровождение,
- расширение,
- реорганизацию и
- понимание.
Главное здесь в том, что любая удачная большая программа имеет
долгую жизнь, в течение которой над ней работают
поколения программистов и разработчиков, она переносится на новую
машину, приспосабливается к непредусмотренным требованиям и несколько
раз перестраивается. Во все время жизни необходимо в приемлемое время и
с допустимым числом ошибок выдавать версии программы. Не планировать все
это - все равно, что запланировать неудачу.
Отметим, что, хотя в идеальном случае случае пользователи не
должны знать внутреннюю структуру системы, на практике они обычно
хотят ее знать. Например, пользователь может желать познакомиться в
деталях с разработкой системы с целью научиться контролировать
возможности и надежность системы на случай переделок и расширений.
Если рассматриваемый программный продукт есть не полная система, а набор
библиотек для получения программных систем, то пользователь захочет
узнать побольше "деталей", чтобы они служили источником идей и
помогали лучше использовать библиотеку.
Нужно уметь очень точно определить объем проектирования программы.
Недостаточный объем приводит к бесконечному срезанию острых углов
("побыстрее передадим систему, а ошибку устраним в следующей версии").
Избыточный объем приводит к усложненному описанию системы, в котором
существенное теряется в формальностях, в результате чего при
реорганизации программы получение работающей версии затягивается ("новая
структура намного лучше старой, пользователь согласен ждать ради нее").
К тому же возникают такие потребности в ресурсах, которые непозволительны
для большинства потенциальных пользователей. Выбор объема
проектирования - самый трудный момент в разработке, именно здесь
проявляется талант и опыт. Выбор трудно сделать и для одного программиста
или разработчика, но он еще труднее для больших задач, где занято
много людей разного уровня квалификации.
Организация должна создавать программный продукт и сопровождать
его, несмотря на изменения в штате, в направлении работы или в
управляющей структуре. Распространенный способ решения этих проблем
заключался в попытке сведения процесса создания системы к нескольким
относительно простым задачам, укладывающимся в жесткую структуру.
Например, создать группу легко обучаемых (дешевых) и взаимозаменяемых
программистов низкого уровня ("кодировщиков") и группу не таких
дешевых, но взаимозаменяемых (а значит также не уникальных)
разработчиков. Считается, что кодировщики не принимают решений по
проектированию, а разработчики не утруждают себя "грязными"
подробностями кодирования. Обычно такой подход приводит к неудаче, а
где он срабатывает, получается слишком громоздкая система с плохими
характеристиками.
Недостатки такого подхода состоят в следующем:
- слабое взаимодействие между программистами и разработчиками
приводит к неэффективности, промедлению, упущенным возможностям и
повторению ошибок из-за плохого учета и отсутствия обмена опытом;
- сужение области творчества разработчиков приводит
к слабому профессиональному росту, безынициативности, небрежности и
большой текучести кадров.
По сути, подобные системы - это бесполезная трата редких человеческих
талантов. Создание структуры, в рамках которой люди могут найти
применение разным талантам, овладеть новым родом деятельности и
участвовать в творческой работе - это не только благородное дело, но
и практичное, коммерчески выгодное предприятие.
С другой стороны, нельзя создать систему, представить документацию
по ней и бесконечно ее сопровождать без некоторой жесткой организационной
структуры. Для чисто новаторского проекта хорошо начать с того, что
просто найти лучших специалистов и позволить им решать задачу в
соответствии с их идеями. Но по мере развития проекта требуется все
больше планирования, специализации и строго определенного взаимодействия
между занятыми в нем людьми. Под строго определенным понимается не
математическая или автоматически верифицируемая запись (хотя это
безусловно хорошо там, где возможно и применимо), а скорее набор
указаний по записи, именованию, документации, тестированию и т.п.
Но и здесь необходимо чувство меры. Слишком жесткая структура может
мешать росту и затруднять совершенствование. Здесь подвергается
проверке талант и опыт менеджера. Для отдельного работника аналогичная
проблема сводится к определению, где нужно проявить смекалку, а где
действовать по рецептам.
Можно рекомендовать планировать не на период до выдачи следующей
версии системы, а на более долгий срок. Строить планы только до
выпуска очередной версии - значит планировать неудачу. Нужно иметь
организацию и стратегию развития программного обеспечения, которые
нацелены на создание и поддержание многих версий разных систем, т.е.
нужно многократное планирование успеха.
Цель проектирования в выработке ясной и относительно простой
внутренней структуры программы, называемой иногда архитектурой, иными
словами каркаса, в который укладываются отдельные программные фрагменты,
и который помогает написанию этих фрагментов.
Проект - конечный результат процесса проектирования (если только
бывает конечный продукт у итеративного процесса). Он является
средоточием взаимодействий между разработчиком и программистом и
между программистами. Здесь необходимо соблюсти чувство меры. Если я,
как отдельный программист, проектирую небольшую программу, которую
собираюсь написать завтра, то точность и полнота описания проекта
может свестись к нескольким каракулям на обратной стороне конверта.
На другом полюсе находится система, над которой работают сотни
программистов и разработчиков, и здесь могут потребоваться тома
тщательно составленных спецификаций проекта на формальном или
полуформальном языке. Определение нужной степени точности, детализации
и формальности проектирования является уже само по себе нетривиальной
технической и административной задачей.
Далее будет предполагаться, что проект системы записывается
как ряд определений классов (в которых частные описания опущены
как лишние детали) и взаимоотношений между ними. Это упрощение, т.к.
конкретный проект может учитывать: вопросы параллельности, использование
глобального пространства имен, использование глобальных функций и
данных, построение программы для минимизации перетрансляции,
устойчивость, многомашинный режим и т.п. Но при обсуждении на данном
уровне детализации без упрощения не обойтись, а классы в контексте С++
являются ключевым понятием проектирования. Некоторые из указанных
вопросов будут обсуждаться ниже, а те, которые прямо затрагивают
проектирование библиотек С++, будут рассмотрены в главе 13. Более
подробное обсуждение и примеры определенных методов объектно-
ориентированного проектирования содержатся в [2].
Мы сознательно не проводили четкого разделения анализа и
проектирования, поскольку обсуждение их различий выходит за рамки этой
книги, и оно зависит от применяемых методов проектирования. Главное в том,
чтобы выбрать метод анализа, подходящий для метода проектирования, и
выбрать метод проектирования, подходящий для стиля программирования
и используемого языка.
11.3 Процесс развития
Процесс развития программного обеспечения - это итеративный и
расширяющийся процесс. По мере развития каждая стадия повторяется
многократно, и при всяком возврате на некоторую стадию процесса уточняется
конечный продукт, получаемый на этой стадии. В общем случае процесс
не имеет ни начала, ни конца, поскольку, проектируя и реализуя систему,
вы начинаете, используя как базу другие проекты, библиотеки и прикладные
системы, в конце работы после вас остается описание проекта и программа,
которые другие могут уточнять, модифицировать, расширять и переносить.
Естественно конкретный проект имеет определенное начало и конец, и
важно (хотя часто удивительно трудно) четко и строго ограничить время
и область действия проекта. Но заявление, что вы начинаете с "чистого
листа", может привести к серьезным проблемам для вас, также как и позиция,
что после передачи окончательной версии - хоть потоп, вызовет
серьезные проблемы для ваших последователей (или для вас в новой
роли).
Из этого вытекает, что следующие разделы можно читать в любом
порядке, поскольку вопросы проектирования и реализации могут в
реальном проекте переплетаться почти произвольно. Именно, "проект"
почти всегда подвергается перепроектированию на основе предыдущего
проекта, определенного опыта реализации, ограничений, накладываемых
сроками, мастерством работников, вопросами совместимости и т.п.