logo
Лекции_ПиОА[1]

4.3. Методы разработки структуры программы

В качестве модульной структуры программы используют древовидную структуру. В узлах такого дерева размещаются программные модули, а направленные дуги (стрелки) описывают статическую подчиненность модулей. Каждая дуга показывает, что в тексте модуля, из которого она исходит, имеется ссылка на модуль, в который она входит. Модульная структура программы обязана включать и совокупность спецификаций модулей, ее образующих. Спецификация модуля содержит: 1) спецификацию его входов, позволяющую строить на языке программирования синтаксически корректное обращение к нему или к его входам; 2) функциональную спецификацию, содержащую описание семантики функций, выполняемых модулем по каждому из его входов. Функциональная спецификация модуля строится так же, как и функциональная спецификация ПС.

Различают два метода разработки модульной структуры программы: восходящая и нисходящая разработка.

1. Метод восходящей разработки. Строится модульная структура программы в виде дерева. Затем модули поочередно программируются, начиная с модулей нижнего уровня. Программирование проводится в таком порядке, чтобы для программируемого модуля ранее были запрограммированы те модули, к которым он обращается. Когда модули запрограммированы, производится их поочередное тестирование и отладка в таком же восходящем порядке. Такой порядок естественен, так как каждый модуль выражается через уже запрограммированные подчиненные ему модули, а при тестировании используются уже отлаженные модули. Однако этот порядок разработки не рекомендуется. Во-первых, для программирования модуля не требуется наличия текстов используемых им модулей. Достаточно, чтобы используемый модуль был специфицирован в объеме, позволяющем построить корректное обращение к нему, а для тестирования использовать имитатор (заглушку) этого модуля. Во-вторых, каждая программа подчиняется некоторым внутренним для нее, но глобальным для ее модулей принципам реализации, предположениям, структурам данных и т.п., что и определяет ее концептуальную целостность и направляет процесс разработки. При восходящей разработке эта глобальная концепция для модулей нижних уровней еще не проработана, поэтому приходится отдельные модули перепрограммировать, когда при программировании других модулей производится уточнение этой концепции, например, изменяется глобальная структура данных. В-третьих, при восходящем тестировании для каждого модуля, кроме головного, приходится создавать ведущий модуль, который готовит для тестируемого модуля необходимое состояние информационной среды и производит обращение к нему. Это увеличивает объем "отладочного" программирования и не дает гарантий соответствия условий тестирования реальным условиям применения программы.

2. Метод нисходящей разработки. Как и ранее строится модульная структура программы в виде дерева. Затем поочередно программируются модули, начиная с верхнего уровня, головного модуля, переходя к программированию очередного модуля только тогда, когда запрограммирован модуль, к нему обращающийся. Когда модули запрограммированы, производится их поочередное тестирование и отладка в том же нисходящем порядке. Первым тестируется головной модуль, представляющий всю программу. Он тестируется при "естественном" состоянии информационной среды, определяющей начальное состояние программы. Модули, к которым обращается головной, заменяются имитаторами-заглушками. Имитатор модуля - это программный фрагмент, который сигнализирует о факте обращения к модулю. Он производит обработку значений его входных параметров, например, распечатывает эти значения, и выдает заранее запасенный результат. После завершения тестирования и отладки головного и любого последующего модуля производится переход к тестированию модуля, ранее представленного имитатором. Имитатор заменяется самим модулем, и добавляются имитаторы тех модулей, к которым он обращается. Модуль тестируется при "естественном" состоянии информационной среды, возникшей к моменту обращения к нему. Большой объем "отладочного" программирования при восходящем тестировании заменяется программированием простых имитаторов модулей. При таком порядке разработки информационная среда формируется своевременно. Недостатком нисходящей разработки является необходимость абстрагироваться от базовых возможностей языка программирования, применяя абстрактные операции, которые позже нужно будет реализовать посредством тех же модулей.

Особенностью двух рассмотренных классических методов разработки является наличие модульной структуры программы до начала программирования. Это требование находится в полном соответствии с водопадным подходом, так как разработка структуры программы и ее кодирование производятся на разных этапах разработки. Разработка модульной структуры завершает этап конструирования, а непосредственно программирование  открывает этап кодирования. Если в теоретическом плане классические методы не вызывают возражений, то на практике их реализация сталкивается с рядом трудностей, связанных с тем, что до программирования невозможно точно и содержательно разработать саму структуру программы. Эти затруднения снимаются в рамках конструктивного и архитектурного подходов, модернизирующих водопадный подход и совмещающих процессы модульной структуризации и программирования.

3 . Конструктивный подход - это модификация нисходящей разработки, в которой структура программы формируется в процессе программирования модулей. Разработка программы начинается с головного модуля, исходя из спецификации программы в целом. Она принимается в качестве спецификации ее головного модуля, который берет на себя ответственность за выполнение функций программы в целом. В процессе его программирования выделяются подзадачи (внутренние функции). Это означает, что для выделенной подзадачи-функции создается спецификация фрагмента программы. Фрагмент в дальнейшем может быть представлен некоторым поддеревом модулей. Ответственность за выполнение выделенной функции несет головной модуль этого поддерева. Спецификация этой функции является одновременно и спецификацией головного модуля этого поддерева. В головном модуле программы для обращения к выделенной функции строится обращение к головному модулю указанного поддерева. На первом шаге разработки программы (ее головного модуля) формируется верхняя начальная часть дерева согласно рис. 7. Аналогичные действия производятся при программировании любого другого модуля, который выбирается из числа уже специфицированных модулей. В результате этого производится очередная достройка дерева программы, например, согласно рис. 8.

4. Архитектурный подход - это модификация восходящей разработки, при которой модульная структура программы формируется в процессе программирования. Его целью является не разработка конкретной программы, а повышение уровня использования языка программирования. Это означает, что для данной предметной области выделяются типичные функции, которые могут использоваться при решении разных задач этой области. Эти функции специфицируются, а затем программируются модули, их реализующие. Процесс выделения функций связан с опытом решения задач в предметной области, поэтому сначала выделяются и реализуются простые функции, а затем программируются модули, реализующие более сложные функции с использованием запрограммированных простых функций. Так создается набор модулей в расчете на его применение в программах предметной области. Этот подход сокращает трудозатраты на разработку программы путем подключения заранее заготовленных и проверенных на практике структур нижнего уровня. Такие структуры (модули) могут многократно использоваться в разных программах, поэтому архитектурный подход рассматривается как средство борьбы с дублированием в программировании.

5. Метод нисходящей реализации. В методе нисходящей разработки рекомендуется сначала все модули запрограммировать, а затем провести их нисходящее тестирование. Такой порядок разработки неэффективен. Тестирование и отладка модулей может приводить к изменению спецификации подчиненных модулей и даже к изменению модульной структуры программы, в этом случае программирование некоторых модулей окажется бесполезной работой. Рационален порядок разработки, модифицирующий водопадный подход, и известный как метод нисходящей реализации. В данном методе каждый запрограммированный модуль тестируют сразу же после своего программирования до перехода к программированию другого модуля.

Методы имеют разновидности, зависящие от порядка обхода узлов-модулей древовидной структуры программы. Например, в лексикографическом порядке - сверху вниз или слева направо. Или обход по слоям. Сначала разрабатываются модули одного уровня, а затем следующего.

6. Метод целенаправленной конструктивной реализации. При конструктивной реализации используется метод вертикального слоения Фуксмана, суть которого в следующем. В рамках конструктивного подхода реализуются модули, которые необходимы для простейшего варианта программы, функционирующей для ограниченного набора входных данных. Вместо других модулей, на которые имеются ссылки, используются имитаторы. Затем к программе вместо имитаторов добавляются реализации модулей, обеспечивающие выполнение программы для других наборов входных данных. Процесс продолжается поэтапно до полной реализации программы. В этом методе обход дерева программы производится по кратчайшему пути, реализующему последовательно наращиваемые варианты функционирующей программы, начиная с самого простого. Такая разновидность конструктивной реализации получила название метода целенаправленной конструктивной реализации. Достоинство метода - уже на ранней стадии создается работающий вариант программы. Психологически это играет роль допинга, повышающего эффективность разработчика. Метод перспективен.

Классификация методов разработки структуры программы