Здавалка
Главная | Обратная связь

Нисходящее структурное программирование

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

 

1. Нисходящая разработка программ. На всех этапах вначале определяются решения наиболее общих проблем, а затем поэтапно выполняется их детализация (это позволяет последовательно концентрировать внимание на небольших фрагментах разработки).

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

A.Определяетсяобщая структура программыв виде одного из трех вариантов:

· последовательности подзадач (например, ввод данных, преобразование данных, вывод данных),

· альтернативы подзадач (например, добавление записей к файлу или их поиск),

· повторения подзадачи (например, циклическая обработка данных);

B.Выполняетсядекомпозиция каждой задачи на более простые подзадачи с использованием тех же структур;

 

Пусть f — композиция двух более простых функций g и h, т.е. f(x) = g[ h(x) ]. Проблема разработки алгоритма для f сводится к проблеме разработки более простых алгоритмов для g и h.

 

Процесс декомпозиции (шаги A и B) продолжается, пока не будут получены подзадачи, которые достаточно просто решаются средствами языка программирования (порядка 5 операторов).

2. Использование определенных структур алгоритмов.Идеология структурного программирования требует, чтобы после завершения декомпозиции структура программы имела вид дерева (а не сети с циклами).

 

Повторяющиеся действия должны включаться во все ветви программы, в которых они необходимы.

 

Эта структура должна представлять собой комбинацию элементарных структур управления, имеющих один вход и один выход (S (statement) — оператор или процедура, B (boolean) — логическое выражение):

 

 

По каждой из ветвей предусмотрено выполнение только по одному оператору. Если необходимо выполнить несколько действий, используют следование DO … OD.

 

Исходя их требований удобства и естественности, допускается большее разнообразие структур управления, которые также имеют один вход и один выход. Они считаются «квазиструктурными».

 

 

Программа, составленная из таких структур управления, будет иметь один вход и один выход.

 

3. Использование определенного стиля программирования.Желательно соблюдать следующие условия.

 

A. Сегментация программ (свойство модульности). Структурированная программа должна реализовываться в виде программных модулей — функционально независимых сегментов программы, к каждому из которых предъявляются следующие требования:

· наличие одного входа и одной точки возврата в вызывающую программу;

 

В некоторых языках допускается несколько точек выхода, но это скорее исключение из правил.

 

· ограниченные размеры;

 

На практике — 50-80 строк программного кода (до 2 страниц как смысловых единиц восприятия), что сводит к минимуму необходимость «перелистывания» для отслеживания передачи управления.

 

· взаимодействие с другими модулями на уровне обмена данными.

Согласно правилам нисходящего программирования, модули должны образовывать иерархию. Модуль верхнего уровня оформляется как главная процедура (основная программа). Он должен включать объявления только глобальных переменных, общих для всех модулей. Объявления локальных переменных включаются в те модули, где эти переменные используются.

 

Сегментация сама по себе не гарантирует отсутствия ошибок в программе, особенно при значительных размерах модулей или при большом числе уровней их вложенности.

 

B. Отказ от использования сложных методов там, где можно использовать простые.

 

Использование профессиональных приемов только для демонстрации способностей программиста недопустимо.

Пример: перестановка переменных x « y.

а) используется дополнительная переменная, но получается ясный и универсальный код:

z = x

x = y

y = z

б) экономится лишняя переменная, но затруднено понимание, и будет сказываться влияние ошибок округления для арифметики с плавающей точкой:

x = x + y

y = x – y

x = x – y

в) экономится лишняя переменная, но затруднено понимание, а область применения ограничена упорядоченными типами данных:

x := x Å y

y := x Å y;

x := x Å y;

 

C. Ограниченное использование команд переходов (операторов goto).

 

Строгие правила структурного программирования исключают использование операторов goto. Однако аккуратное их применение допустимо внутри алгоритмических структур, если при этом сохраняется свойство структурных схем «один вход — один выход».

NB. Пара-тройка goto не испортит хорошую по сути программу, в то время как отказ от переходов не приводит автоматически к структурированной программе, и текст ее не становится более понятным. Структурное программирование не является методом, преобразующим неструктурированную программу в программу без команд переходов.

 

D. Реализация альтернативы с помощью конструкции IF–THEN–ELSE (что позволяет избежать неоправданного использования goto).

 

В языке Borland Pascal:  
label xMin, result; ... if x < y then gotoxMin; min := y; gotoresult; xMin: min := x; result: ... if x < y then min := x else min := y;
В языке Borland C:  
if (x < y) gotoxMin; min = y; gotoresult; xMin: min = x; result: ... if (x < y) min = x; else min = y; ... min = (x < y) ? x: y;

 

E. Простота циклов и задание их в явном виде (что позволяет избежать неоправданное использование goto). Использование циклов для переходов по программе.

 

В языке Borland Pascal:  
label start; ... x := 1.0; start: ... x := x + 0.1; if x < 2.0 then gotostart; x := 1.0; while x < 2.0 do begin ... x := x + 0.1; end;
В языке Borland C:  
x = 1.0; start: ... if (x += 0.1) < 2.0 gotostart; for (x = 1.0; x < 2.1; x += 0.1) ... ;

 

G. Грамотное использование рекурсии только в тех случаях, когда она эффективна или позволяет просто описать вычислительную ситуацию. В противном случае рационально использовать итерации.

 

Вычисление факториала числа:

 

В языке Borland Pascal:  
functionF(n: LongInt): LongInt; var i, p: LongInt; begin p := 1; if n > 0 then for i := 1 to n do p := p * i; F := p; end; functionF(n: LongInt): LongInt; begin if n > 1 then F := n * F(n – 1) else F := 1; end;
В языке Borland C:  
longF(long n) { for (long p = 1, long i = 1; i <= n; p *= i); return p; } longF(long n) { return (n > 1) ? n * F(n – 1): 1; }

 

H. Использование содержательных имен, что делает текст программы самодокументируемым.

 

distance = velocity * time;

 

Содержательные имена упрощают операции автоматического поиска и замены по тексту программы.

 

4. Сквозной структурный контроль всех этапов разработки (чем раньше обнаружена ошибка, тем проще ее исправить).

Используя структурный подход к разработке программы, легче доказать ее правильность. Пусть f(x) = g[ h(x) ]. Если алгоритмы для g и h получены, и они правильны, то правильный алгоритм для f получается автоматически.





©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.