Спецификация программного модуля содержит синтаксическую спецификацию его входов, позволяющую построить на используемом языке программирование правильное обращение к нему. Функциональная спецификация модуля строится также, как и функциональная спецификация ПС. В процессе разработки программы модульная структура может формироваться по-разному, обычно используется 2 метода: метод восходящей и нисходящей разработки.
Метод восходящей разработки
Сначала строится модульная структура программы в виде дерева, затем поочередно программируются модули программы, начиная с самого нижнего уровня (листья дерева, самых маленьких модулей). Модули программируются в таком порядке, чтобы для каждого нового модуля были созданы уже все модули, к которым он обращается. Затем происходит поочередное тестирование и отладка в таком же порядке. Такой расклад не рекомендуется. Это связано со следующим:
Для программирования какого-либо модуля совсем не требуется текста описывающий модуль, для этого достаточно чтобы каждый модуль был лишь специфицирован.
Каждая программа подчиняется некоторым внутренним для нее соображениям, например, структура данных, набор исходных переменных и т.д. на который накладывай свой отпечаток предметная область в которой функционирует приложение. Поэтому модули часто требуют перепрограммирования, когда происходит уточнение этой глобальной информации. Таким образом, наблюдается большой объем отладочного программирования и при этом не гарантируется, что тестирование модуля будет происходить в тех же условиях, что и в рабочей программе.
В процессе разработки программы модульная структура может формироваться по-разному, обычно используется 2 метода: метод восходящей и нисходящей разработки.
Метод снисходящей разработки
Заключается в следующем: сначала также строится модульная структура в виде дерева, но программирование происходит в другом направлении, начиная с самого верхнего (головного) уровня и только затем переходит к программированию других модулей. Когда все модули запрограммированы происходит программирование и отладка. В этом случае вся глобальная информация формируется своевременно, т.е. просчеты в программировании модулей сводятся к минимуму, облегчается тестирование, поскольку головной модуль уже создан и можно лишь его запустить. Также все модули тестируются в естественном состоянии информационной среды. Если головной модуль обращается к еще незапрограммированному модулю, то он заменяется на имитатор (т.е. простой программный фрагмент, сигнализирующий о том, что произошел факт обращения к модулю с необходимыми входными параметрами). Таким образом объем отладочного программирования сводится к созданию простых имитаторов. Также имитаторы удобно использовать для того чтобы они возвращали строго определенные значения.
Представляет собой модификацию снисходящей разработки. Программирование начинается с головного модуля исходя из спецификации программы в целом, при этом спецификация программы головного модуля является спецификацией программы, так как именно он ответственен за выполнение функций. В процессе программирования головного модуля, в случае если программа достаточно большая, выделяются подзадачи (т.е. внутренние функции). В терминах в которых программируется головной модуль, таким образом, что для каждой выделяемой подзадачи создается спецификация реализующего ее фрагменты программы, который в дальнейшем может быть представлен под деревом модулей. В головном модуле для обращения к выделенной функцией строят соответствующие обращения, в соответствии с созданной спецификацией. Таким образом на первом шаге разработке создается верхняя (начальная) часть дерева. В результате создается дооформление дерева программы.
Конструктивный подход имеет ряд положительных особенностей в отношении архитектурного, а именно поскольку в конструктивном подходе головной модуль уже создан, следовательно, программа уже готова к работе, поэтому появляется возможность выпуска на рынок не полностью доделанной программы, которая решает только основные функции. В дальнейшем функционал приложения может быть доведен до требуемого, однако приложение уже может использоваться в конкретных целях, например, для определения особенностей функционирования программы.
Модификация восходящей разработки. Модульная структура также создается в процессе работы. Цель разработки – повышение уровня языка программирования, а вовсе не разработка программы. Это означает что для заданной предметной области выделяются типичные задачи, которые специфицируются, а затем программируются как отдельные программные модули. Т.е. процесс выделения функции связан с накоплением и обобщением опыта решения задач в заданной предметной области. Сначала выделяются и реализуются более простые функции, а затем постепенно появляются модули, которые используют созданные ранее модули. Такой набор модулей создаётся в расчете на то, что при разработке программы заданной предметной области в рамках конструктивного подхода могут быть приемлемы некоторые из этих модулей. Таким образом применение готовых модулей может сократить затраты на разработку конкретных программ. Также архитектурный подход является методом борьбы с повторением. Программные модули в архитектурном подходе всегда параметризируются, т.е. выделяются конкретные программы, для того чтобы конкретизировать модули путем настройки их программы (создаются универсальные модули). Пример, кнопочка в форме.
Приступая к разработке ПС, следует иметь ввиду, что она является большой системой и необходимо принять меры для ее упрощения. Для этого программы часто разрабатывают по частям, такие части называются программными модулями, а стиль программирования – модульным программированием. Программный модуль – это любой фрагмент описания процесса, оформляемый как самостоятельный программный продукт. Это означает, что каждый модуль создается и отлаживается отдельно от других и физически разделен с другими модулями. Также каждый программный модуль может включатся в состав разных программных продуктов, при условии использовании определенных правил, декларированных в документации к этому модулю. Таким образом, программный модуль не только борется со сложностью, но также борется с дублированием. Выделение отдельных модулей, ведущих к упрощению системы является серьезной творческой задачей.
Модульное программирование является воплощением в процессе разработки программ обоих общих методов борьбы со сложностью: и обеспечение независимости компонент системы, и использование иерархических структур. Для воплощения первого метода формулируются определенные требования, которым должен удовлетворять программный модуль, т.е. выявляются основные характеристики "хорошего" программного модуля. Для воплощения второго метода используют древовидные модульные структуры программ (включая деревья со сросшимися ветвями).
Для оценки приемлемости модуля используют некоторые характеристики, так для оценки ее приемлемости используется следующее:
Размер модуля определяется количеством использованных в нем операторов. Модуль не может быть слишком маленьким или слишком большим. Обычно рекомендуются модули до нескольких сотен операторов.
Прочность модуля – мера его внутренних связей. Прочность модуля показывает сколько связей он может спрятать от внешней программы, т.е. модули могут иметь как можно меньше внешних связей. Прочность может быть следующей:
Прочность по совпадению – самый низкий уровень прочности. Между элементами модуля нет осмысленных связей. Может использоваться при обнаружении в разных модулях повторения разных операторов, которые оформляются в отдельный модуль.
Не рекомендуется к использованию.
Функционально-прочный модуль – модуль, реализующий одну определенную функцию. При реализации такой функции модуль может использовать другие модули. НАИБОЛЕЕ рекомендуемый для использования.
Информационно-прочный модуль – модуль, реализующих несколько операций над одной и той же структурой данных, которой считаются неизвестной вне этого модуля. Для каждой операции имеется свой вход с формой обращения к нему.
Сцепление модуля – мера зависимости от других модулей, характеризуется способом передачи данных. Чем выше независимость модуля от других, тем слабее сцепление. Виды сцепления бывают следующими:
Сцепление по содержимому (худший вариант) – это сцепление двух модулей, когда один модуль имеет прямые ссылки на содержимое другого модуля.
Сцепление по общей области (также не рекомендуется) – разные модули используют одну и ту же область памяти (например, глобальные переменные).
Параметрическое сцепление (рекомендуемое) – данные передаются модулю при обращении к нему через специальные параметры. Пример такого обращения – это обращения к аргументам функции и процедур. В этом случае модуль всегда должен иметь некоторый внешний интерфейс независимый от внутреннего содержания.
Рутинность модуля – независимость модуля от предыстории (не зависит от предыдущих вызовов). В рутинном модуле результат однозначно определяется входными данными, которые формируются в момент вызова модуля. Если же модуль зависит от истории, то он называется зависящим от предыстории. Такой модуль всегда хранит результаты предыдущих обращений. Такие модули применять не рекомендуется, за исключением тех случаев, когда без них нельзя. Применение таких модулей может приводить к непредсказуемым результатам.
Применение модулей, зависящих от предыстории всегда требует четкого описания, в противном случае применение модуля не предоставляется возможным.
При разработке программного модуля целесообразно придерживаться следующего порядка:
Изучение и проверка спецификации модуля, выбор языка программирования
Выбор алгоритма и структуры данных
Программирование модуля
Шлифовка (оптимизация) текста модуля
Проверка модуля (включая тестирование)
Компиляция модуля
Первый шаг представляет собой смежный контроль структуры программы снизу, т.е. разработчик должен убедится, что описание ему понятно и достаточно для разработки модуля. В ряде случаев, если система это допускает, может быть выбран другой язык (например, assembler), такие программы работают очень быстро.
Второй шаг подразумевает в себе анализ уже существующих методов решения подобных задач. Здесь выбирается наиболее подходящий алгоритм для решения задачи.
Третий этап — это построение текста модуля на выбранном языке программирования. Обилие всевозможных деталей, которые должны быть учтены при реализации задачи могут привести к созданиям весьма запутанного текста, содержащего массу ошибок. Поэтому для построения текста модуля необходимо пользоваться технологически обособленной и проверенной дисциплиной программирования. Наиболее распространённой является пошаговая детализация.
Четвертый этап заключает в себя приведение текста модуля к совершенному виду в соответствии со спецификацией качества. Необходимо редактировать не только команды, но и комментарии, с целью обеспечения требуемых примитивов качества. Также приводится редактирование текста программы, для обеспечения стилистических требований (например, отступов).
Пятый шаг представляет собой ручную проверку внутренней логики модулей, а также выполнение операций тестирования на конкретных заданиях (что ввели – что выдало).
На последнем шаге предусматривает завершение проверки модуля и подготовка программного продукта.
При программировании модуля следует иметь ввиду что программа должна быть понятной не только компьютеру, но и человеку (разработчику модуля, проверяющий модуль, готовящим тесты для отладки модуля и т.д.). Поэтому необходимо принимать меры для выбора подходящих языковых средств. Так вначале было предложено строить программу как композицию из нескольких типов управляющих конструкций, который позволяет сильно повысить понимаемость логики работы. Программирование только с помощью таких конструкций называется структурным. Итак, основными конструкциями структурного программирования являются следующие:
1. Следование – линейная структура, определяющая последовательность действий
2. Разветвление – предполагает наличие условия (if – else), в зависимости от которого выполняется одна из двух ветвей
3. Повторение – обычный цикл
В качестве обобщенного оператора может быть оператор либо фрагмент программы. Может быть композицией основных управляющих конструкций. Каждая конструкция имеет один вход и один выход, так и обобщенный оператор имеет один вход и один выход. Конструкции являются математическими объектами. И доказано, что для каждой неструктурированной программы можно построить эквивалентную структурированную. А для структурированных программ можно математически доказать некоторые свойства, что позволит обнаружить в некоторых программах ошибки.
Особенностью структурного программирования это отсутствия оператора go to. В ряде случаев оператор go to необоснованно примененный запутывает программу и нарушает структурированность. Тем не менее применение оператора go to бывает обоснованным, поэтому рекомендуется избегать оператора go to везде, где это возможно. Одним из полезных случаев использование go to – это досрочный выход из-под программы или цикла, или какой-то структурной единицы. Тем самым структурированность нарушается лишь локально, не нарушая общей структуры программы.
Также большие трудности вызывает структурная реализация в реакции на исключения, так как в большинстве случаев необходимо не только отреагировать на ошибку, но и предпринять соответствующие действия.
Псевдокод — компактный (зачастую неформальный) язык описания алгоритмов, использующий ключевые слова императивных языков программирования, но опускающий несущественные подробности и специфический синтаксис. Псевдокод обычно опускает детали, несущественные для понимания алгоритма человеком. Такими несущественными деталями могут быть описания переменных, системно-зависимый код и подпрограммы. Главная цель использования псевдокода — обеспечить понимание алгоритма человеком, сделать описание более воспринимаемым, чем исходный код на языке программирования. Псевдокод широко используется в учебниках и научно-технических публикациях, а также на начальных стадиях разработки компьютерных программ.
К 17 и 18 вопросу:
Отладка ПС – деятельность, направленная на обнаружение и исправление ошибок с использованием процессов выполнения его программ.
Тестирование ПС – процесс выполнения программ на некотором наборе данных, для которого заранее известен результат либо правило поведения программы. Набор соответствующих данных называется тестом или тестовым набором.
Отладочные модули, входящие в окружение отлаживаемого модуля, зависят от порядка, в каком отлаживаются модули этой программы, от того, какой модуль отлаживается и, возможно, от того, какой тест будет пропускаться.