- •Тема 5. Внутреннее проектирование программного изделия
- •Понятие модуля программы
- •К преимуществам разработки пи с использованием модулей можно отнести следующие:
- •Связность модулей программы
- •Сцепление модулей программы
- •Таким образом, на основании изложенных выше соображений можно сформулировать следующие правила формирования структуры и взаимодействия модулей в пи:
- •Оформление структуры программного изделия
- •Особенности архитектуры Windows-программ
- •Программирование модулей
- •Внешние спецификации модуля должны содержать:
- •Стиль программирования
- •Сборка программы
Программирование модулей
Этапы проектирования и программирования самих модулей являются завершающими в цикле проектирования ПИ. На этих этапах выполняются операции внешнего проектирования модулей, а также проектирование и кодирование логики модулей.
В процессе внешнего проектирования модулей разрабатываются внешние взаимосвязи модулей, которые представляют собой внешние спецификации каждого модуля и необходимы другим модулям, осуществляющим обращение к данному. Внешняя спецификация модуля не должна содержать никакой информации о внутреннем устройстве модуля, об особенностях реализованного в нем алгоритма. Кроме того, недопустимо, чтобы спецификация содержала какие-либо ссылки на вызывающие модули или на контексты, в которых этот модуль используется.
Внешние спецификации модуля должны содержать:
имя модуля, с помощью которого можно к нему обратиться;
его функцию, определяющую, что делает, модуль, когда он вызван, а также его назначение (этот элемент спецификации не должен содержать сведения о том, как функция реализуется);
список (число и порядок) входных и выходных параметров (указываются атрибуты, формат, размер, единицы измерения, а также допустимые диапазоны возможных значений, взаимосвязь между входными и выходными данными, а также - выходные данные, возвращаемые в вызывающий модуль в случае ошибочных входных данных);
внешние эффекты - описание всех внешних для программы или системы событий, происходящих при работе модуля, таких, как прием запроса, выдача сообщений об ошибках и т.п.
Для того чтобы можно было считать модуль полностью специфицированным, должно быть определено его поведение при любых входных условиях.
Важно отличать внешние спецификации модуля от другой документации, например от описания его логики, потому что изменение логики может никак не повлиять на вызывающие модули, а изменение внешних спецификаций обычно приводит к изменениям в вызывающих модулях. Внешние спецификации лучше хранить в самой программе в виде комментариев в начале текста программы модуля.
После разработки внешних спецификаций модулей приступают к проектированию модуля и собственно программированию (кодированию) внутренней логики каждого модуля. Этот процесс должен быть тщательно спланирован, и состоять из следующих шагов.
1. Выбор языка программирования. Выбор языка программирования часто предопределен имеющимися у заказчика вычислительными ресурсами, принятыми организационными стандартами или подготовкой программистов.
Выбор языка программирования обычно осуществляется на более ранних стадиях разработки ПИ. Однако если язык не определен, то программист выполняет выбор на этом шаге. Существенное влияние на выбор языка оказывают его возможности обеспечивать надежный процесс получения программ, наличие и специфические особенности компилятора и т.д. Выбранный язык программирования оказывает влияние и на разработку ПИ.
2. Выбор алгоритма и структуры данных. К настоящему времени разработано значительное количество алгоритмов и соответствующих структур данных, которые позволяют удовлетворить потребности проектировщиков. Поэтому следует использовать опыт предыдущих разработок, отчеты, опубликованные материалы, выбрать из имеющихся эквивалентных алгоритмов и структур данных необходимые.
Если же поиск не приводит к желаемому результату, то алгоритм и структуры данных необходимо разработать.
3. Формирование структуры модуля в соответствии с полученным алгоритмом и требованиями принятого языка программирования. Так, например, в Паскале все программные элементы модуля можно разбить на две части:
- программные элементы, предназначенные для использования другими программами или модулями, такие элементы называют видимыми вне модуля;
- программные элементы, необходимые только для работы самого модуля, их называют невидимыми или скрытыми.
В соответствии с этим модуль, кроме заголовка, содержит две основные части, называемые интерфейсом и реализацией: unit (имя модуля); {заголовок модуля} interface { описание видимых программных элементов модуля } { описание скрытых программных элементов модуля } begin { операторы инициализации элементов модуля } end.
Использование в модулях процедур и функций имеет свои особенности.
Заголовок подпрограммы содержит все сведения, необходимые для ее вызова: имя, перечень и тип параметров, тип результата для функций, эта информация должна быть доступна для других программ и модулей. С другой стороны, текст подпрограммы, реализующий ее алгоритм, другими программами и модулями не может быть использован. Поэтому заголовок процедур и функций помещают в интерфейсную часть модуля, а текст - в часть реализации.
Интерфейсная часть модуля содержит только видимые (доступные для других программ и модулей) заголовки процедур и функций (без служебного слова forward). Полный текст процедуры или функции помещают в часть реализации, причем заголовок может не содержать список формальных параметров. В том случае, если имена переменных в интерфейсной части модуля и в программе, использующей этот модуль, совпадают, обращение будет происходить к переменной, описанной в программе. Для обращения к переменной, описанной в модуле, необходимо применить составное имя, состоящее из имени модуля и имени переменной, разделенных точкой, например unit_M.var_K.
Использование составных имен применяется не только к именам переменных, а ко всем именам, описанным в интерфейсной части модуля.
Если в модуле имеется раздел инициализации, то операторы из этого раздела будут выполнены перед началом выполнения программы, в которой используется этот модуль.
Рекурсивное использование модулей запрещено.
4. Детализация текста программы. В результате нескольких итераций осуществляется последовательная детализация логики модуля, начиная с достаточно высокого уровня абстракции и заканчивая готовым текстом программы. В зависимости от выбранного подхода к декомпозиции задачи и ее ПО на этом шаге используються и соответствующие методы программирования.
5. Окончательное оформление текста программы. Текст модуля проверяется еще раз. При этом вставляются дополнительные комментарии, поясняющие текст программы.
6. Проверка правильности программы. Вручную проверяется правильность модуля - правильность его внутренней логики. Такая проверка осуществляется людьми до выполнения программы вычислительной машиной. Проверка правильности основывается на различных способах чтения текста программы. Проверка может осуществляться как в форме статического чтения программы, так и в форме динамического чтения. Эти формы дополняют друг друга и должны использоваться совместно.
7. Компиляция модуля. Этот шаг отмечает переход проектирования к тестированию модуля. Работа над созданием модуля завершена. Компилятор, строя машинную программу, проводит контроль синтаксиса и частично семантики исходной программы.
При проектировании логики модуля необходимо предусмотреть ряд контрольных мероприятий, обеспечивающих функционирование модуля, т.е. выполнить защитное программирование.
Защитное программирование основано на важной предпосылке [12]: "...худшее, что может сделать модуль, - это принять неправильные входные данные и затем вернуть неверный, но правдоподобный результат".
Поэтому проектировщик обязан до начала работы модуля предусмотреть контроль входных данных на соответствие их свойств атрибутам и диапазонам изменения, на полноту и осмысленность. Защитное программирование требует разумного подхода к его проведению, тщательного анализа необходимости и объема выполняемых проверок.
Таким образом, модуль - это особым образом оформленная библиотека подпрограмм, которая представляет собой отдельно хранимую и независимо компилируемую программную единицу. Однако в отличие от программы модуль не может быть запущен на выполнение самостоятельно, он может только участвовать в построении программ и других модулей.
Использование модулей позволяют создавать личные библиотеки процедур и функций и строить программы практически любого размера.
