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

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

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

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

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

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

Допустим, вы заглянули в холодильник и обнаружили наличие отсутствия колбасы. Возникла задача: пополнить запасы колбасы. Какое решение этой задачи пришло вам на ум? Конечно, пойти в магазин и купить колбасы. Таким образом, вы сформировали общий алгоритм решения – сходить и купить, т.е. задача разбита на две подзадчи «сходить» и «купить».

Теперь перед вами неизбежно возникают «нюансы», ведь за словом «сходить» может крыться и «съездить» (если ближайший магазин закрыт), и даже «позвонить жене/мужу и попросить купить по дороге домой» — в общем, разные варианты. И даже если вы определились с личным походом, прежде чем покинуть дом, вам придется определиться с тем, что надеть, проверить наличие финансов и т.п. То есть укрупненная задача неизбежно распадается на ряд малых, а те в свою очередь могут быть разбиты на еще более мелкие и так до тех пор, пока, наконец, окончательное принятие решения уже будет у вас на интуитивном уровне, т.е. не требующем детализации.

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

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

Пример: Морзе-маячок.

Постановка задачи: требуется разработать программу для радиомаяка, подающего сигнал в виде сообщения из 4 символов азбуки Морзе каждую минуту.

Решение.

Самое интуитивно простое решение задачи заключается в следующем:

  1. Выдать сообщение
  2. Подождать 1 минуту
  3. Перейти к п.1

Это и есть первый этап разработки – общее укрупненное решение. Запишем его, пользуясь возможностями языка Си в виде главной функции нашей программы:

// пока мы не знаем, как, но эта функция передает сообщение

void wait(int sec)<

// пока не знаем, как, но эта функция задерживает исполнение программы на sec секунд

// не забыть добавить в этом месте инициализацию периферии!

Я всегда начинаю писать код с того, что мне известно и понятно, добавляя в него в виде функций-пустышек то, что пока неизвестно или непонятно. Но здесь я привожу код в том виде, как он уже получился, т.е. сначала те самые неизвестно-непонятные функции, а потом уже то, что ясно-понятно. Так будет на протяжении всей статьи – начинайте просмотр врезок кода с конца .

Эта «программа» уже может быть скомпилирована, что является определенным плюсом нисходящего программирования – по мере разработки мы на любом этапе можем проверить, нет ли ошибок в нашем алгоритме путем компиляции. Очевидно, что ошибок в этой программе нет. Наступает следующий этап – детализация имеющихся функций. В этом случае нам, разумеется, поможет знание стандартных библиотек, имеющихся в нашем распоряжении. В частности, в библиотеках WinAVR имеется функция _delay_ms, позволяющая задержать исполнение программы на заданное количество миллисекунд – воспользуемся ею для реализации функции wait в нашей программе:

void wait(int sec)<

Надеюсь, в отдельных комментариях данная функция не нуждается, как и не нуждается в дальнейшей детализации.

Теперь беремся за send_message, причем ровно с тех же позиций: теперь задача «передача сообщения» для нас является главной. Сообщение – это 4 символа. Очевидно, что сообщение передается укрупненно так (сразу записываю на Си):

void send_morse_symbol(char c)<

// пока не знаем как, но эта функция передает один символ азбуки Морзе

Основные технологии

Основные понятия, факты

Структурное программирование. Модульное программирование. Объектно-ориентированное программирование. Базовые принципы ООП: инкапсуляция, наследование, полиморфизм.

Разработка программ с использованием принципов структурного, модульного, объектно-ориентированного программирования.

Основными технологиями разработки программного обеспечения являются

Сутью структурного программирования является возможность разбиения программы на составляющие элементы.

Идеи структурного программирования появились в начале 70-годов в компании IBM , в их разработке участвовали известные ученые Э. Дейкстра, Х. Милс, Э. Кнут, С. Хоор.

Распространены две методики (стратегии) разработки программ, относящиеся к структурному программированию: программирование "сверху вниз" и программирование "снизу вверх".

Программирование "сверху вниз", или нисходящее программирование – это методика разработки программ, при которой разработка начинается с определения целей решения проблемы, после чего идет последовательная детализация, заканчивающаяся детальной программой. Является противоположной методике программирования «снизу вверх».

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

В данном случае программа конструируется иерархически - сверху вниз: от главной программы к подпрограммам самого нижнего уровня, причем на каждом уровне используются только простые последовательности инструкций, циклы и условные разветвления.

Программирование "снизу вверх", или восходящее программирование – это методика разработки программ, начинающаяся с разработки подпрограмм (процедур, функций), в то время когда проработка общей схемы не закончилась. Является противоположной методике программирования «сверху вниз».

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

Достоинства структурного программирования :

1) повышается надежность программ (благодаря хорошему структурированию при проектировании, программа легко поддается тестированию и не создает проблем при отладке);

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

3) уменьшается время и стоимость программной разработки;

4) улучшается читабельность программ.

Резюме

Технология структурного программирования при разработке серьезных программных комплексов, основана на следующих принципах:

- программирование должно осуществляться сверху вниз;

- весь проект должен быть разбит на модули (подпрограммы) с одним входом и одним выходом;

- подпрограмма должна допускать только три основные структуры – последовательное выполнение, ветвление ( if , case ) и повторение ( for , while , repeat ).

- недопустим оператор передачи управления в любую точку программы ( goto );

- документация должна создаваться одновременно с программированием в виде комментариев к программе.

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

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

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

Модульное программирование предназначено для разработки больших программ.

Разработкой больших программ занимается коллектив программистов. Каждому программисту поручается разработка некоторой самостоятельной части программы. И он в таком случае отвечает за конструирование всех необходимых процедур и данных для этих процедур. Сокрытие данных (запрет доступа к данным из-за пределов модуля) предотвращает их случайное изменение и соответственно нарушение работы программы. Для взаимодействия отдельных частей (модулей) программы коллективу программистов необходимо продумать только интерфейс (взаимодействие) сконструированных модулей в основной программе.

Напомним понятие и структуру модуля в терминах языка Pascal .

Модуль ( unit ) – программная единица, текст которой компилируется независимо (автономно).

Модуль содержит 4 раздела: заголовок, интерфейсная часть (раздел объявлений), раздел реализации и раздел инициализации.

INTERFACE <интерфейсная часть>

4.3.1. Сравнение нисходящего и восходящего программирования

4.3.1. Сравнение нисходящего и восходящего программирования

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

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

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

Аналогичный выбор обнаруживается во многих других ситуациях. Предположим, что разрабатывается программа цифрового музыкального синтезатора (MIDI sequencer). Организовывать такой код можно вокруг его верхнего уровня (упорядочение дорожек) или вокруг нижнего уровня (переключение фрагментов или выборок и управление генераторами колебаний).

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

В качестве более крупного примера рассмотрим разработку Web-браузера. Верхним уровнем конструкции Web-браузера является спецификация ожидаемого поведения данной программы: какие типы URL-адресов ( http: или ftp: , или file: ) она интерпретирует, какие виды изображений она способна визуализировать, допускает ли она использование языков Java или JavaScript и с какими ограничениями и т.д. Уровень реализации, который соответствует данному верхнему уровню, является основным событийным циклом программы. В каждой итерации цикл ожидает, накапливает и координирует действия пользователя (такие как нажатие Web-ссылки или ввод символа в поле).

Однако Web-браузер для решения поставленных перед ним задач вынужден вызывать большой набор основных примитивов. Одна группа примитивов занята установкой сетевых соединений, отправкой данных по ним, а также получением ответов. В другую группу входят операции GUI-инструментария, который используется браузером. Третья группа может быть занята механическим преобразованием полученных HTML-документов из текстовой формы в объектное дерево документа.

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

С момента возникновения полемики по поводу структурного программирования в 60-х годах, начинающих программистов, как правило, учат, что верный подход заключается в проектировании сверху вниз. То есть в поэтапном усовершенствовании, где на абстрактном уровне определяется, для чего предназначена данная программа, и постепенном заполнении пустот реализации до тех пор, пока не будет образован точно работающий код. Нисходящий подход становится хорошей практикой, когда выполняются три предусловия: (а) можно с большой точностью определить, для решения каких задач предназначена данная программа, (b) значительные изменения спецификации в ходе реализации маловероятны и (с) большая свобода выбора на низком уровне, каким образом программа будет выполнять свои функции.

Данные условия наиболее часто выполняются в программах, расположенных сравнительно близко к пользователю и высоко в стеке программ, т.е. в прикладном программировании. Однако даже в этом случае указанные предусловия часто не выполняются. Невозможно заранее определить "правильный" режим работы текстового редактора или графической программы до тех пор, пока пользовательский интерфейс не пройдет тестирование среди конечных пользователей. Исключительно нисходящее программирование часто характеризуется чрезмерным вложением трудозатрат в код, который придется удалить за ненадобностью и перестроить, поскольку интерфейс не проходит проверку в реальных условиях.

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

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

Независимо от того является программист системным или нет, восходящий подход также может выглядеть более привлекательно при программировании исследовательским способом, когда пытаются получить контроль над феноменами аппаратного или программного обеспечения или реальными феноменами, которые еще не полностью понятны. Восходящее программирование предоставляет время и пространство для уточнения нечеткой спецификации. Кроме того, восходящее программирование "апеллирует к естественной человеческой лени" программистов: когда требуется удалить часть кода и перестроить его, при работе в нисходящем направлении приходится удалять более крупные фрагменты, чем при работе в восходящем направлении.

Таким образом, создание реального кода склоняется к использованию как нисходящего, так и восходящего подходов. Нередко нисходящий и восходящий код является частью одного и того же проекта. В таком случае возникает необходимость использования связующих уровней.

Данный текст является ознакомительным фрагментом.

Методы разработки структуры программ (восходящая и нисходящая разработка, конструктивный и архитектурный подходы).

В процессе разработки программы ее структура может по-разному формироваться и использоваться для определения порядка программирования и отладки модулей, указанных в этой структуре. Поэтому можно говорить о разных методах разработки структуры программы.

1. Метод восходящей разработки

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

Достоинство метода заключается в том, что каждый модуль при программировании выражается через уже запрограммированные непосредственно подчиненные модули, а при тестировании использует уже отлаженные модули.

Недостатки метода восходящей разработки заключаются в следующем:

• на нижних уровнях модульной структуры спецификации могут быть еще определены не полностью, что может привести к полной переработке этих модулей после уточнения

спецификаций на верхнем уровне;

• для восходящего тестирования всех модулей, кроме головного, который является модулем самого верхнего уровня, приходится создавать вызывающие программы, что приводит к созданию большого количества отладочного материала, но не гарантирует, что результаты тестирования верны;

• головной модуль проектируется и реализуется в последнюю очередь, что не дает продемонстрировать его заказчику для уточнения спецификаций.)

2. Метод нисходящей разработки

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

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

Рассмотренные выше методы (нисходящей и восходящей разработок), являющиеся классическими, требуют, чтобы модульная древовидная структура была готова до начала программирования модулей. Как правило, точно и содержательно разработать структуру программы до начала программирования невозможно. При конструктивном и архитектурном подходах к разработке модульная структура формируется в процессе реализации модулей.)

3. Конструктивный подход

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

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

4. Архитектурный подход

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

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

Дата добавления: 2018-06-01 ; просмотров: 710 ;

Модульное программирование

Цели урока:

  • Образовательная: познакомить учащихся с технологией нисходящего и восходящего программирования, ее реализацией с помощью модулей.
  • Развивающая: развивать алгоритмическое мышление, умение анализировать результаты, развивать творческие способности, память, внимательность, развивать информационную культуру.
  • Воспитательная: воспитание аккуратности и точности при составлении алгоритмов; воспитание чувства ответственности, уважения к личности, навыков самообразования.

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

1.1. Устный опрос:

  • Какой вид имеет структура описания процедуры и функции в Turbo Pascal?
  • В чем состоит отличие описания процедуры и функции?
  • Что такое область действия идентификаторов?
  • Какие параметры называются формальными и какие фактическими?
  • Какие способы передачи параметров реализованы в Turbo Pascal?
  • Почему при работе с графикой в Turbo Pascal необходимо предложение uses Graph?
  • Какие процедуры и функции модуля Graph вам известны?

2. Изложение нового материала.

2.1. Содержание и последовательность излагаемых учебных вопросов.

2.1.1. Технология модульного программирования.

Языки высокого уровня появились в 60-е годы. Ресурсы ЭВМ (объем ОЗУ 8 Кбайт, быстродействие 20 тыс. операций в сек.) были недостаточны, поэтому программисты вынуждены были писать программы весьма “хитроумно” с использованием оператора безусловного перехода. Программа получалась запутанной, имела структуру “блюдо спагетти”. Так как область применения ЭВМ расширялась, программное обеспечение усложнялось. Программисты, решающие сложные задачи, столкнулись с проблемой разрастания количества и размера программ до такой степени, что дальнейший процесс разработки становился практически неуправляемым, и никто из разработчиков не мог с уверенностью сказать, что созданный программный продукт всегда выполняет то, что требуется, и что он не выполняет ничего такого, что не требуется. Поэтому возникла необходимость в новой методологии разработки программных проектов. В 1968–1969 гг. состоялись конференции по программированию. На второй из них Эдсгер Дийкстра предложил принципиально новый способ создания прграмм – структурное программирование. Главное – разбиение программного комплекса (при его создании) на программные модули, которые соединяются иерархически.

Цели модульного программирования:

1. Улучшать читабельность программ.
2. Повышать эффективность и надежность программ (легко находить и корректировать ошибки).
3. Уменьшать время и стоимость программной разработки (уменьшается время отладки).

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

  1. Модуль – это независимый блок, код которого физически и логически отделен от кода других модулей.
  2. Размер модуля не больше 100 операторов.
  3. Имеет одну входную и одну выходную точку.
  4. Модули связаны иерархически.
  5. Разбиение должно обеспечивать надежное скрытие информации в модуле.
    Парнас: “Для написания одного модуля должно быть достаточно минимальных знаний о тексте другого”.
  6. Каждый модуль должен начинаться с комментария (его назначение – входные и выходные переменные).
  7. Не использовать метки и оператор GOTO.
  8. Использовать только стандартные управляющие конструкции (условие, выбор, цикл, блок).

2.1.2. Нисходящее и восходящее программирование.

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

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

При восходящем проектировании разработка идет снизу вверх. На первом этапе разрабатываются модули самого низкого уровня. На следующем этапе к ним подключаются модули более высокого уровня и проверяется их работоспособность. На завершающем этапе проектирования разрабатывается головной модуль, отвечающий за логику работы всего программного комплекса. Методы нисходящего и восходящего программирования имеют свои преимущества и недостатки.

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

  • Необходимость заглушек.
  • До самого последнего этапа проектирования неясен размер программного комплекса и его эксплутационные характеристики, за которые, как правило, отвечают модули самого низкого уровня.

Преимущество нисходящего проектирования – на самом начальном этапе проектирования отлаживается головной модуль (логика программы).

Преимущество восходящего программирования – не нужно писать заглушки.

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

На практике применяются оба метода. Метод нисходящего проектирования чаще всего применяется при разработке нового программного комплекса, а метод восходящего проектирования – при модификации уже существующего комплекса.

2.1.3. Оформление программы в виде модуля.

При подключении стандартных модулей достаточно корректно записать их идентификаторы в предложении uses. При разработке собственных модулей необходимо помнить некоторые особенности:

  • Не допускается одновременное использование модулей с одинаковыми именами.
  • Идентификатор модуля, указанный в заголовке (unit), должен совпадать с именами файлов, содержащих исходный (.pas) (.tpu, . tpp, .tpw) код.
  • Если идентификатор модуля длиннее восьми символов, то он должен совпадать с именами файлов по первым восьми символам.

Общая структура модуля

unit идентификатор модуля;

<Интерфейсный раздел>

в этом разделе описывается взаимодействие данного модуля с другими пользовательскими и стандартными модулями, а также с главной программой. Другими словами – взаимодействие модуля с “внешним миром”.

Список импорта интерфейсного раздела

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

Список экспорта интерфейсного раздела

const
type
var
procedure
function

Раздел реализации

в этом разделе указывается реализационная (личная) часть описаний данного модуля, которая недоступна для других модулей и программ. Другими словами – “внутренняя кухня модуля”.

Список импорта раздела реализации

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

Подразделы внутренних для модуля описаний

В этих подразделах описываются метки, константы, типы, переменные, процедуры и функции, которые описывают алгоритмические действия, выполняемые данным модулем, и которые являются “личной собственностью” только данного модуля. Эти описания недоступны ни одному другому модулю. Заголовки процедур и функций в этом подразделе допускается указывать без списка формальных параметров. Если заголовки указаны все же с параметрами, то список формальных параметров должен быть идентичен такому же списку для соответствующей процедуры (функции) в разделе interface.

label
const
type
var
procedure
function

Раздел инициализации

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

Пример модуля a1

unit a1;
interface
uses graph;
procedure init;
procedure pr1;
implementation
procedure init;

procedure pr1;
begin

end;
begin
init;
pr1;
readln;
end.

Головной модуль

program a;
uses a1, a2, a3, a4;
begin
pr1;
pr2;
pr3;
pr4;
readln;
end.

3. Проверка качества усвоения нового материала.

3.1. Устный опрос.

  • Назовите принципы модульного программирования.
  • Когда применяется технология нисходящего программирования? А восходящего?
  • В чем различие между технологией восходящего и технологией нисходящего программирования?
  • Какие существуют особенности при разработке собственных модулей?
  • Из каких разделов состоит модуль?
  • Что описывается в разделе interface?
  • Что описывается в разделе implementation?
  • Что описывается в разделе инициализации?

3.2. Самостоятельная работа учащихся на уроке.

Учащиеся разбиты на две группы. Работой каждой группы руководит “начальник”. Получив задание, учащиеся начинают коллективную работу. Каждый ученик разрабатывает свою программу, оформляет ее в виде модуля UNIT и отдает “начальнику”, который пишет головную программу, объединяя модули своих “подчиненных”.

Литература:

  1. Марченко А. И., Марченко Л. М. “Программирование в среде Turbo Pascal 7.0”, М.: “Бином Универсал”, 1998.
  2. Информатика. № 2. /Приложение к газете “Первое сентября”, 1996.
Читать еще:  Использование инструментов программирования является примером
IT Новости из мира ПК
Добавить комментарий