10. Модульное программирование
Сейчас мы переходим к новой теме – модульному программированию. Модульное программирование предполагает особый способ разработки программы, которая при этом строится из нескольких относительно независимых друг от друга частей – модулей. Модули могут писаться как на одном языке программирования, например, на Ассемблере, так и на разных языках, в этом случае говорят, что используется многоязыковая система программирования. Что такое система программирования мы строго определим несколько позже, а пока изучим общее понятие модульного программирования и программного модуля.
Мы уже знаем одно из полезных свойств такой программы, отдельные части (модули) которой написаны на разных языках программирования – это позволяет нам из программ на языках высокого уровня вызывать процедуры на Ассемблере. Познакомимся теперь со свойствами модульной программы, написанной на одном языке программирования (в нашем случае на Ассемблере).
Перечислим сначала те преимущества, которые предоставляет модульное программирование. Во-первых, как мы уже отмечали, это возможность писать модули на разных языках программирования. Во-вторых, модуль является естественной единицей локализации имён: как мы говорили, внутри модуля на Ассемблере все имена должны быть различны (уникальны), 1 что не очень удобно, особенно когда модуль большой по объёму или совместно пишется разными программистами. Как и в блоке программы на языке Паскаль, имена локализованы в модуле на Ассемблере и не видны из другого модуля, если только это не указано явно с помощью специальных директив.
Следующим преимуществом модульного программирования является локализация места ошибки: обычно исправление ошибки внутри одного модуля не влечёт за собой исправление других модулей (разумеется, это свойство будет выполняться только при хорошем разбиении программы на модули, с малым числом связей между модулями, о чём мы будем говорить далее). Это преимущество особенно сильно сказывается во время отладки программы. Например при внесении изменений только в один мз нескольких десятков модулей прграммы, только он и должен быть заново проверен программой Ассемблером и переведён на язык машины. 2 Обычно говорят о малом времени перекомпиляции всей программы при исправлении ошибки в одном модуле, что сильно ускоряет процесс отладки всей программы.
Разумеется, за всё надо платить, у модульного программирования есть и свои слабые стороны. Во-первых, модули не являются совсем независимыми друг от друга: между ними существуют связи, то есть один модуль иногда может использовать переменные и программный код другого модуля. Необходимость связей между модулями естественно вытекает из того факта, что модули совместно решают одну общую задачу, при этом каждый модуль выполняет свою часть задачи. Связи между модулями на Ассемблере должны быть явно заданы при описании этих модулей.
Во-вторых, теперь перед счётом программы необходим особый этап сборки программы из составляющих её модулей. Этот процесс достаточно сложен, так как кроме собственно сборки программы из модулей, необходимо проконтролировать и установить все связи между модулями. 3 Сборки программы из модулей производится специальной системной программой, которая называется редактором внешних связей между модулями.
В-третьих, так как теперь наш Ассемблер никогда не видит всей исходной программы одновременно, то, следовательно, и не может получить полностью готовую к счёту программу на машинном языке. Более того, в каждый момент времени он видит только один модуль, и не может проконтролировать, правильно ли установлены связи между модулями. Ошибка в связях теперь выявляется на этапе сборки программы из модулей, а иногда только на этапе счёта, если используется так называемое динамическое связывание модулей, обо всём этом мы будем говорить далее. Позднее обнаружение ошибок связи между модулями может существенно замедлить процесс отладки программы.
Несмотря на отмеченные недостатки, преимущества модульного программирования так велики, что сейчас это главный способ разработки программного обеспечения. Теперь мы начнём знакомиться с особенностями написания модульной программы на языке Ассемблера.
Модульное
программирование Модульность в программировании подобна честности в политике: каждый утверждает, что она — одно из его достоинств, но кажется, никто не знает, что она собой представляет . Йодан Э.
Основные понятия
Модульное программирование – это такой способ программирования, при котором вся программа разбивается на группу компонентов, называемых модулями, причем каждый из них имеет свой контролируемый размер, четкое назначение и детально проработанный интерфейс с внешней средой. Альтернатива модульности – монолитная программа
Основные концепции:
В основе модульного программирования лежат три основные концепции: Принцип утаивания информации Парнаса При разработке программ формируется список проектных решений, которые особенно трудно понять или которые , скорее всего, будут меняться. Затем определяются отдельные модули, каждый из которых реализует одно из указанных решений.Большие программы должны использовать модули без каких-либо предварительных знаний об их внутренней структуре. Примерами удачных модулей могут служить программы ППП (пакетов прикладных программ) и стандартные процедуры. Сборочное программирование Цейтина . Модули – это программные «кирпичи», из которых строится программа.
Основные концепции:
Аксиома модульности Коуэна Модуль – независимая программная единица, служащая для выполнения некоторой определенной функции программы и для связи с остальной частью программы. Программная единица должна удовлетворять следующим условиям: • Блочность организации • Синтаксическая обособленность • Семантическая независимость • Общность данных • Полнота определения
Характеристики модуля (Майерс, 1980)
Размер модуля Связность (прочность) модуля Сцепление модуля с другими модулями Рутинность (независимость от предыдущих обращений) модуля
Размер модуля
Модуль не должен превышать 60 строк В результате его можно поместить на одну страницу распечатки или легко просмотреть на экране монитора
Связность модуля
Связность модуля – мера независимости его частей. Чем выше связность, тем больше связей он «упрятывает» в себе Типы связности: Функциональная Модуль с функциональной связностью реализует одну какую-нибудь функцию и не может быть разбит на два модуля с теми же типами связности Последовательная
Связность модуля
Типы связности: Последовательная Модуль с такой связностью может быть разбит на последовательные части, выполняющие независимые функции, но реализующие совместно единственную функцию (например, оценка , а затем обработка данных)
Связность модуля
Типы связности: Информационная Модуль с информационной связностью – это модуль, выполняющий несколько операций или функций над одной и той же структурой данных, которая считается неизвестной вне этого модуля (применяется для реализации, например, абстрактных типов данных таких как стек, очередь и др.)
Связность модуля: Следует избегать
Временной связности — когда объединяются действия, связанные со временем (например, действия, которые должны быть выполнены в один и тот же момент времени) Логической связности — когда в модуль объединяются действия по признаку их некоторого подобия (например, функции для проверки корректности входных данных для всей программы) Случайной связности — когда действия объединяются произвольным образом Процедурной связности — когда действия сгруппированы вместе только потому, что они выполняются в течение одной и той же части процесса
7 Модульное программирование
Модуль – это последовательность логически связанных фрагментов, оформленных как отдельная часть программы.
К модулю предъявляются следующие требования:
- модуль должен реализовывать единственную функцию, т.е. при построении модуля используется концепция: «один модуль – одна функция». Таким образом, модуль – это элемент программы, выполняющий самостоятельную задачу. На его входе он может получать определенный набор исходных данных, обрабатывать их в соответствии с заданным алгоритмом и возвращать результат обработки, т.е. реализуется стандартный принцип IPO (Input – Process – Output) – вход-процесс-выход;
- на модуль нужно ссылаться с помощью его имени. Он должен иметь один вход и один выход, что гарантирует замкнутость модуля и упрощает сопровождение программ;
- модуль должен иметь функциональную завершенность, т.е. выполнять перечень регламентированных операций для реализации каждой отдельной функции в полном составе, достаточных для завершения начатой обработки;
- модуль должен возвращать управление в точку его вызова, в свою очередь, он должен иметь возможность сам вызывать другие модули;
- модуль не должен сохранять историю своих вызовов и использовать ее при своем функционировании;
- модуль должен иметь логическую независимость, т.е. результат работы программного модуля зависит только от исходных данных, но не зависит от работы других модулей;
- модуль должен иметь слабые информационные связи с другими программными модулями – обмен информацией между модулями должен быть по возможности минимизирован;
- модуль должен быть сравнительно невелик, т.е. быть обозримым по размеру и сложности. Опытные программисты рекомендуют его размер не более двух страниц распечатки на принтере.
- большую программу могут писать одновременно несколько программистов, что позволяет раньше закончить задачу;
- можно создавать библиотеки наиболее употребительных модулей;
- упрощается процедура загрузки в оперативную память большой программы, требующей сегментации;
- появляется много естественных контрольных точек для отладки проекта;
- проще проектировать и в дальнейшем модифицировать программы.
- возрастает размер требуемой оперативной памяти;
- увеличивается время компиляции и загрузки;
- увеличивается время выполнения программы;
- довольно сложными становятся межмодульные интерфейсы.