Главная » Статьи » Образовательные » Программирование |
1.
ПОНЯТИЕ СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ Исторически
сложилось так, что императивные языки в настоящее
время доминируют в программировании. Однако исследования, проведенные в
70-80-х годах XX века,
показали, что аппликативная методика обеспечивает более эффективные способы верификации программ и доказательство их корректности. Это видно из блок-схем, представленных на рис. 4. На рис. 4, а изображена блок-схема, типичная для программ 60-х годов XX века. В ней нет никакой
явной структуры. Такие программы называют про-граммами-спагетти.
Из-за большого числа нерациональных передач управления
назад и вперед трудно понять, каково состояние программы в каждый момент
времени в процессе ее выполнения. На рис.
4, б приведена более структурированная конструкция. Каждый
сегмент данной блок-схемы можно заключить в пунктирный прямоугольник. Каждый из таких прямоугольников на этой схеме будет иметь одну точку входа и одну точку
выхода. Эту программу можно рассматривать как композицию четырех функций-подпрограмм, и поведение программы можно
определить как функцию, которая получает данное состояние на входе
выделенного пунктиром прямоугольника и
преобразует его в результирующее состояние на выходе из него. Писать
сложные программы в тысячи и десятки тысяч
строк без расчленения на самостоятельные фрагменты, т. е. без
структурирования, просто невозможно. Структурное
программирование - подход,
при котором для передачи управления в
программе используются только три конструкции, допускающих последовательную,
условную и итеративную передачи управления. При этом безусловная передача
управления например, оператором goto запрещается. Рис. 4. Аппликативные методы в императивных языках В результате
каждая сложная команда в программе, являющаяся
комбинацией последовательных, условных и циклических операторов, имеет
только одну точку входа и одну точку выхода, что дает возможность разбиения
программы на относительно самостоятельные фрагменты. Структурное программирование
является результатом применения аппликативных методов к императивным
программам. Для этого используются
процедурно-ориентированные языки, в которых имеется возможность описания программы как совокупности процедур. Процедуры могут вызывать друг друга, и
каждая из них может быть вызвана
основной программой, которую также можно рассматривать как процедуру. Структурный
подход к программированию представляет собой методологию создания программ. Его
внедрение обеспечивает: повышение
производительности труда программистов при написании и контроле программ; получение
программ, которые более пригодны для сопровождения, так как состоят из
отдельных модулей; создание
программ коллективом разработчиков; окончание
создания программ в заданный срок. В
структурированных программах обычно легко прослеживается основной
алгоритм, они удобнее в отладке и менее чувствительны к ошибкам программирования. Эти свойства являются следствием важной особенности подпрограмм, каждая из
которых представляет собой во многом самостоятельный фрагмент
программы, связанный с основной программой
лишь с помощью нескольких параметров. Такая самостоятельность
подпрограмм позволяет локализовать в них все
детали программной реализации того или иного алгоритмического действия,
и поэтому изменение этих деталей, например в процессе отладки, обычно не
приводит к изменениям основной программы. 2. ПРИНЦИП УТАИВАНИЯ ИНФОРМАЦИИ Концепция структурного программирования предполагает разбиение программы на отдельные компоненты согласно принципу утаивания информации. Принцип утаивания информации заключается в
том, что идентификаторы
локальных объектов (имена констант, типов, переменных, процедур, функций, меток, и полей в записях переменных), то есть
тех, которые используются только внутри заданной последовательности инструкций, не должны иметь смысла за
пределами этих инструкций. Процедуры и
функции выступают как естественные текстовые единицы,
с помощью которых ограничивается область существования локальных
идентификаторов. Идентификатором
называется
строка символов, используемая для
идентификации или именованная (последовательность букв, цифр и знаков подчеркивания, которая начинается с
буквы или символа подчеркивания и не содержит пробелов). Областью
видимости (действия)
идентификатора называется часть программы, где он может быть использован. Область видимости идентификаторов
определяется местом их объявления. Если идентификаторы допускается использовать
только в рамках одной процедуры или
функции, то такие идентификаторы называются локальными. Если
действие идентификаторов распространяется на несколько вложенных (не менее
одной) процедур и/или функций, то такие идентификаторы называются глобальными. Правила определения области видимости для идентификаторов
состоят в следующем: 1) действуют
все идентификаторы, определенные внутри процедуры/функции; 2) действуют
все идентификаторы окружающего контекста, если
их имена отличаются от имен, объявленных внутри процедуры/функции; 3)локальные
идентификаторы процедуры/функции во внешнем окружении не действовуют никогда; 4)в случае совпадения имен глобального
и локального идентификаторов действует
только внутренний, локальный идентификатор, независимо от того
совпадают они по типу, или нет. 3. МЕТОДЫ
СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ При
проектировании любого изделия, в том числе и алгоритма,
на ранних стадиях основное внимание обращается на самые главные проблемы, и искусственно упускаются из виду многие частные детали. Поэтому наиболее общая тактика программирования
состоит в разложении процесса на отдельные действия. На каждом таком
шаге декомпозиции нужно удостовериться, что: решения
частных задач приводят к решению общей задачи; данная последовательность отдельных действий наиболее рациональна; осуществленная декомпозиция позволяет получить инструкции, по своему
смыслу наиболее близкие к языку, на котором впоследствии будет написана программа. Нисходящий
подход к разработке программных систем. В
соответствии с этим методом создание программы начинается
сверху, т.е. с разработки самого главного, генерального алгоритма. Так как на верхнем уровне обычно еще не ясны детали реализации той или иной части программы, то эти
части следует заменить временными заглушками . Прогон
незаконченной программы (перед заменой заглушек реально работающими
процедурами) дает определенную уверенность перед разработкой и реализацией
алгоритмов нижнего уровня. Если реализуемый
в заглушке алгоритм достаточно сложен, его вновь структурируют, выделяя главный алгоритм и применяя новые заглушки и т.д.
(Заглушка - заменяющая компонента, которая временно используется в
программе с тем, чтобы можно было
продолжать ее разработку, т. е. компилирование или тестирование, до того
времени, когда эта компонента будет сделана в надлежащем виде.). Процесс продолжается вниз до
тех пор, пока не будет создан полностью работоспособный вариант программы. На
практике «чистую» нисходящую разработку осуществить невозможно. На одной из
более поздних стадий часто обнаруживается, что
некоторый выбор, сделанный ранее, был неадекватным и это
приводит к необходимости итеративной разработки. Восходящий подход к разработке программ. В этом случае осуществляется последовательное построение программы из уже
имеющихся элементов, начиная с примитивов, предоставляемых выбранным языком программирования. Этот процесс заканчивается получением требуемой готовой программы.
На каждом этапе из имеющихся
элементов строятся более мощные элементы.
Эти элементы будут использоваться на следующем этапе для построения еще более мощных элементов, и так
далее до тех пор, пока не будут
получены элементы, из которых можно непосредственно составить требуемую
программу. На практике
восходящая разработка в чистом виде также как и нисходящая
невозможна. Построение каждого нового элемента должно
сопровождаться просмотром вперед с целью проверки, удовлетворяет ли он требованиям к разрабатываемой программе; но даже и при таком подходе на более позднем этапе часто обнаруживается, что использованная ранее последовательность построения
была выбрана неправильно и требуется новая итерация. При конструировании новых
алгоритмов обычно доминирует нисходящий
метод. При адаптации программ к несколько измененным требованиям
предпочтение зачастую отдается восходящему методу. Оба этих метода позволяют
разрабатывать структурированные программы. 4. СТРУКТУРНАЯ СХЕМА ПРОГРАММЫ И СРЕДСТВА ДЛЯ ЕЕ ИЗМЕНЕНИЯ В понятие структуры
программы (program structure) включается состав и описание связей всех модулей, которые реализуют
самостоятельные функции программы и описание носителей вводимых и выводимых данных, а также данных, участвующих в обмене
между отдельными подпрограммами. Для
разработки больших и сложных программ программисту необходимо
овладеть специальными приемами получения рациональной структуры программы, которая
обеспечивает почти двукратное
сокращение объема программирования и многократное
сокращение Подчиненность
модулей программы отражается в схеме иерархии. Однако последняя не отражает
порядок их вызова или функционирование программы. Схема иерархии может иметь
вид, показанный
на рис. 5. Она, обычно, дополняется расшифровкой функций, выполняемой модулями. Перед
составлением схемы иерархии целесообразно составить внешние спецификации
программы и составить функциональные описания программы вместе с описанием
переменных-носителей данных. Особое внимание
следует уделять иерархии типов структурированных данных и их
комментированию. Расчленение программы на подпрограммы производится по принципу от общего к частному, более детальному. Процесс составления
функционального описания и составления схемы иерархии является итерационным, а
выбор наилучшего варианта является многокритериальным. Расчленение должно
обеспечивать удобный порядок ввода частей в эксплуатацию. Схеме
иерархии можно придать любой топологический рисунок. Фрагменты с
вертикальными вызовами могут быть преобразованы
в вызовы одного уровня посредством введения дополнительного модуля,
который может не выполнять никаких полезных функций с точки зрения алгоритма
программы. Функция нового модуля может
состоять лишь в мониторинге, то есть вызове других модулей в
определенном порядке. Фрагменты с горизонтальными вызовами на одном
уровне могут быть преобразованы в вертикальные вызовы модулей разных уровней
посредством введения дополнительных переменных, которые не могли
быть получены декомпозицией функционального описания
на подфункции. Эти дополнительные переменные обычно имеют тип целый или
логический и называются флагами, семафорами,
ключами событий. Их смысл обычно характеризуется фразой: в зависимости от следующей предыстории
действий, выполнить такие-то
действия. В процессе проектирования нужно сделать несколько проектных итераций, каждый раз генерируя новую схему иерархии, и сравнить эти иерархии по данным критериям для отбора лучшего варианта. Ключ - значение переменной, используемое для подтверждения
полномочий на доступ к некоторой информации или подпрограмме. Флаг — переменная, значение которой свидетельствует о том, что
некоторый аппаратный или программный компонент находится в определенном состоянии или что для него
выполняется определенное условие.
Флаг используется для реализации условного ветвления и прочих процессов
принятия решений. Семафор - тип данных
специального назначения, который является
средством управления доступом к критическому ресурсу со стороны
совместно идущих последовательных процессов. Над семафором
можно производить только две операции (не считая создания
и аннулирования): операцию ожидания (занятия) и операцию
сигнализации (освобождения). Семафор принимает целое значение, которое не
может быть отрицательным. Операция ожидания
уменьшает значение семафора на единицу, когда это можно сделать, не получая при этом отрицательного
значения, и это означает, что
свободный ресурс используется. Операция сигнализации увеличивает
значение семафора на единицу, что означает освобождение ресурса. Критический
ресурс - ресурс, который в каждый момент времени используется
не более чем одним процессом. Когда требуется, чтобы
несколько асинхронных процессов координировали свой доступ к критическому
ресурсу, используется управляемый доступ через семафор. 5. КРИТЕРИИ
ОЦЕНКИ КАЧЕСТВА СТРУКТУРНОЙ
СХЕМЫ ПРОГРАММЫ Первый вариант структурной схемы, полученный путем простого членения функций программы на подфункции с указанием
переменных, необходимых для размещения данных, чаще всего не является оптимальным и требуются проектные итерации для
улучшения топологии схемы. Эти действия обычно выполняются методом «проб и ошибок». Каждый новый вариант сравнивается
с предшествующим по описанным ниже критериям: 1) полнота выполнения специфицированных функций; 2)возможность
быстрого и дешевого пополнения новыми, ранее не специфицированными функциями; 3)обозримость (понятность) для проектировщика составных частей
программы; 4)максимальная независимость отдельных
частей программы; 5) возможность
связывания подпрограмм редактором связей; 6)достаточность оперативной памяти; 7) влияние топологии схемы иерархии на скорость выполнения программы при
использовании динамической загрузки
программы и
механизма подкачки страниц; 8) отсутствие разных модулей со сходными функциями. Один и тот же модуль должен вызываться на разных уровнях схемы иерархии; 9)достижение
такого графика работы коллектива программистов при
реализации программы, который обеспечивает равномерную загрузку
коллектива; 10)всемерное
сокращение затрат на тестирование программы. 11)использование в данном проекте как
можно большего числа проработанных в
предшествующих проектах модулей и библиотек при минимальном объеме
изготавливаемых заново частей. Генерация вариантов прекращается при невозможности дальнейших улучшений. Рациональная структура программы обеспечивает сокращение общего объема текстов в 2-3 раза, что соответственно удешевляет создание программы и ее тестирование, на которое обычно приходится не менее 60% от общих затрат. При этом облегчается и снижается стоимость сопровождения программы. | |
Просмотров: 9896 | Рейтинг: 4.5/2 |
Всего комментариев: 0 | |