Таня действуй:)
ТЕХНОЛОГИЯ РАЗРАБОТКИ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
Сообщений 1 страница 7 из 7
Поделиться22008-01-17 23:20:33
63. Жизненный цикл ПО
Понятие жизненного цикла занимает центральное место в методологиях программирования. Оно образует базу для естественной систематизации инструментов и методов, ресурсов и результатов на разных этапах разработки и использования программных систем. Понятие это не является специфическим для программирования. Оно возникло и развивалось сначала применительно к техническим системам. В частности, еще недавно наши экономисты выражали беспокойство по поводу того, что зарубежный потребитель сравнительно дешевым советским тракторам предпочитает канадские, цена которых в несколько раз выше. Оказалось, что полная стоимость последних с учетом затрат всего "жизненного цикла существования машин" (включая их техническое обслуживание и ремонт) получается в конечном счете в несколько раз меньше. Не случайно вопрос технологичности с точки зрения не только изготовления, но и последующей эксплуатации имеет в технике первостепенное значение.
Жизненный цикл работы в целом
Жизненный цикл программы представлен на рис. 1. Здесь отражен тот факт, что, будучи однажды созданной, программа входит в цикл, включающий ее использование и модификацию; продолжительность этого цикла распространяется на все время жизни программы. Такая картина характерна и для многих промышленных изделий. Отличие заключается лишь в том, что для таких изделий фазу модификации точнее было бы назвать ремонтом или техническим обслуживанием, поскольку они модифицируются по мере износа их частей.
Рис.1 Жизненный цикл программы
Однако программы не подвержены износу. Поэтому они проходят фазу модификации из-за обнаружения ошибок, возникновения изменений в области их применения, требующих внесения соответствующих корректировок в программы, или из-за того, что прежняя модификация вызвала появление проблем в других частях программы. Например, изменения в налоговом законодательстве могут потребовать внесения корректировок в программы подготовки платежных ведомостей, связанные с расчетом удерживаемого налога. Однако внесенные изменения, в свою очередь, могут неблагоприятно повлиять на другие части программы, причем это может быть замечено не сразу.
Независимо от того, почему программа модифицируется, необходимо, чтобы некто (как правило, не автор ее исходной версии) изучил и понял программу и ее документацию; если не всю программу, то хотя бы ту часть, которая относится к делу. Любая модификация алгоритма программы может вызвать намного больше проблем, чем она предназначена решить. Достижение необходимой степени понимания является сложной задачей, даже если программа правильно разработана и документирована. Фактически именно на этой стадии отдельные фрагменты программного обеспечения просто отбрасывают, исходя из утверждений (часто вполне справедливых), что проще разработать новую систему с нуля, чем успешно модифицировать уже существующий пакет.
Жизненный цикл ИС можно представить как ряд событий, происходящих с системой в процессе ее создания и использования.
Модель жизненного цикла отражает различные состояния системы, начиная с момента возникновения необходимости в данной ИС и заканчивая моментом ее полного выхода из употребления. Модель жизненного цикла - структура, содержащая процессы, действия и задачи, которые осуществляются в ходе разработки, функционирования и сопровождения программного продукта в течение всей жизни системы, от определения требований до завершения ее использования.
В настоящее время известны и используются следующие модели жизненного цикла:
• Каскадная модель (рис. 2.1) предусматривает последовательное выполнение всех этапов проекта в строго фиксированном порядке. Переход на следующий этап означает полное завершение работ на предыдущем этапе.
Рис.2.1 Каскадная модель ЖЦ
• Поэтапная модель с промежуточным контролем (рис. 2.2). Разработка ИС ведется итерациями с циклами обратной связи между этапами. Межэтапные корректировки позволяют учитывать реально существующее взаимовлияние результатов разработки на различных этапах; время жизни каждого из этапов растягивается на весь период разработки.
Рис.2.2 Поэтапная модель с промежуточным контролем
• Спиральная модель (рис. 2.3). На каждом витке спирали выполняется создание очередной версии продукта, уточняются требования проекта, определяется его качество и планируются работы следующего витка. Особое внимание уделяется начальным этапам разработки - анализу и проектированию, где реализуемость тех или иных технических решений проверяется и обосновывается посредством создания прототипов (макетирования).
Рис.2.3 Спиральная модель
На практике наибольшее распространение получили две основные модели жизненного цикла:
• каскадная модель (характерна для периода 1970-1985 гг.)
• спиральная модель (характерна для периода после 1986.г.)
В ранних проектах достаточно простых ИС каждое приложение представляло собой единый, функционально и информационно независимый блок. Для разработки такого типа приложений эффективным оказался каскадный способ. Каждый этап завершался после полного выполнения и документального оформления всех предусмотренных работ.
Можно выделить следующие положительные стороны применения каскадного подхода:
• на каждом этапе формируется законченный набор проектной документации, отвечающий критериям полноты и согласованности;
• выполняемые в логической последовательности этапы работ позволяют планировать сроки завершения всех работ и соответствующие затраты.
Каскадный подход хорошо зарекомендовал себя при построении относительно простых ИС, когда в самом начале разработки можно достаточно точно и полно сформулировать все требования к системе. Основным недостатком этого подхода является то, что реальный процесс создания системы никогда полностью не укладывается в такую жесткую схему, постоянно возникает потребность в возврате к предыдущим этапам и уточнении или пересмотре ранее принятых решений.
Спиральная модель ЖЦ была предложена для преодоления перечисленных проблем. На этапах анализа и проектирования реализуемость технических решений и степень удовлетворения потребностей заказчика проверяется путем создания прототипов. Каждый виток спирали соответствует созданию работоспособного фрагмента или версии системы. Это позволяет уточнить требования, цели и характеристики проекта, определить качество разработки, спланировать работы следующего витка спирали. Таким образом углубляются и последовательно конкретизируются детали проекта и в результате выбирается обоснованный вариант, который удовлетворяет действительным требованиям заказчика и доводится до реализации.
Итеративная разработка отражает объективно существующий спиральный цикл создания сложных систем. Она позволяет переходить на следующий этап, не дожидаясь полного завершения работы на текущем и решить главную задачу - как можно быстрее показать пользователям системы работоспособный продукт, тем самым, активизируя процесс уточнения и дополнения требований.
Основная проблема спирального цикла - определение момента перехода на следующий этап. Для ее решения вводятся временные ограничения на каждый из этапов жизненного цикла, и переход осуществляется в соответствии с планом, даже если не вся запланированная работа закончена. Планирование производится на основе статистических данных, полученных в предыдущих проектах, и личного опыта разработчиков.
Несмотря на настойчивые рекомендации компаний - вендоров и экспертов в области проектирования и разработки ИС, многие компании продолжают использовать каскадную модель вместо какого-либо варианта итерационной модели.
В соответствии с базовым международным стандартом ISO/IEC 12207 все процессы ЖЦ ПО делятся на три группы:
• Основные процессы:
o приобретение
o поставка
o разработка
o эксплуатация
o сопровождение
• Вспомогательные процессы:
o документирование
o управление конфигурацией
o обеспечение качества
o разрешение проблем
o аудит
o аттестация
o совместная оценка
o верификация
• Организационные процессы:
o создание инфраструктуры
o управление
o обучение
o усовершенствование
Традиционные этапы разработки программ
Фаза разработки в жизненном цикле программы традиционно включает следующие этапы: анализ, проектирование, реализацию и тестирование (рис. 3).
Рис.3 Фаза разработки в жизненном цикле программного обеспечения
Анализ
Фаза разработки в жизненном цикле программы начинается с анализа, основная задача которого состоит в определении нужд пользователей предлагаемой системы. Если система должна быть продуктом общего назначения, продаваемым на рынке в условиях свободной конкуренции, анализ, вероятно, будет включать широкомасштабные исследования в целях определения потребностей потенциальных пользователей. Однако если система разрабатывается для нужд конкретного пользователя, исследования будут носить более целенаправленный характер.
По мере того как выясняются потребности потенциального пользователя, они преобразуются в ряд требований, которым должна удовлетворять новая система, Эти требования формулируются в терминах, принятых в сфере приложения, без использования специальной терминологии, принятой среди специалистов по обработке данных.
После того как требования к создаваемой системе будут определены, их преобразуют в систему спецификаций, имеющих более технически организованный вид.
Проектирование
В то время как анализ определяет, что должна делать предлагаемая система, проектирование определяет, как она будет выполнять эти задачи. Именно на этом этапе определяется структура системы программного обеспечения.
Не вызывает сомнения то, что наилучшей структурой для крупной системы программного обеспечения является модульная. Именно благодаря разбиению больших систем на модули становится возможной их практическая реализация. Без этого разбиения технические детали, необходимые при реализации большой системы, превысили бы возможности человеческого восприятия. При использовании модульной конструкции разработчик может ограничиться изучением только тех деталей, которые относятся к рассматриваемому модулю. Модульная конструкция также удобна при дальнейшем сопровождении программы, поскольку позволяет вносить изменения на модульной основе.
Реализация
Реализация включает собственно написание программ, создание файлов данных и разработку баз данных.
Тестирование
Тестирование тесно связано с реализацией, так как каждый модуль системы, как правило, должен подвергаться тестированию как только он будет написан. Действительно, в правильно сконструированной системе каждый модуль может и должен быть проверен либо независимо от других модулей, либо с использованием упрощенных версий других модулей, называемых заглушками. Назначение заглушек состоит в том, чтобы имитировать взаимодействие тестируемых модулей и остальной части системы. Аналогичным образом можно тестировать и систему в целом, по мере завершения создания отдельных модулей и их объединения в единое целое.
К сожалению, этап тестирования и устранения обнаруженных в системе неполадок чрезвычайно сложно довести до успешного завершения. Опыт показывает, что большие системы программного обеспечения могут содержать множество ошибок даже после продолжительного тестирования.
Современные тенденции
Ранние подходы к проектированию программного обеспечения предполагали строго последовательное выполнение этапов анализа, проектирования, реализации и тестирования. Предполагалось, что риск, связанный с использованием метода проб и ошибок при разработке больших систем программного обеспечения, слишком велик. В результате разработчики программного обеспечения настаивали на полном завершении общего анализа системы до начала ее проектирования. Точно так же необходимо полностью завершить этап проектирования системы до начала ее реализации. Подобная схема процесса разработки получила название модели водопада (по аналогии с движением потока падающей воды, поскольку процесс разработки должен был двигаться только в одном направлении).
Пошаговая модель является примером использования в технологии разработки программного обеспечения метода создания прототипов, который заключается в создании и последующей оценке неполных версий разрабатываемой системы, называемых прототипами. В пошаговой модели прототип развивается в конечную версию системы, поэтому данный вариант метода создания прототипов именуется эволюционным. В других случаях прототипы могут отбрасываться, уступая место новым реализациям конечного проекта. Такой вариант метода создания прототипов называется методом с отбрасыванием прототипов. Примером использования этого варианта может служить быстрое создание прототипов, при котором на них стадиях разработки очень быстро создается серия упрощенных вариантов разрабатываемой системы. Такой прототип может состоять всего лишь из нескольких эскизов компоновки экрана, показывающих, как система будет взаимодействовать с пользователем и каковы будут ее возможности. В данном случае задача состоит не в создании рабочей версии продукта, а в получении средства демонстрации, предназначенного для углубления взаимопонимания между участвующими в разработке сторонами. В частности, метод быстрого создания прототипов доказывает свою эффективность в отношении систематизации требований к системе, выдвинутых на этапе анализа, а также в качестве средства для проведения презентации возможностей системы ее потенциальным заказчикам.
Другое усовершенствование методов проектирования программных систем предусматривает применение компьютерных технологий к самому процессу разработки программного обеспечения, что привело к появлению CASE-технологий (CASE-Computed-Aided Software Engineering). Эти компьютеризованные системы, известные как CASE-инструменты, включают средства планирования проекта (предназначенные для оценки стоимости календарного планирования и распределения исполнителей), средства управления проектом (для контроля за процессом разработки проекта), средства документирования (для написания и систематизации проектной документации), средства создания прототипов и имитации (для создания прототипов), средства разработки интерфейсов (для разработки графических интерфейсов пользователя), а также средства программирования (для написания и отладки программ). Некоторые из этих инструментов немногим отличаются от обычных текстовых редакторов, приложений электронных таблиц и систем электронной почты, используемых в других приложениях. Однако другие представляют собой достаточно сложные пакеты, предназначенные преимущественно для использования при разработке систем программного обеспечения. Например, некоторые CASE-инструменты включают генераторы кода, которые по заданной спецификации на некоторую часть системы генерируют программу на языке высокого уровня, представляющую собой реализацию этой части системы.
Поделиться32008-01-17 23:23:54
64. Качество ПО
Программное средство.
Целью программирования является описание процессов обработки данных (в дальнейшем - просто процессов). Данные - это представление фактов и идей в формализованном виде, пригодном для передачи и переработки в некоем процессе, а информация - это смысл, который придается данным при их представлении. Обработка данных - это выполнение систематической последовательности действий с данными. Данные представляются и хранятся на т.н. носителях данных. Совокупность носителей данных, используемых при какой-либо обработке данных, будем называть информационной средой. Набор данных, содержащихся в какой-либо момент в информационной среде, будем называть состоянием этой информационной среды. Процесс можно определить как последовательность сменяющих друг друга состояний некоторой информационной среды.
Описать процесс - значит определить последовательность состояний заданной информационной среды. Если мы хотим, чтобы по заданному описанию требуемый процесс порождался автоматически на каком-либо компьютере, необходимо, чтобы это описание было формализованным. Такое описание называется программой. С другой стороны, программа должна быть понятной и человеку, так как и при разработке программ, и при их использовании часто приходится выяснять, какой именно процесс она порождает. Поэтому программа составляется на удобном для человека формализованном языке программирования, с которого она автоматически переводится на язык соответствующего компьютера с помощью другой программы, называемой транслятором. Человеку (программисту), прежде чем составить программу на удобном для него языке программирования, приходится проделывать большую подготовительную работу по уточнению постановки задачи, выбору метода ее решения, выяснению специфики применения требуемой программы, прояснению общей организации разрабатываемой программы и многое другое. Использование этой информации может существенно упростить задачу понимания программы человеком, поэтому весьма полезно ее как-то фиксировать в виде отдельных документов (часто не формализованных, рассчитанных только для восприятия человеком).
Обычно программы разрабатываются в расчете на то, чтобы ими могли пользоваться люди, не участвующие в их разработке (их называют пользователями). Для освоения программы пользователем помимо ее текста требуется определенная дополнительная документация. Программа или логически связанная совокупность программ на носителях данных, снабженная программной документацией, называется программным средством (ПС). Программа позволяет осуществлять некоторую автоматическую обработку данных на компьютере. Программная документация позволяет понять, какие функции выполняет та или иная программа ПС, как подготовить исходные данные и запустить требуемую программу в процесс ее выполнения, а также: что означают получаемые результаты (или каков эффект выполнения этой программы). Кроме того, программная документация помогает разобраться в самой программе, что необходимо, например, при ее модификации.
Критерий оценки качества программного обеспечения.
Разработка программного обеспечения - это, прежде всего, нахождение способов получения качественного программного продукта. Что мы подразумеваем, когда мы говорим о "качестве" программного обеспечения? Качество программного обеспечения может измеряться во внешних характеристиках (например, легкий в использовании, выполняется быстро) или во внутренних характеристиках (например, модульная конструкция, читабельный код). Внешние метрики - единственные, которые, в конце концов, действительно имеют значение. Никто, на самом деле, не заботится, насколько хорошую модульную конструкцию вы использовали при создании программы. Всех только заботит, чтобы она хорошо выполнялась. Однако, внутренняя (скрытая) метрика является ключом к созданию внешних, и при этом необходимо учитывать правила конструирования программ и технику программирования. В таблице 1 приводится список наиболее общих внешних факторов, найденных в качественном программном обеспечении. Более подробно некоторые из них будут рассмотрены ниже.
Характеристики качества программного обеспечения
Фактор Означает
Корректность (правильность) Обеспечивает правильную обработку на правильных данных
Устойчивость "Элегантно" завершает обработку ошибок
Расширяемость Может легко адаптироваться к изменяющимся требованиям
Многократность использования Может использоваться и в других системах, а не только в той, для которой было создано.
Совместимость Может легко использоваться с другим программным обеспечением
Эффективность Эффективное использование времени, компьютерной памяти, дискового пространства и т.д.
Переносимость Можно легко перенести на другие аппаратные и программные средства
Верификация Простота проверки, легкость разработки тестов при обнаружении ошибок, легкость обнаружения мест, где программа потерпела неудачу, и т.д.
Поддержка целостности Защищает себя от неправильного обращения и неправильного употребления
Легкость использования Для пользователя и для будущих программистов
Корректность и устойчивость
Легко спутать термины "Корректная программа" и "Устойчивая программа". Корректная программа работает, когда поданы на вход правильные данные. Она отвечает всем требованиям к спецификации данных и не терпит неудачу внутри заданного диапазона. Устойчивость подразумевает не только правильность. Устойчивая программа способна обработать ситуации, не запланированные проектом. Эти ситуации включают некорректный ввод пользователя, аппаратный отказ и ошибки во время выполнения программы. Устойчивые системы терпят неудачу элегантно, без потери критических данных. Легко увидеть, что обе характеристики необходимы для любой системы, которая будет оценена как высококачественное программное обеспечение. Если система некорректна, то она бесполезна. Если система неустойчива, то она окажется неспособной справиться с задачей в реальной ситуации.
Расширяемость
Требований меняются. Это - один из бесспорных фактов процесса разработки программного обеспечения. Высококачественная программа способна иметь дело с этими изменениями относительно безболезненно. Этот сорт адаптируемости - не является существенным для малых проектов, но становится определяющим, когда происходит "программирование в большом". Два основных принципа создания расширяемого программного обеспечения:
Простота проекта. Более простые проект и архитектура позволяют произвести изменения намного быстрее и легче, чем при сложном проекте.
Децентрализация. Разбиение сложных проблем на малые. Управляемость и независимость фрагментов, означающая, что они могут быть поделены внутри себя. Это значит, что изменения, могут быть выполнены без перекраивания других частей системы.
Эти принципы позволяют нам понять проблему в частях без опасения затеряться в несметном количестве непостижимых подробностей.
Многократность (повторность) использования и совместимость
Многократное использование может просматриваться на различных уровнях: при анализе, проектировании, и реализации. Оно поддерживает качество следующими способами:
Если проекты и код могут повторно использоваться, то мы можем начинать с уже проверенных, опробованных и правильных компонент, качество которых уже является высоким.
Время и энергия, сохраненные через многократное использование, могут применяться для улучшения других характеристик качества программы (например, корректности или устойчивости).
Совместимость программного обеспечения - мера того, насколько просто объединить различные программные изделия вместе для нового применения. Основы совместимости вытекают из общих проектных решений. Например, файловая система UNIX разработана таким образом, чтобы позволить малым инструментальным средствам хорошо работать вместе при решении сложных проблем. Противоположным примером является типичный беспорядок при совместной подготовке текстов и графических изображений. В этом случае, большие усилия должны быть затрачены на создание транслятора, которые позволяет одной программе работать с другой.
Совместимость и многократное использование идут "взявшись за руки", потому что повторно используемое программное обеспечение (например, plug&play компоненты) должно быть совместимо с его новым окружением. Совместимое программное обеспечение поддерживает качество посредством использования прошлых усилий и подпорок при формировании новых систем. Программное обеспечение с низким коэффициентом совместимости требует огромных усилий, чтобы настроить систему на необходимое использование. Это усилие могло быть потрачено на проектирование лучшей системы или на улучшение эффективности кода.
Понятность – легкость понимания документации, сопровождающей ПИ.
Каждое ПИ должно создаваться с учетом требований пользователя, определенных в техническом задании.
Все это может быть обеспечено, если ПИ описано ясным, лаконичным языком, без излишних повторений, с необходимыми ссылками.
Характеристики понятности:
Информативность ПИ – ПИ обладает информативностью, если оно содержит информацию, обеспечивающую понимание назначения ПИ, принятых ограничений, смыслового значения результатов работы отдельных компонентов ПИ.
Открытость ПИ – дает возможность понять назначение каждого оператора ПИ при чтении ее текста, т.е. каждый из идентификаторов должен нести смысловую нагрузку, например, SUM= CENA*KOL.
Согласованность ПИ – бывает внутренняя и внешняя.
Внутренняя согласованность должна обеспечивать единую терминологию, единую трактовку понятий и значений. Особое значение эта характеристика приобретает при создании программных комплексов, когда над проектом работает группа специалистов, и в процессе работы необходимы контакты по взаимоувязке программных модулей.
Внешняя согласованность обеспечивается однозначным соответствием создаваемого ПИ требованиям, изложенным в техническом проекте на его разработку.
Структурированность ПИ – делает его понятным для пользователя. Она предполагает создание ПИ в соответствии с определенными требованиями: использование при программировании трех базовых конструкций:
1а) линейная структура б) условный переход в) цикл
(или последовательная).
2Подробное комментирование текста программ.
3Использование модульного программирования (отдельная программная единица).
4Ограничение на объем модулей (количество операторов).
3. Надежность – свойство ПИ сохранять работоспособность в течение определенного периода времени в определенных условиях эксплуатации с учетом последствий для пользователя при любом отказе.
Она характеризуется:
Завершенность – завершенное ПИ включает все необходимые для функционирования программные компоненты.
Например, независимые ПИ:
– отсутствие в нем одного из модулей (нет перехода с года на год, нет перехода с века на век);
– некомплектная документация (т.е. нет документа целиком, либо раздела в документе).
Точность - характеристика, определяющая точность результатов расчета в соответствии с их назначением.
Например: если ведутся расчеты банковским операциям, то разумная точность – 3 знака после запятой, с последующим округлением до 2 знаков. Если в программе производятся расчеты по биологическим экспериментам, на молекулярном уровне, то точность по 10-12 знаков после запятой.
4. Эффективность – выполнение требуемых функций при минимальных затратах ресурсов. Причем под ресурсами подразумевается: объем оперативной памяти, время работы процессора, объем внешней памяти, пропускная способность канала.
Часто характеристика эффективности вступает в противоречие с другими характеристиками качественного ПИ.
Например: ПИ будет более эффективным во время работы, если будет состоять из меньшего количества модулей, чем это требует характеристика структурированности, так как на вызов модулей затрачивается относительно много машинного времени. Поэтому необходимость повышения эффективности ПИ за счет других характеристик необходимо оговаривать в техническом проекте на разработку ПИ.
5. Модифицируемость – эта характеристика отражает возможность внесения изменений в ПИ без значительных затрат времени на последующую отладку.
Эта характеристика включает в себя характеристику расширяемости ПИ, которая предполагает модификацию ПИ в части увеличения объема памяти либо числа функциональных модулей.
Оцениваемость – это существование критерия оценки ПИ и способа проверки соответствия этому критерию, по которым можно сравнить с другими подобными ПИ (критерии оценки в техническом проекте соответствует заданным требованиям: время работы модуля и т.д.).
Человеческий фактор: (сервис)
1. Легкость использования ПИ.
2. ПИ должно удовлетворять требованиям пользователя.
3. ПИ должно реализовывать потенциальные потребности пользователя.
4. Необходимо при разработке ПИ следовать золотому правилу: относить к людям так же, как бы ты хотел, чтобы относились к тебе.
Мобильность – возможность работы ПИ в различных ОС
Поделиться42008-01-17 23:25:19
67. Объекты и отношения в программировании. Сущность объектного подхода к разработке программных средств.
Окружающий нас мир состоит из объектов и отношений между ними. Объект воплощает некоторую сущность и имеет некоторое состояние, которое может изменяться со временем как следствие влияния других объектов, находящихся с данным в каком-либо отношении. Он может иметь внутреннюю структуру: состоять из других объектов, также находящихся между собой в некоторых отношениях. Исходя из этого можно построить иерархическое строение мира из объектов. Однако, при каждом конкретном рассмотрении окружающего нас мира некоторые объекты считаются неделимыми ("точечными"), причем в зависимости от целей рассмотрения такими (неделимыми) могут приниматься объекты разного уровня иерархии. Отношение связывает некоторые объекты: можно считать, что объединение этих объектов обладает некоторым свойством. Если отношение связывает n объектов, то такое отношение называется n-местным (n-арным). На каждом месте объединения объектов, которые могут быть связаны каким-либо конкретным отношением, могут находиться разные объекты, но вполне определенные (в этом случае говорят: объекты определенного класса). Одноместное отношение называется свойством объекта (соответствующего класса). Состояние объекта может быть изучено по значению свойств этого объекта или неявно по значению свойств объединений объектов, связываемых вместе с данным тем или иным отношением.
В процессе познания или изменения окружающего нас мира мы всегда принимаем в рассмотрение ту или иную упрощенную модель мира (модельный мир), в которую включаем некоторые из объектов и некоторые из отношений окружающего нас мира и, как правило, одного уровня иерархии. Каждый объект, имеющий внутреннюю структуру, может представлять свой модельный мир, включающий объекты этой структуры и отношения, которые их связывают. Таким образом, окружающий нас мир, можно рассматривать (в некотором приближении) как иерархическую структуру модельных миров.
В настоящее время в процессе познания или изменения окружающего нас мира широко используется компьютерная техника для обработки различного рода информации. В связи с этим применяется компьютерное (информационное) представление объектов и отношений. Каждый объект информационно может быть представлен некоторой структурой данных, отображающей его состояние. Свойства этого объекта могут задаваться непосредственно в виде отдельных компонент этой структуры, либо специальными функциями над этой структурой данных. N-местные отношения для N>1 можно представить либо в активной форме, либо в пассивной форме. В активной форме N-местное отношение представляется некоторым программным фрагментом, реализующим либо N-местную функцию (определяющую значение свойства соответствующего объединения объектов), либо процедуру, осуществляющую по состоянию представлений объектов, связываемых представляемым отношением, изменение состояний некоторых из них. В пассивной форме такое отношение может быть представлено некоторой структурой данных (в которую могут входить и представления объектов, связываемых этим отношением), интерпретируемую на основании принятых соглашений по общим процедурам, независящим от конкретных отношений (например, реляционная база данных). В любом случае представление отношения определяет некоторые действия по обработке данных.
При исследовании модельного мира пользователь может по-разному получать (или захотеть получать) информацию от компьютера. При одном подходе его могут интересовать получение информации об отдельных свойствах интересующих его объектов или результатах какого-либо взаимодействия между некоторыми объектами. Для этого он заказывает разработку того или иного ПС, выполняющего интересующие его функции, или некоторую информационную систему, способной выдавать информацию об интересующих его отношениях, используя при этом соответствующую базу данных. В начальный период развития компьютерной техники (при не достаточно высокой мощности компьютеров) такой подход к использованию компьютеров был вполне естественным. Именно он и провоцировал функциональный (реляционный) подход к разработке ПС, который был подробно рассмотрен в предшествующих лекциях. Сущность этого подхода состоит в систематическом использовании декомпозиции функций (отношений) для построения структуры ПС и текстов программ, входящих в него. При этом сами объекты, к которым применялись заказываемые и реализуемые функции, представлялись фрагментарно (в том объеме, который необходим для выполнения этих функций) и в форме, удобной для реализации этих функций. Тем самым не обеспечивалось цельного и адекватного компьютерного представления модельного мира, интересующего пользователя: отображение его на используемые ПС могло оказаться для пользователя достаточно трудоемкой задачей, попытки незначительного расширения объема и характера информации об интересующем пользователя модельном мире. получаемой от таких ПС, могло привести к серьезной их модернизации. Такой подход к разработке ПС поддерживается большинством используемых языков программирования, начиная от языков ассемблеров и процедурных языков (ФОРТРАН, Паскаль) до функциональных языков (ЛИСП) и языков логического программирования (ПРОЛОГ).
При другом подходе к исследованию модельного мира с помощью компьютера пользователя может интересовать наблюдение за изменением состояний объектов в результате их взаимодействий. Это требует достаточно цельного представления в компьютере интересующего пользователя объекта, а программные компоненты, реализующие отношения, в которых участвует этот объект, явно связываются с ним. Для реализации такого подхода приходилось строить программные средства, моделирующих процессы взаимодействия объектов (модельного мира). С помощью традиционных средств разработки это оказалось довольно трудоемкой задачей. Правда, появились языки программирования, специально ориентированные на такое моделирование, но это лишь частично упростило задачу разработки требуемых ПС. Наиболее полно отвечает решению этой задачи объектный подход к разработке ПС. Сущность его состоит в систематическом использовании декомпозиции объектов при построении структуры ПС и текстов программ, входящих в него. При этом функции (отношения), выполняемые таким ПС, выражались через отношения объектов разных уровней, т. е. их декомпозиция существенно зависела от декомпозиции объектов.
Говоря об объектном подходе следует также четко понимать о какого рода объектах идет речь: объектах модельного мира пользователя, об их информационном представлении, об объектах программы, с помощью которых строится ПС. Кроме того, следует различать собственно объекты (объекты "пассивные") и субъекты (объекты "активные").
Особенности объектного подхода к разработке внешнего описания программного средства
При объектном подходе этап внешнего описания ПС оказывается существенно более емким и содержательным по сравнению с реляционным подходом.
Определение требований заключается в неформальном описании модельного мира, который пользователь собирается изучать или просто использовать с помощью требуемого ПС. При этом повышается роль прототипирования, которое при этом подходе часто окупается уменьшением объема работы на последующих этапах разработки ПС. Часто определение требование завершается разработкой диаграммы вариантов использования, в которой фиксируются, в каких случаях будет использоваться ПС. Это позволяет при разработке ПС ограничиться только такими ее функциональными возможностями, которые поддерживают эти случаи (варианты) использования. По существу, диаграмма вариантов использования представляет собой описание некоторого контекста использования. На рис. 15.1. приведен пример диаграммы вариантов использования.
Существенно изменяется содержание процесса спецификации требований: вместо разработки функциональной спецификации ПС создается формальное описание модельного мира, состоящее из трех частей:
• • объектной модели,
• • динамической модели,
• • функциональной модели.
Назначение этих частей можно образно определить следующим образом [15.3]: объектная модель определяет то, с чем что-то случается; динамическая модель определяет, когда это случается; функциональная модель определяет то, что случается.
Рис. 15.1. Диаграмма вариантов использования для банкомата
Объектная модель показывает статическую объектную структуру модельного мира, который должно представлять разрабатываемое ПС (программная система). Она включает определения используемых классов объектов и отношений между этими классами, а также определение используемых объектов этих классов и отношения между этими объектами.
Обычно класс объектов в объектной модели представляется в виде тройки
(Имя класса, Список атрибутов, Список операций).
Каждый атрибут представляется некоторым именем и может принимать значения определенного типа. По существу, атрибут класса выражает некоторое простое свойство объектов этого класса. Представление некоторых простых свойств объектов атрибутами весьма удобно, особенно когда по значениям этих атрибутов осуществляется классификация объектов. Операции, указываемые в представлении класса, отражают другие свойства объектов этого класса (как простые, так и ассоциативные). Они показывают, что можно делать с объектами этого класса (или что могут делать сами эти объекты).
В объектной модели отношение между объектами некоторых классов обобщаются в отношения между этими классами. При этом используются, как правило, только одноместные и двуместные отношения между объектами. Более сложные отношения приводит к неоправданному усложнению объектных моделей, а с другой стороны, такие отношения всегда могут быть сведены к двуместным за счет определения дополнительных классов. Одноместные отношения называют атрибутами, причем некоторые атрибуты объекта получаются из атрибутов класса присвоением им конкретных значений. Отношение между двумя (и более) объектами называют связями, а их обобщение (отношение между классами) обычно называют ассоциациями. Ассоциации определяют допустимые связи между объектами. Различают следующие виды ассоциаций:
• • взаимодействия состояний объектов,
• • агрегирования (структурирования) объектов,
• • абстрагирования (порождения) классов.
Ассоциация «взаимодействие», по существу, означает, что объекты классов, находящихся в таком отношении, могут быть параметрами некоторых операций. Ассоциация «агрегирование» означает, что объект одного из классов, находящихся в таком отношении, включает (или может включать) в себя (как часть) объекты другого из этих классов. Ассоциация «абстрагирование» означает, что один из классов, находящихся в таком отношении, наследует свойства другого из этих классов и может обладать также и другими (дополнительными) свойствами.
Рис. 15.2. Пример отношения между классами объектов
Для представления объектной модели часто используются графические языки спецификации объектов (например, язык UML). На таких языках классы и объекты задаются прямоугольниками, которых указывается специфицирующая их информация. Для задания отношений между двумя классами соответствующие им прямоугольники связываются линией, снабженной различными графическими значками и некоторыми надписями. Графические значки специфицируют характер (вид) отношения между этими классами, а надписи обеспечивают полную идентификацию этого отношения (делают его конкретным). Например, на рис. 15.2 заданное отношение между классами Страна и Город имеет характер «один к одному». Более конкретно это отношение означает, что каждый объект класса Страна обязательно связан отношением «имеет столицей» с одним и только одним объектом класса Город, и этот объект класса Город не связан таким отношением ни с каким другим объектом класса Страна.
Для описания декомпозиции объектов используется отношение вида агрегирования. Например, отношение «программа состоит из одного или нескольких модулей» представлено на рис. 15.3.
Рис. 15.3. Пример отношения агрегирования между классами объектов.
Следует заметить, что объектная модель полностью включает описание внешней информационной среды при реляционном подходе.
Динамическая модель показывает допустимые последовательности изменений состояний объектов из объектной модели модельного мира, который должно представлять разрабатываемое ПС (программная система). Она описывает последовательности операций в ответ на внешние сигналы (взаимодействия) без рассмотрения того, что эти операции делают. Динамическая модель необходима, если в соответствующей объектной модели имеются активные объекты.
Основные понятия динамической модели: события и состояния объектов. Под событием здесь понимается элементарное воздействие одного объекта на другой, происходящее в определенный момент времени. Одно событие может логически предшествовать другому или быть не связанным с другим. Другими словами, события в динамической модели частично упорядочены. Под состоянием объекта здесь понимается совокупность значений атрибутов объекта и представления текущих связей этого объекта с другими объектами. Состояние объекта связывается с интервалом времени между некоторыми двумя событиями, на которые реагирует этот объект. Объект переходит из одного состояния в другое в результате реакции на некоторое событие (в конце интервала, связанного с этим состоянием).
Рис. 15.4. Диаграмма состояний телефонной линии.
В связи с этим в динамической модели для каждого класса активных объектов строится своя диаграмма состояний. Она представляет собой граф, вершинами которого являются состояния, а дугами – переходы между этими состояниями (переходы часто обозначаются именами событий). Некоторые переходы могут быть связаны с условиями, разрешающими эти переходы. Условие – это предикат, зависящий от значений некоторых атрибутов объекта. Каждое условие указывается на дуге, переходом по которой управляет это условие. Существенно, что в диаграмме состояний с некоторыми состояниями или событиями связываются определенные операции. Операция, связываемая с событием, обозначает реакцию объекта на это событие и считается, что она выполняется мгновенно (в точке некоторого временного интервала). Такая операция называется действием. Операция, связываемая с состоянием, выполняется в рамках временного интервала, с которым связано это состояние (т.е. имеет продолжительность, ограниченную этим интервалом). Такая операция называется деятельностью. Диаграмма состояний определяет управление активизацией указанных операций. Таким образом, диаграмма состояний описывает поведение одного класса объектов. Пример диаграммы состояний класса приведен на рис. 15.4.
Динамическая модель в целом объединяет все диаграммы состояний с помощью событий между классами.
Функциональная модель показывает, как вычисляются выходные значения из входных без указания порядка, в котором эти значения вычисляются. Она определяет все операции, условия и ограничения, используемые в объектной и динамической моделях (внешние операции). Функциональная модель соответствует определению внешних функций при реляционном подходе к разработке ПС.
Для определения крупных операций в функциональной модели используются потоковые диаграммы (диаграммы потоков данных), позволяющие выразить эти операции через более простые операции. Основными понятиями потоковых диаграмм являются процессы, объекты и потоки данных. Потоковая диаграмма – это граф, вершинами которого являются объекты или процессы, а дугами – потоки данных. Процессы преобразуют данные, поступающие от одних объектов и направляемые для хранения в другие объекты. Эти процессы представляют внутренние операции, через которые выражается операция, представляемая данной потоковой диаграммой. Объекты могут быть пассивными (хранилищами данных) и активными (агентами). Пассивные объекты используются только для хранения данных, а активные объекты используются как для хранения, так и для преобразования данных. Потоки данных определяют допустимые направления перемещения данных и типы перемещаемых данных.
Процессы могут выражаться терминальными операциями (определяемые непосредственно) или с помощью других потоковых диаграмм. Таким образом, потоковые диаграммы являются иерархическими.
Терминальные операции определяются так же, как и при реляционном подходе. Впрочем, и диаграммы потоков данных используются при реляционном подходе.
Таким образом, основным содержанием этапа внешнего описания при объектном подходе является объектное моделирование. При этом широко используются формальные языки спецификаций, в том числе и графические. Одним из наиболее употребительных в настоящее время таких языков является язык UML.
Поделиться52008-01-17 23:27:32
68. Отладка программного средства
Отладка ПС - это деятельность, направленная на обнаружение и исправление ошибок в ПС с использованием процессов выполнения его программ. Тестирование ПС - это процесс выполнения его программ на некотором наборе данных, для которого заранее известен результат применения или известны правила поведения этих программ. Указанный набор данных называется тестовым или просто тестом. Таким образом, отладку можно представить в виде многократного повторения трех процессов: тестирования, в результате которого может быть констатировано наличие в ПС ошибки, поиска места ошибки в программах и документации ПС и редактирования программ и документации с целью устранения обнаруженной ошибки. Другими словами:
Отладка = Тестирование + Поиск ошибок + Редактирование.
В зарубежной литературе отладку часто понимают только как процесс поиска и исправления ошибок (без тестирования), факт наличия которых устанавливается при тестировании. Иногда тестирование и отладку считают синонимами. В нашей стране в понятие отладки обычно включают и тестирование, поэтому мы будем следовать сложившейся традиции. Впрочем, совместное рассмотрение в данной лекции этих процессов делает указанное разночтение не столь существенным. Следует, однако, отметить, что тестирование используется и как часть процесса аттестации ПС.
Принципы и виды отладки программного средства
Успех отладки ПС в значительной степени предопределяет рациональная организация тестирования. При отладке ПС отыскиваются и устраняются, в основном, те ошибки, наличие которых в ПС устанавливается при тестировании. Как было уже отмечено, тестирование не может доказать правильность ПС, в лучшем случае оно может продемонстрировать наличие в нем ошибки. Другими словами, нельзя гарантировать, что тестированием ПС практически выполнимым набором тестов можно установить наличие каждой имеющейся в ПС ошибки. Поэтому возникает две задачи. Первая задача: подготовить такой набор тестов и применить к ним ПС, чтобы обнаружить в нем по возможности большее число ошибок. Однако чем дольше продолжается процесс тестирования (и отладки в целом), тем большей становится стоимость ПС. Отсюда вторая задача: определить момент окончания отладки ПС (или отдельной его компоненты). Признаком возможности окончания отладки является полнота охвата пропущенными через ПС тестами (т.е. тестами, к которым применено ПС) множества различных ситуаций, возникающих при выполнении программ ПС, и относительно редкое проявление ошибок в ПС на последнем отрезке процесса тестирования. Последнее определяется в соответствии с требуемой степенью надежности ПС, указанной в спецификации его качества.
Для оптимизации набора тестов, т.е. для подготовки такого набора тестов, который позволял бы при заданном их числе (или при заданном интервале времени, отведенном на тестирование) обнаруживать большее число ошибок в ПС, необходимо, во-первых, заранее планировать этот набор и, во-вторых, использовать рациональную стратегию планирования (проектирования) тестов. Проектирование тестов можно начинать сразу же после завершения этапа внешнего описания ПС. Возможны разные подходы к выработке стратегии проектирования тестов, которые можно условно графически разместить между следующими двумя крайними подходами. Левый крайний подход заключается в том, что тесты проектируются только на основании изучения спецификаций ПС (внешнего описания, описания архитектуры и спецификации модулей). Строение модулей при этом никак не учитывается, т.е. они рассматриваются как черные ящики. Фактически такой подход требует полного перебора всех наборов входных данных, так как в противном случае некоторые участки программ ПС могут не работать при пропуске любого теста, а это значит, что содержащиеся в них ошибки не будут проявляться. Однако тестирование ПС полным множеством наборов входных данных практически неосуществимо. Правый крайний подход заключается в том, что тесты проектируются на основании изучения текстов программ с целью протестировать все пути выполнения каждой программ ПС. Если принять во внимание наличие в программах циклов с переменным числом повторений, то различных путей выполнения программ ПС может оказаться также чрезвычайно много, так что их тестирование также будет практически неосуществимо.
Рис. Спектр подходов к проектированию тестов
Оптимальная стратегия проектирования тестов расположена внутри интервала между этими крайними подходами, но ближе к левому краю. Она включает проектирование значительной части тестов по спецификациям, но она требует также проектирования некоторых тестов и по текстам программ. При этом в первом случае эта стратегия базируется на принципах:
• • на каждую используемую функцию или возможность - хотя бы один тест,
• • на каждую область и на каждую границу изменения какой-либо входной величины - хотя бы один тест,
• • на каждую особую (исключительную) ситуацию, указанную в спецификациях, - хотя бы один тест.
Во втором случае эта стратегия базируется на принципе: каждая команда каждой программы ПС должна проработать хотя бы на одном тесте.
Оптимальную стратегию проектирования тестов можно конкретизировать на основании следующего принципа: для каждого программного документа (включая тексты программ), входящего в состав ПС, должны проектироваться свои тесты с целью выявления в нем ошибок. Во всяком случае, этот принцип необходимо соблюдать в соответствии с определением ПС и содержанием понятия технологии программирования как технологии разработки надежных ПС. В связи с этим Майерс даже определяет разные виды тестирования в зависимости от вида программного документа, на основании которого строятся тесты. В нашей стране различаются два основных вида отладки (включая тестирование): автономную и комплексную отладку ПС. Автономная отладка ПС означает последовательное раздельное тестирование различных частей программ, входящих в ПС, с поиском и исправлением в них фиксируемых при тестировании ошибок. Она фактически включает отладку каждого программного модуля и отладку сопряжения модулей. Комплексная отладка означает тестирование ПС в целом с поиском и исправлением фиксируемых при тестировании ошибок во всех документах (включая тексты программ ПС), относящихся к ПС в целом. К таким документам относятся определение требований к ПС, спецификация качества ПС, функциональная спецификация ПС, описание архитектуры ПС и тексты программ ПС.
Автономная отладка программного средства
При автономной отладке ПС каждый модуль на самом деле тестируется в некотором программном окружении, кроме случая, когда отлаживаемая программа состоит только из одного модуля. Это окружение состоит из других модулей, часть которых является модулями отлаживаемой программы, которые уже отлажены, а часть - модулями, управляющими отладкой (отладочными модулями, см. ниже). Таким образом, при автономной отладке тестируется всегда некоторая программа (тестируемая программа), построенная специально для тестирования отлаживаемого модуля. Эта программа лишь частично совпадает с отлаживаемой программой, кроме случая, когда отлаживается последний модуль отлаживаемой программы. В процессе автономной отладки ПС производится наращивание тестируемой программы отлаженными модулями: при переходе к отладке следующего модуля в его программное окружение добавляется последний отлаженный модуль. Такой процесс наращивания программного окружения отлаженными модулями называется интеграцией программы. Отладочные модули, входящие в окружение отлаживаемого модуля, зависят от порядка, в каком отлаживаются модули этой программы, от того, какой модуль отлаживается и, возможно, от того, какой тест будет пропускаться.
При восходящем тестировании это окружение будет содержать только один отладочный модуль (кроме случая, когда отлаживается последний модуль отлаживаемой программы), который будет головным в тестируемой программе. Такой отладочный модуль называют ведущим (или драйвером). Ведущий отладочный модуль подготавливает информационную среду для тестирования отлаживаемого модуля (т. е. формирует ее состояние, требуемое для тестирования этого модуля, в частности, путем ввода некоторых тестовых данных), осуществляет обращение к отлаживаемому модулю и после окончания его работы выдает необходимые сообщения. При отладке одного модуля для разных тестов могут составляться разные ведущие отладочные модули.
При нисходящем тестировании окружение отлаживаемого модуля в качестве отладочных модулей содержит отладочные имитаторы (заглушки) некоторых еще не отлаженных модулей. К таким модулям относятся, прежде всего, все модули, к которым может обращаться отлаживаемый модуль, а также еще не отлаженные модули, к которым могут обращаться уже отлаженные модули (включенные в это окружение). Некоторые из этих имитаторов при отладке одного модуля могут изменяться для разных тестов.
На практике в окружении отлаживаемого модуля могут содержаться отладочные модули обоих типов, если используется смешанная стратегия тестирования. Это связано с тем, что как восходящее, так и нисходящее тестирование имеет свои достоинства и свои недостатки.
К достоинствам восходящего тестирования относятся:
• • простота подготовки тестов,
• • возможность полной реализации плана тестирования модуля.
Это связано с тем, что тестовое состояние информационной среды готовится непосредственно перед обращением к отлаживаемому модулю (ведущим отладочным модулем).
Недостатками восходящего тестирования являются следующие его особенности:
• • тестовые данные готовятся, как правило, не в той форме, которая рассчитана на пользователя (кроме случая, когда отлаживается последний, головной, модуль отлаживаемой программ);
• • большой объем отладочного программирования (при отладке одного модуля приходится составлять много ведущих отладочных модулей, формирующих подходящее состояние информационной среды для разных тестов);
• • необходимость специального тестирования сопряжения модулей.
• К достоинствам нисходящего тестирования относятся следующие его особенности:
• • большинство тестов готовится в форме, рассчитанной на пользователя;
• • во многих случаях относительно небольшой объем отладочного программирования (имитаторы модулей, как правило, весьма просты и каждый пригоден для большого числа, нередко - для всех, тестов);
• • отпадает необходимость тестирования сопряжения модулей.
Недостатком нисходящего тестирования является то, что тестовое состояние информационной среды перед обращением к отлаживаемому модулю готовится косвенно - оно является результатом применения уже отлаженных модулей к тестовым данным или данным, выдаваемым имитаторами. Это, во-первых, затрудняет подготовку тестов и требует высокой квалификации тестовика (разработчика тестов), а во-вторых, делает затруднительным или даже невозможным реализацию полного плана тестирования отлаживаемого модуля. Указанный недостаток иногда вынуждает разработчиков применять восходящее тестирование даже в случае нисходящей разработки. Однако чаще применяют некоторые модификации нисходящего тестирования, либо некоторую комбинацию нисходящего и восходящего тестирования. Исходя из того, что нисходящее тестирование, в принципе, является предпочтительным, остановимся на приемах, позволяющих в какой-то мере преодолеть указанные трудности.
Прежде всего, необходимо организовать отладку программы таким образом, чтобы как можно раньше были отлажены модули, осуществляющие ввод данных, - тогда тестовые данные можно готовить в форме, рассчитанной на пользователя, что существенно упростит подготовку последующих тестов. Далеко не всегда этот ввод осуществляется в головном модуле, поэтому приходится в первую очередь отлаживать цепочки модулей, ведущие к модулям, осуществляющим указанный ввод. Пока модули, осуществляющие ввод данных, не отлажены, тестовые данные поставляются некоторыми имитаторами: они либо включаются в имитатор как его часть, либо вводятся этим имитатором.
При нисходящем тестировании некоторые состояния информационной среды, при которых требуется тестировать отлаживаемый модуль, могут не возникать при выполнении отлаживаемой программы ни при каких входных данных. В этих случаях можно было бы вообще не тестировать отлаживаемый модуль, так как обнаруживаемые при этом ошибки не будут проявляться при выполнении отлаживаемой программы ни при каких входных данных. Однако так поступать не рекомендуется, так как при изменениях отлаживаемой программы (например, при сопровождении ПС) не использованные для тестирования отлаживаемого модуля состояния информационной среды могут уже возникать, что требует дополнительного тестирования этого модуля (а этого при рациональной организации отладки можно было бы не делать, если сам данный модуль не изменялся). Для осуществления тестирования отлаживаемого модуля в указанных ситуациях иногда используют подходящие имитаторы, чтобы создать требуемое состояние информационной среды. Чаще же пользуются модифицированным вариантом нисходящего тестирования, при котором отлаживаемые модули перед их интеграцией предварительно тестируются отдельно (в этом случае в окружении отлаживаемого модуля появляется ведущий отладочный модуль, наряду с имитаторами модулей, к которым может обращаться отлаживаемый модуль). Однако, представляется более целесообразной другая модификация нисходящего тестирования: после завершения нисходящего тестирования отлаживаемого модуля для достижимых тестовых состояний информационной среды следует его отдельно протестировать для остальных требуемых состояний информационной среды.
Часто применяют также комбинацию восходящего и нисходящего тестирования, которую называют методом сандвича. Сущность этого метода заключается в одновременном осуществлении как восходящего, так и нисходящего тестирования, пока эти два процесса тестирования не встретятся на каком-либо модуле где-то в середине структуры отлаживаемой программы. Этот метод при разумном порядке тестирования позволяет воспользоваться достоинствами как восходящего, так и нисходящего тестирования, а также в значительной степени нейтрализовать их недостатки.
Весьма важным при автономной отладке является тестирование
сопряжения модулей. Дело в том, что спецификация каждого модуля программы, кроме головного, используется в этой программы в двух ситуациях: во-первых, при разработке текста (иногда говорят: тела) этого модуля и, во-вторых, при написании обращения к этому модулю в других модулях программы. И в том, и в другом случае в результате ошибки может быть нарушено требуемое соответствие заданной спецификации модуля. Такие ошибки требуется обнаруживать и устранять. Для этого и предназначено тестирование сопряжения модулей. При нисходящем тестировании тестирование сопряжения осуществляется попутно каждым пропускаемым тестом, что считают достоинством нисходящего тестирования. При восходящем тестировании обращение к отлаживаемому модулю производится не из модулей отлаживаемой программы, а из ведущего отладочного модуля. В связи с этим существует опасность, что последний модуль может приспособиться к некоторым "заблуждениям" отлаживаемого модуля. Поэтому, приступая (в процессе интеграции программы) к отладке нового модуля, приходится тестировать каждое обращение к ранее отлаженному модулю с целью обнаружения несогласованности этого обращения с телом соответствующего модуля (и не исключено, что виноват в этом ранее отлаженный модуль). Таким образом, приходится частично повторять в новых условиях тестирование ранее отлаженного модуля, при этом возникают те же трудности, что и при нисходящем тестировании.
Автономное тестирование модуля целесообразно осуществлять в четыре последовательно выполняемых шага.
• На основании спецификации отлаживаемого модуля подготовьте тесты для каждой возможности и каждой ситуации, для каждой границы областей допустимых значений всех входных данных, для каждой области изменения данных, для каждой области недопустимых значений всех входных данных и каждого недопустимого условия.
• Проверьте текст модуля, чтобы убедиться, что каждое направление любого разветвления будет пройдено хотя бы на одном тесте. Добавьте недостающие тесты.
• Проверьте текст модуля, чтобы убедиться, что для каждого цикла существуют тесты, обеспечивающие, по крайней мере, три следующие ситуации: тело цикла не выполняется ни разу, тело цикла выполняется один раз и тело цикла выполняется максимальное число раз. Добавьте недостающие тесты.
• Проверьте текст модуля, чтобы убедиться, что существуют тесты, проверяющие чувствительность к отдельным особым значениям входных данных. Добавьте недостающие тесты.
Комплексная отладка программного средства
Как уже было сказано выше, при комплексной отладке тестируется ПС в целом, причем тесты готовятся по каждому из документов ПС. Тестирование этих документов производится, как правило, в порядке, обратном их разработке. Исключение составляет лишь тестирование документации по применению, которая разрабатывается по внешнему описанию параллельно с разработкой текстов программ - это тестирование лучше производить после завершения тестирования внешнего описания. Тестирование при комплексной отладке представляет собой применение ПС к конкретным данным, которые в принципе могут возникнуть у пользователя (в частности, все тесты готовятся в форме, рассчитанной на пользователя), но, возможно, в моделируемой (а не в реальной) среде. Например, некоторые недоступные при комплексной отладке устройства ввода и вывода могут быть заменены их программными имитаторами.
Тестирование архитектуры ПС. Целью тестирования является поиск несоответствия между описанием архитектуры и совокупностью программ ПС. К моменту начала тестирования архитектуры ПС должна быть уже закончена автономная отладка каждой подсистемы. Ошибки реализации архитектуры могут быть связаны, прежде всего, с взаимодействием этих подсистем, в частности, с реализацией архитектурных функций (если они есть). Поэтому хотелось бы проверить все пути взаимодействия между подсистемами ПС. При этом желательно хотя бы протестировать все цепочки выполнения подсистем без повторного вхождения последних. Если заданная архитектура представляет ПС в качестве малой системы из выделенных подсистем, то число таких цепочек будет вполне обозримо.
Тестирование внешних функций. Целью тестирования является поиск расхождений между функциональной спецификацией и совокупностью программ ПС. Несмотря на то, что все эти программы автономно уже отлажены, указанные расхождения могут быть, например, из-за несоответствия внутренних спецификаций программ и их модулей (на основании которых производилось автономное тестирование) функциональной спецификации ПС. Как правило, тестирование внешних функций производится так же, как и тестирование модулей на первом шаге, т.е. как черного ящика.
Тестирование качества ПС. Целью тестирования является поиск нарушений требований качества, сформулированных в спецификации качества ПС. Это наиболее трудный и наименее изученный вид тестирования. Ясно лишь, что далеко не каждый примитив качества ПС может быть испытан тестированием. Завершенность ПС проверяется уже при тестировании внешних функций. На данном этапе тестирование этого примитива качества может быть продолжено, если требуется получить какую-либо вероятностную оценку степени надежности ПС. Однако, методика такого тестирования еще требует своей разработки. Могут тестироваться такие примитивы качества, как точность, устойчивость, защищенность, временная эффективность, в какой-то мере - эффективность по памяти, эффективность по устройствам, расширяемость и, частично, независимость от устройств. Каждый из этих видов тестирования имеет свою специфику и заслуживает отдельного рассмотрения. Мы здесь ограничимся лишь их перечислением. Легкость применения ПС (критерий качества, включающий несколько примитивов качества) оценивается при тестировании документации по применению ПС.
Тестирование документации по применению ПС. Целью тестирования является поиск несогласованности документации по применению и совокупностью программ ПС, а также выявление неудобств, возникающих при применении ПС. Этот этап непосредственно предшествует подключению пользователя к завершению разработки ПС (тестированию определения требований к ПС и аттестации ПС), поэтому весьма важно разработчикам сначала самим воспользоваться ПС так, как это будет делать пользователь. Все тесты на этом этапе готовятся исключительно на основании только документации по применению ПС. Прежде всего, должны тестироваться возможности ПС как это делалось при тестировании внешних функций, но только на основании документации по применению. Должны быть протестированы все неясные места в документации, а также все примеры, использованные в документации. Далее тестируются наиболее трудные случаи применения ПС с целью обнаружить нарушение требований относительности легкости применения ПС.
Тестирование определения требований к ПС. Целью тестирования является выяснение, в какой мере ПС не соответствует предъявленному определению требований к нему. Особенность этого вида тестирования заключается в том, что его осуществляет организация-покупатель или организация-пользователь ПС [10.1] как один из путей преодоления барьера между разработчиком и пользователем. Обычно это тестирование производится с помощью контрольных задач - типовых задач, для которых известен результат решения. В тех случаях, когда разрабатываемое ПС должно придти на смену другой версии ПС, которая решает хотя бы часть задач разрабатываемого ПС, тестирование производится путем решения общих задач с помощью как старого, так и нового ПС (с последующим сопоставлением полученных результатов). Иногда в качестве формы такого тестирования используют опытную эксплуатацию ПС - ограниченное применение нового ПС с анализом использования результатов в практической деятельности. По существу, этот вид тестирования во многом перекликается с испытанием ПС при его аттестации, но выполняется до аттестации, а иногда и вместо аттестации.
Поделиться62008-01-17 23:29:06
69. Инструментальные среды разработки и сопровождения ПС
Инструментальные среды разработки и сопровождения программных средств.
В настоящее время с каждой системой программирования связываются не отдельные инструменты (например, компилятор), а некоторая логически связанная совокупность программных и аппаратных инструментов поддерживающих разработку и сопровождение ПС на данном языке программирования или ориентированных на какую-либо конкретную предметную область. Такую совокупность будем называть инструментальной средой разработки и сопровождения ПС. Для таких инструментальных сред характерно, во-первых, использование как программных, так и аппаратных инструментов, и, во-вторых, определенная ориентация либо на конкретный язык программирования, либо на конкретную предметную область.
Инструментальная среда не обязательно должна функционировать на том компьютере, на котором должно будет применяться разрабатываемое с помощью ее ПС. Часто такое совмещение бывает достаточно удобным (если только мощность используемого компьютера позволяет это): не нужно иметь дело с компьютерами разных типов, в разрабатываемую ПС можно включать компоненты самой инструментальной среды. Однако, если компьютер, на котором должно применяться ПС, недоступен для разработчиков этого ПС (например, он постоянно занят другой работой, которую нельзя прерывать, или он находится еще в стадии разработки), либо неудобен для разработки ПС, либо мощность этого компьютера недостаточна для обеспечения функционирования требуемой инструментальной среды, то применяется так называемый инструментально-объектный подход. Сущность его заключается в том, что ПС разрабатывается на одном компьютере, называемым инструментальным, а применяться будет на другом компьютере, называемым целевым (или объектным).
Различают три основных класса инструментальных сред разработки и сопровождения ПС: •
• среды программирования, •
• рабочие места компьютерной технологии,•
• инструментальные системы технологии программирования.
Среда программирования предназначена в основном для поддержки процессов программирования (кодирования), тестирования и отладки ПС. Рабочее место компьютерной технологии ориентировано на поддержку ранних этапов разработки ПС (спецификаций) и автоматической генерации программ по спецификациям. Инструментальная система технологии программирования предназначена для поддержки всех процессов разработки и сопровождения в течение всего жизненного цикла ПС и ориентирована на коллективную разработку больших программных систем с длительным жизненным циклом. Для таких систем стоимость сопровождения обычно превышает стоимость разработки.
Рис. Основные классы инструментальных сред разработки и сопровождения ПС.
Инструментальные среды программирования.
Инструментальные среды программирования содержат прежде всего текстовый редактор, позволяющий конструировать программы на заданном языке программирования, инструменты, позволяющие компилировать или интерпретировать программы на этом языке, а также тестировать и отлаживать полученные программы. Кроме того, могут быть и другие инструменты, например, для статического или динамического анализа программ. Взаимодействуют эти инструменты между собой через обычные файлы с помощью стандартных возможностей файловой системы.
Различают следующие классы инструментальных сред программирования (см. рис. 14.2): •
среды общего назначения,•
языково-ориентированные среды.
Инструментальные среды программирования общего назначения содержат набор программных инструментов, поддерживающих разработку программ на разных языках программирования (например, текстовый редактор, редактор связей или интерпретатор языка целевого компьютера) и обычно представляют собой некоторое расширение возможностей используемой операционной системы. Для программирования в такой среде на каком-либо языке программирования потребуются дополнительные инструменты, ориентированные на этот язык (например, компилятор).
Рис. Классификация инструментальных сред программирования.
Языково-ориентированная инструментальная среда программирования предназначена для поддержки разработки ПС на каком-либо одном языке программирования и знания об этом языке существенно использовались при построении такой среды. Вследствие этого в такой среде могут быть доступны достаточно мощные возможности, учитывающие специфику данного языка. Такие среды разделяются на два подкласса:
• интерпретирующие среды, •
• синтаксически-управляемые среды.
Интерпретирующая инструментальная среда программирования обеспечивает интерпретацию программ на данном языке программирования, т.е. содержит прежде всего интерпретатор языка программирования, на который эта среда ориентирована. Такая среда необходима для языков программирования интерпретирующего типа (таких, как Лисп), но может использоваться и для других языков (например, на инструментальном компьютере). Синтаксически-управляемая инструментальная среда программирования базируется на знании синтаксиса языка программирования, на который она ориентирована. В такой среде вместо текстового используется синтаксически-управляемый редактор, позволяющий пользователю использовать различные шаблоны синтаксических конструкций (в результате этого разрабатываемая программа всегда будет синтаксически правильной). Одновременно с программой такой редактор формирует (в памяти компьютера) ее синтаксическое дерево, которое может использоваться другими инструментами.
Понятие компьютерной технологии разработки программных средств и ее рабочие места.
Имеются некоторые трудности в выработке строгого определения CASE-технологии (компьютерной технологии разработки ПС). CASE - это абревиатура от английского Computer-Aided Software Engineering (Компьютерно-Помогаемая Инженерия Программирования). Но без помощи (поддержки) компьютера ПС уже давно не разрабатываются (используется хотя бы компилятор). В действительности, в это понятие вкладывается более узкий (специальный) смысл, который постепенно размывается (как это всегда бывает, когда какое-либо понятие не имеет строгого определения). Первоначально под CASE понималась [16.2] инженерия ранних этапов разработки ПС (определение требований, разработка внешнего описания и архитектуры ПС) с использованием программной поддержки (программных инструментов). Теперь под CASE может пониматься [16.2] и инженерия всего жизненного цикла ПС (включая и его сопровождение), но только в том случае, когда программы частично или полностью генерируются по документам, полученным на указанных ранних этапах разработки. В этом случае CASE-технология стала принципиально отличаться от ручной (традиционной) технологии разработки ПС: изменилось не только содержание технологических процессов, но и сама их совокупность.
В настоящее время компьютерную технологию разработки ПС можно характеризовать использованием:
• программной поддержки для разработки графических требований и графических спецификаций ПС, •
• автоматической генерации программ на каком-либо языке программирования или в машинном коде (частично или полностью), •
• программной поддержки прототипирования.
Говорят также, что компьютерная технология разработки ПС является "безбумажной", т.е. рассчитанной на компьютерное представление программных документов. Однако, уверенно отличить ручную технологию разработки ПС от компьютерной по этим признакам довольно трудно. Значит, самое существенное в компьютерной технологии не выделено.
На наш взляд, главное отличие ручной технологии разработки ПС от компьютерной заключается в следующем. Ручная технология ориентирована на разработку документов, одинаково понимаемых разными разработчиками ПС, тогда как компьютерная технология ориентирована на обеспечение семантического понимания (интерпретации) документов программной поддержкой компьютерной технологии. Компьютерное представление документов еще не означает такого их понимание. Тогда как семантическое понимание документов дает программной поддержке возможность автоматической генерации программ, а необходимость обеспечения такого понимания делает желательными и различные графические формы входных документов. Именно это позволяет рационально изменить и саму совокупность технологических процессов разработки и сопровождения ПС.
Из проведенного обсуждения сущности компьютерной технологии можно понять и связанные с ней изменения в жизненном цикле ПС. Если при использовании ручной технологии основные усилия по разработке ПС делались на этапах собственно программирования (кодирования) и отладки (тестирования), то при использовании компьютерной технологии - на ранних этапах разработки ПС (определения требований и функциональной спецификации). При этом существенно изменился характер документации: вместо целой цепочки неформальных документов, ориентированной на передачу информации от заказчика (пользователя) к различным категориям разработчикам, формируются прототип ПС, поддерживающий выбранный пользовательский интерфейс, и формальные функциональные спецификации, достаточные для автоматического синтеза (генерации) программ ПС (или хотя бы значительной их части). При этом появилась возможность автоматической генерации части документации, необходимой разработчикам и пользователям. Вместо ручного программирования (кодирования) - автоматическая генерация программ, что делает не нужной автономную отладку и тестирование программ: вместо нее добавляется достаточно глубокий автоматический семантический контроль документации. Существенно изменяется и характер сопровождения ПС: все изменения разработчиком-сопроводителем вносятся только в спецификации (включая и прототип), остальные изменения в ПС осуществляются автоматически.
С учетом сказанного жизненный цикл ПС с использованием компьютерной технологии можно представить следующей схемой (рис. 16.3).
Рис. Жизненный цикл программного средства при использовании компьютерной технологии.
Прототипирование позволяет заменить косвенное описание взаимодействия между пользователем и ПС при ручной технологии (при определении требований к ПС и внешнем описании ПС) прямым выбором пользователем способа и стиля этого взаимодействия с фиксацией всех необходимых деталей. По-существу, на этом этапе производится точное описание пользовательского интерфейса, понятное программной поддержке компьютерной технологии, причем с ответственным участием пользователя: разработчик показывает пользователю на мониторе различные возможности и пользователь выбирает приемлемые для него варианты, пользователь с помощью разработчика вводит обозначения обрабатываемых им информационных объектов и операций над ними, он выбирает способ доступа к ним и связывает их с различными окнами, меню, виртуальными клавиатурами и т.п. Все это базируется на наличие в программной поддержке компьютерной технологии настраиваемой оболочки с обширной библиотекой заготовок различных фрагментов и деталей экрана. В результате указанных действий определяется оболочка ПС - верхний управляющий уровень ПС. Такое прототипирование, по-видимому, является лучшим способом преодоления барьера между пользователем и разработчиком.
Разработка спецификаций распадается на несколько разных процессов. Если исключить начальный этап разработки спецификаций (определение требований), то в этих процессах используются методы, приводящие к созданию формализованных документов, т. е. используются формализованные языки спецификаций. При этом широко используются графические методы спецификаций, приводящие к созданию различных схем и диаграмм, которые достаточно формализованно определяют структуру информационной среды и структуру управления ПС. К таким структурам привязываются фрагменты описания данных и программ, представленные на алгебраических языках спецификаций (например, использующие операционную или аксиоматическую семантику), или логических языках спецификаций (базирующихся на логическом подходе к спецификации программ). Такие спецификации позволяют в значительной степени или полностью автоматически генерировать программы.
Автоматизированный контроль спецификаций
Инструментальные системы технологии программирования.
Для компьютерной поддержки разработки и сопровождения больших ПС с продолжительным жизненным циклом используются инструментальные системы технологии программирования. Инструментальная система технологии программирования - это интегрированная совокупность программных и аппаратных инструментов, поддерживающая все процессы разработки и сопровождения больших ПС в течение всего его жизненного цикла в рамках определенной технологии. Из этого определения вытекают следующие основные черты этого класса компьютерной поддержки: •
• комплексность, •
• ориентированность на коллективную разработку, •
• технологическая определенность, •
• интегрированность.
Комплексность компьютерной поддержки означает, что она охватывает все процессы разработки и сопровождения ПС и что продукция этих процессов согласована и взаимоувязана. Тем самым, система в состоянии обеспечить, по-крайней мере, контроль полноты (комплектности) создаваемой документации (включая набор программ) и согласованности ее изменения (версионности). Тот факт, что компьютерная поддержка охватывает и фазу сопровождения ПС, означает, что система должна поддерживать работу сразу с несколькими вариантами ПС, ориентированными на разные условия применения ПС и на разную связанную с ним аппаратуру, т.е. должна обеспечивать управление конфигурацией ПС.
Ориентированность на коллективную разработку означает, что система должна поддерживать управление (management) работой коллектива и для разных членов этого коллектива обеспечивать разные права доступа к различным фрагментам продукции технологических процессов.
Технологическая определенность компьютерной поддержки означает, что ее комплексность ограничивается рамками какой-либо конкретной технологии программирования. Инструментальные системы технологии программирования представляют собой достаточно большие и дорогие ПС, чтобы как-то была оправданна их инструментальная перегруженность. Поэтому набор включаемых в них инструментов тщательно отбирается с учетом потребностей предметной области, используемых языков и выбранной технологией программирования.
Интегрированность компьютерной поддержки означает•
• интегрированность по данным, •
• интегрированность по пользовательскому интерфейсу, •
• интегрированность по действиям (функциям),
Интегрированность по данным означает, что инструменты действуют в соответствии с фиксированной информационной схемой (моделью) системы, определяющей зависимость различных используемых в системе фрагментов данных (информационных объектов) друг от друга. Интегрированность по пользовательскому интерфейсу означает, что все инструменты объединены единым пользовательским интерфейсом. Интегрированность по действиям означает, что, во-первых, в системе имеются общие части всех инструментов и, во-вторых, одни инструменты при выполнении своих функций могут обращаться к другим инструментам.
С учетом обсужденных свойств инструментальных систем технологии программирования можно выделить три их основные компоненты:•
• база данных разработки (репозиторий),•
• инструментарий, •
• интерфейсы.
Репозиторий - центральное компьютерное хранилище информации, связанной с проектом (разработкой) ПС в течении всего его жизненного цикла. Инструментарий - набор инструментов, определяющий возможности, предоставляемые системой коллективу разработчиков. Обычно этот набор является открытым: помимо минимального набора (встроенные инструменты), он содержит средства своего расширения (импортированными инструментами), - и структурированным, состоящим из некоторой общей части всех инструментов (ядра) и структурных (иногда иерархически связанных) классов инструментов. Интерфейсы разделяются на пользовательский и системные. Пользовательский интерфейс обеспечивает доступ разработчикам к инструментарию (командный язык и т.п.), реализуется оболочкой системы. Системные интерфейсы обеспечивают взаимодействие между инструментами и их общими частями. Системные интерфейсы выделяются как архитектурные компоненты в связи с открытостью системы - их обязаны использовать новые (импортируемые) инструменты, включаемые в систему.
Самая общая архитектура инструментальных систем технологии программирования представлена на рис.
Различают два класса инструментальных систем технологии программирования: инструментальные системы поддержки проекта и языково-зависимые инструментальные системы. Инструментальная система поддержки проекта - это открытая система, способная поддерживать разработку ПС на разных языках программирования после соответствующего ее расширения программными инструментами, ориентированными на выбранный язык. Такая система содержит ядро (обеспечивающее, в частности, доступ к репозиторию), набор инструментов, поддерживающих управление (management) разработкой ПС, независимые от языка программирования инструменты, поддерживающие разработку ПС (текстовые и графические редакторы, генераторы отчетов и т.п.), а также инструменты расширения системы. Языково-зависимая инструментальная система - это система поддержки разработки ПС на каком-либо одном языке программирования, существенно использующая в организации своей работы специфику этого языка. Эта специфика может сказываться и на возможностях ядра (в том числе и на структуре репозитория), и на требованиях к оболочке и инструментам. Примером такой системы является среда поддержки программирования на Аде (APSE).
Рис. Общая архитектура инструментальных систем технологии программирования.
Поделиться72008-01-19 00:21:29
66. Методы разработки структуры ПС. Восходящая разработка ПС. Нисходящая разработка. Конструктивный подход. Архитектурный подход разработки ПС.
Методы разработки структуры программы.
Как уже отмечалось выше, в качестве модульной структуры программы принято использовать древовидную структуру, включая деревья со сросшимися ветвями. В узлах такого дерева размещаются программные модули, а направленные дуги (стрелки) показывают статическую подчиненность модулей, т.е. каждая дуга показывает, что в тексте модуля, из которого она исходит, имеется ссылка на модуль, в который она входит. Другими словами, каждый модуль может обращаться к подчиненным ему модулям, т.е. выражается через эти модули. При этом модульная структура программы, в конечном счете, должна включать и совокупность спецификаций модулей, образующих эту программу. Спецификация программного модуля содержит, во-первых, синтаксическую спецификацию его входов, позволяющую построить на используемом языке программирования синтаксически правильное обращение к нему (к любому его входу), и, во-вторых, функциональную спецификацию модуля (описание семантики функций, выполняемых этим модулем по каждому из его входов). Функциональная спецификация модуля строится так же, как и функциональная спецификация ПС.
В процессе разработки программы ее модульная структура может по-разному формироваться и использоваться для определения порядка программирования и отладки модулей, указанных в этой структуре. Поэтому можно говорить о разных методах разработки структуры программы. Обычно в литературе обсуждаются два метода [7.1, 7.7]: метод восходящей разработки и метод нисходящей разработки.
Метод восходящей разработки заключается в следующем. Сначала строится модульная структура программы в виде дерева. Затемпоочередно программируются модули программы, начиная с модулей самого нижнего уровня (листья дерева модульной структуры программы), в таком порядке, чтобы для каждого программируемого модуля были уже запрограммированы все модули, к которым он может обращаться. После того, как все модули программы запрограммированы, производится их поочередное тестирование и отладка в принципе в таком же (восходящем) порядке, в каком велось их программирование. На первый взгляд такой порядок разработки программы кажется вполне естественным: каждый модуль при программировании выражается через уже запрограммированные непосредственно подчиненные модули, а при тестировании использует уже отлаженные модули. Однако, современная технология не рекомендует такой порядок разработки программы. Во-первых, для программирования какого-либо модуля совсем не требуется текстов используемых им модулей - для этого достаточно, чтобы каждый используемый модуль был лишь специфицирован (в объеме, позволяющем построить правильное обращение к нему), а для тестирования его возможно (и даже, как мы покажем ниже, полезно) используемые модули заменять их имитаторами (заглушками). Во-вторых, каждая программа в какой-то степени подчиняется некоторым внутренним для нее, но глобальным для ее модулей соображениям (принципам реализации, предположениям, структурам данных и т.п.), что определяет ее концептуальную целостность и формируется в процессе ее разработки. При восходящей разработке эта глобальная информация для модулей нижних уровней еще не ясна в полном объеме, поэтому очень часто приходится их перепрограммировать, когда при программировании других модулей производится существенное уточнение этой глобальной информации (например, изменяется глобальная структура данных). В-третьих, при восходящем тестировании для каждого модуля (кроме головного) приходится создавать ведущую программу (модуль), которая должна подготовить для тестируемого модуля необходимое состояние информационной среды и произвести требуемое обращение к нему. Это приводит к большому объему "отладочного" программирования и в то же время не дает никакой гарантии, что тестирование модулей производилось именно в тех условиях, в которых они будут выполняться в рабочей программе.
Метод нисходящей разработки заключается в следующем. Как и в предыдущем методе сначала строится модульная структура программы в виде дерева. Затем поочередно программируются модули программы, начиная с модуля самого верхнего уровня (головного), переходя к программированию какого-либо другого модуля только в том случае, если уже запрограммирован модуль, который к нему обращается. После того, как все модули программы запрограммированы, производится их поочередное тестирование и отладка в таком же (нисходящем) порядке. При таком порядке разработки программы вся необходимая глобальная информация формируется своевременно, т.е. ликвидируется весьма неприятный источник просчетов при программировании модулей. Существенно облегчается и тестирование модулей, производимое при нисходящем тестировании программы. Первым тестируется головной модуль программы, который представляет всю тестируемую программу и поэтому тестируется при "естественном" состоянии информационной среды, при котором начинает выполняться эта программа. При этом все модули, к которым может обращаться головной, заменяются на их имитаторы (так называемые заглушки [7.5]). Каждый имитатор модуля представляется весьма простым программным фрагментом, сигнализирующим, в основном, о самом факте обращения к имитируемому модулю с необходимой для правильной работы программы обработкой значений его входных параметров (иногда с их распечаткой) и с выдачей, если это необходимо, заранее запасенного подходящего результата. После завершения тестирования и отладки головного и любого последующего модуля производится переход к тестированию одного из модулей, которые в данный момент представлены имитаторами, если таковые имеются. Для этого имитатор выбранного для тестирования модуля заменяется на сам этот модуль и добавляются имитаторы тех модулей, к которым может обращаться выбранный для тестирования модуль. При этом каждый такой модуль будет тестироваться при "естественных" состояниях информационной среды, возникающих к моменту обращения к этому модулю при выполнении тестируемой программы. Таким образом большой объем "отладочного" программирования заменяется программированием достаточно простых имитаторов используемых в программе модулей. Кроме того, имитаторы удобно использовать для подыгрывания процессу подбора тестов путем задания нужных результатов, выдаваемых имитаторами.
Некоторым недостатком нисходящей разработки, приводящим к определенным затруднениям при ее применении, является необходимость абстрагироваться от базовых возможностей используемого языка программирования, выдумывая абстрактные операции, которые позже нужно будет реализовать с помощью выделенных в программе модулей. Однако способность к таким абстракциям представляется необходимым условием разработки больших программных средств, поэтому ее нужно развивать.
В рассмотренных методах восходящей и нисходящей разработок (которые мы будем называть классическими) модульная древовидная структуру программы должна разрабатываться до начала программирования модулей. Однако такой подход вызывает ряд возражений: представляется сомнительным, чтобы до программирования модулей можно было разработать структуру программы достаточно точно и содержательно. На самом деле это делать не обязательно: так при конструктивном и архитектурном подходах к разработке программ [7.3] модульная структура формируется в процессе программирования модулей.
Конструктивный подход к разработке программы представляет собой модификацию нисходящей разработки, при которой модульная древовидная структура программы формируется в процессе программирования модуля. Сначала программируется головной модуль, исходя из спецификации программы в целом, причем спецификация программы является одновременно и спецификацией ее головного модуля, так как последний полностью берет на себя ответственность за выполнение функций программы. В процессе программирования головного модуля, в случае, если эта программа достаточно большая, выделяются подзадачи (внутренние функции), в терминах которых программируется головной модуль. Это означает, что для каждой выделяемой подзадачи (функции) создается спецификация реализующего ее фрагмента программы, который в дальнейшем может быть представлен некоторым поддеревом модулей. Важно заметить, что здесь также ответственность за выполнение выделенной функции берет головной (может быть, и единственный) модуль этого поддерева, так что спецификация выделенной функции является одновременно и спецификацией головного модуля этого поддерева. В головном модуле программы для обращения к выделенной функции строится обращение к головному модулю указанного поддерева в соответствии с созданной его спецификацией. Таким образом, на первом шаге разработки программы (при программировании ее головного модуля) формируется верхняя начальная часть дерева, например, такая, которая показана на рис. 7.1.
Рис. 7.1. Первый шаг формирования модульной структуры программы при конструктивном подходе.
Аналогичные действия производятся при программировании любого другого модуля, который выбирается из текущего состояния дерева программы из числа специфицированных, но пока еще не запрограммированных модулей. В результате этого производится очередное доформирование дерева программы, например, такое, которое показано на рис. 7.2.
Архитектурный подход к разработке программы представляет собой модификацию восходящей разработки, при которой модульная структура программы формируется в процессе программирования модуля. Но при этом ставится существенно другая цель разработки: повышение уровня используемого языка программирования, а не разработка конкретной программы. Это означает, что для заданной предметной области выделяются типичные функции, каждая из которых может использоваться при решении разных задач в этой области, и специфицируются, а затем и программируются отдельные программные модули, выполняющие эти функции. Так как процесс выделения таких функций связан с накоплением и обобщением опыта решения задач в заданной предметной области, то обычно сначала выделяются и реализуются отдельными модулями более простые функции, а затем постепенно появляются модули, использующие ранее выделенные функции. Такой набор модулей создается в расчете на то, что при разработке той или иной программы заданной предметной области в рамках конструктивного подхода могут оказаться приемлемыми некоторые из этих модулей. Это позволяет существенно сократить трудозатраты на разработку конкретной программы путем подключения к ней заранее заготовленных и проверенных на практике модульных структур нижнего уровня. Так как такие структуры могут многократно использоваться в разных конкретных программах, то архитектурный подход может рассматриваться как путь борьбы с дублированием в программировании. В связи с этим программные модули, создаваемые в рамках архитектурного подхода, обычно параметризуются для того, чтобы усилить применимость таких модулей путем настройки их на параметры.
Рис. 7.2. Второй шаг формирования модульной структуры программы при конструктивном подходе.
В классическом методе нисходящей разработки рекомендуется сначала все модули разрабатываемой программы запрограммировать, а уж затем начинать нисходящее их тестирование [7.5]. Однако такой порядок разработки не представляется достаточно обоснованным: тестирование и отладка модулей может привести к изменению спецификации подчиненных модулей и даже к изменению самой модульной структуры программы, так что в этом случае программирование некоторых модулей может оказаться бесполезно проделанной работой. Нам представляется более рациональным другой порядок разработки программы, известный в литературе как метод нисходящей реализации. В этом методе каждый запрограммированный модуль начинают сразу же тестировать до перехода к программированию другого модуля.
Все эти методы имеют еще различные разновидности в зависимости от того, в какой последовательности обходятся узлы (модули) древовидной структуры программы в процессе ее разработки [7.1]. Это можно делать, например, по слоям (разрабатывая все модули одного уровня, прежде чем переходить к следующему уровню). При нисходящей разработке дерево можно обходить также в лексикографическом порядке (сверху-вниз, слева-направо). Возможны и другие варианты обхода дерева. Так, при конструктивной реализации для обхода дерева программы целесообразно следовать идеям Фуксмана, которые он использовал в предложенном им методе вертикального слоения [7.8]. Сущность такого обхода заключается в следующем. В рамках конструктивного подхода сначала реализуются только те модули, которые необходимы для самого простейшего варианта программы, которая может нормально выполняться только для весьма ограниченного множества наборов входных данных, но для таких данных эта задача будет решаться до конца.
Рис. 7.3. Классификация методов разработки структуры программ.
Вместо других модулей, на которые в такой программе имеются ссылки, в эту программу вставляются лишь их имитаторы, обеспечивающие, в основном, контроль за выходом за пределы этого частного случая. Затем к этой программе добавляются реализации некоторых других модулей (в частности, вместо некоторых из имеющихся имитаторов), обеспечивающих нормальное выполнение для некоторых других наборов входных данных. И этот процесс продолжается поэтапно до полной реализации требуемой программы. Таким образом, обход дерева программы производится с целью кратчайшим путем реализовать тот или иной вариант (сначала самый простейший) нормально действующей программы. В связи с этим такая разновидность конструктивной реализации получила название метода целенаправленной конструктивной реализации. Достоинством этого метода является то, что уже на достаточно ранней стадии создается работающий вариант разрабатываемой программы. Психологически это играет роль допинга, резко повышающего эффективность разработчика. Поэтому этот метод является весьма привлекательным.
Подводя итог сказанному, на рис. 7.3 представлена общая схема классификации рассмотренных методов разработки структуры программы.