Технологии программирования
Шрифт:
Процедура — это не только способ сокращения программного текста, но и, что более важно, средство разложения программы на логически связанные, замкнутые элементы, определяющие ее структуру. Разложение на части существенно для понимания программы, особенно если программа сложна и трудно обозрима из-за большой длины текста. Разложение на подпрограммы необходимо как для документирования, так и для верификации программы. Поэтому желательно оформлять последовательность инструкций в виде подпрограммы, даже если подпрограмма используется однократно и, следовательно, отсутствует
Дополнительная информация о переменных (которые передаются и используются в процедуре) или об условиях, которым должны удовлетворять аргументы, задается в заголовке процедуры. О полезности процедуры, в частности о ее роли при структуризации программы, неоспоримо свидетельствуют еще два понятия в программировании. Некоторые переменные (их обычно называют вспомогательными или локальными переменными), используемые внутри процедуры, не имеют смысла за ее пределами. В программе существенно проще разобраться, если явно указаны области действия таких переменных. Процедура выступает как естественная текстовая единица, с помощью которой ограничивается область существования так называемых локальных переменных.
Вероятно, наиболее общая тактика программирования состоит в разложении процесса на отдельные действия: функционального описания на подфункции, а соответствующих программ — на отдельные инструкции. На каждом таком шаге декомпозиции нужно удостовериться, что решения частных задач приводят к решению общей задачи; выбранная последовательность отдельных действий разумна; выбранная декомпозиция позволяет получить инструкции, в каком-либо смысле более близкие к языку, на котором будет реализована программа.
Последнее требование исключает возможность прямолинейного продвижения от первоначальной постановки задачи к конечной программе, которая должна получиться в конечном итоге. Каждый этап декомпозиции сопровождается формулированием частных подпрограмм. В процессе этой работы может обнаружиться, что выбранная декомпозиция неудачна в том смысле хотя бы потому, что подпрограммы неудобно выражать с помощью имеющихся средств. В этом случае один или несколько предыдущих шагов декомпозиции следует пересмотреть заново.
Если видеть в поэтапной декомпозиции и одновременном развитии и детализации программы постепенное продвижение вглубь, то такой метод при решении задач можно охарактеризовать как нисходящий (сверху вниз). И наоборот, возможен такой подход к решению задачи, когда программист сначала изучает имеющиеся в его распоряжении вычислительную машину и/или язык программирования, а затем собирает некоторые последовательности инструкций в элементарные процедуры, типичные для решаемой задачи. Элементарные процедуры затем используются на следующем уровне иерархии процедур. Такой метод перехода от примитивных машинных команд к требуемой реализации программы называется восходящим (снизу вверх).
На практике разработку программы никогда не удается провести строго в одном направлении (сверху вниз или снизу вверх). Однако при конструировании новых алгоритмов нисходящий метод обычно доминирует.
Оба метода позволяют разрабатывать программы, которым присуща структура — свойство, отличающее их от аморфных линейных последовательностей инструкций или команд машины. И чрезвычайно важно, чтобы используемый язык в полной мере отражал эту структуру. Только тогда окончательный вид полученной программы позволит применить систематические методы верификации.
7.2. МОДУЛЬ И ОСНОВНЫЕ ПРИНЦИПЫ СТРУКТУРНОГО ПОДХОДА
Если программа разбивается на подпрограммы, то для представления результатов и аргументов часто приходится вводить новые переменные и таким образом устанавливать связь между подпрограммами. Такие переменные следует вводить и описывать на том этапе разработки, на котором они потребовались. Более того, детализация описания процесса может сопровождаться детализацией описания структуры используемых переменных. Следовательно, в языке должны быть средства для отражения иерархической структуры данных. Из сказанного видно, какую важную роль играет при пошаговой разработке программы понятие процедуры, локальности процедур и данных, структурирования данных.
Проектирование начинается с фиксации внешних спецификаций. На основании внешних спецификаций составляется описание внутреннего алгоритма программы, обязательно со структурой внутренних данных. Далее крупные функции разбиваются на подфункции до достижения подфункции размера модуля — подпрограммы (процедуры или функции) языка программирования, к которым предъявляются особые дополнительные требования.
Модуль — фундаментальное понятие и функциональный элемент технологии структурного программирования.
Модуль — это подпрограмма, но оформленная в соответствии с особыми правилами.
Правило 1. Модуль должен иметь один вход и один выход и выполнять строго однозначную функцию, которая описывается простым распространенным предложением естественного (русского) языка или даже предложением без сказуемого.
Правило 2. Модуль должен обеспечивать компиляцию, независимую от других модулей, с "забыванием" всех внутренних обозначений модулей.
Правило 3. Модуль может вызывать другие модули по их именам.
Правило 4. Хороший модуль не использует глобальные переменные для общения с другим модулем, так как потом трудно отыскать модуль, который портит данные. Если все же используются глобальные переменные, то нужно четко комментировать те модули, которые только читают, и те модули, которые могут менять данные.
Правило 5. Модуль кодируется только стандартными структурами и тщательно комментируется.