Модульное программирование. Модульное программирование — ПИЭ.Wiki

Материал из ПИЭ.Wiki

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

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

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

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

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

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

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

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

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

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

Концепция модульного программирования

Концепцию модульного программирования можно сформулировать в виде нескольких понятий и положений:

  • Функциональная декомпозиция задачи - разбиение большой задачи на ряд более мелких, функционально самостоятельных подзадач - модулей. Модули связаны между собой только по входным и выходным данным.
  • Модуль - основа концепции модульного программирования. Каждый модуль в функциональной декомпозиции представляет собой "черный ящик " с одним входом и одним выходом. Модульный подход позволяет безболезненно производить модернизацию программы в процессе ее эксплуатации и облегчает ее сопровождение. Дополнительно модульный подход позволяет разрабатывать части программ одного проекта на разных языках программирования, после чего с помощью компоновочных средств объединять их в единый загрузочный модуль.
  • Реализуемые решения должны быть простыми и ясными. Если назначение модуля непонятно, то это говорит о том, что декомпозиция начальной или промежуточной задачи была проведена недостаточно качественно. В этом случае необходимо еще раз проанализировать задачу и, возможно, провести дополнительное разбиение на подзадачи. При наличии сложных мест в проекте их нужно подробнее документировать с помощью продуманной системы комментариев. Этот процесс нужно продолжать до тех пор, пока действительно не удастся добиться ясного понимания назначения всех модулей задачи и их оптимального сочетания.
  • Назначение всех переменных модуля должно быть описано с помощью комментариев по мере их определения.

Литература

  1. М.М. Бежанова, Л.А. Москвина. Практическое программирование. Приемы создания программ на языке Паскаль. М.: Научный Мир, 2000, 270 с.
  2. Истомин Е.П., Новиков В.В., Новикова М.В. Высокоуровневые методы информатики и программирования: Учебник. - СПб. ООО "Адреевский издательский дом", 2006 г. - 228 с.

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

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

Модуль характеризуют:

  1. один вход и один выход - на входе программный модуль получает определенный набор исходных данных, выполняет содержательную обработку и возвращает один набор результатных данных, т.е. реализуется стандартный принцип IPO (Input - Process - Output) - вход-процесс-выход;
  2. функциональная завершенность - модуль выполняет перечень регламентированных операций для реализации каждой отдельной функции в полном составе, достаточных для завершения начатой обработки;
  3. логическая независимость - результат работы программного модуля зависит только от исходных данных, но не зависит от работы других модулей;
  4. слабые информационные связи с другими программными модулями - обмен информацией между модулями должен быть по возможности минимизирован;
  5. обозримый по размеру и сложности программный элемент.

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

Каждый модуль состоит из спецификации и тела. Спецификации определяют правила использования модуля, а тело - способ реализации процесса обработки.

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

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

1.3.2. Основные характеристики программного модуля.

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

  • хороший модуль снаружи проще, чем внутри;
  • хороший модуль проще использовать, чем построить.

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

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

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

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

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

В модульных языках программирования как минимум имеются средства для задания функционально прочных модулей (например, модуль типа FUNCTION в языке ФОРТРАН). Средства же для задания информационно прочных модулей в ранних языках программирования отсутствовали - они появились только в более поздних языках. Так в языке программирования Ада средством задания информационно прочного модуля является пакет.

Сцепление модуля - это мера его зависимости по данным от других модулей. Характеризуется способом передачи данных. Чем слабее сцепление модуля с другими модулями, тем сильнее его независимость от других модулей. Для оценки степени сцепления Майерс предлагает упорядоченный набор из шести видов сцепления модулей. Худшим видом сцепления модулей является сцепление по содержимому . Таким является сцепление двух модулей, когда один из них имеет прямые ссылки на содержимое другого модуля (например, на константу, содержащуюся в другом модуле). Такое сцепление модулей недопустимо. Не рекомендуется использовать также сцепление по общей области - это такое сцепление модулей, когда несколько модулей используют одну и ту же область памяти. Такой вид сцепления модулей реализуется, например, при программировании на языке ФОРТРАН с использованием блоков COMMON. Единственным видом сцепления модулей, который рекомендуется для использования современной технологией программирования, является параметрическое сцепление (сцепление по данным по Майерсу) - это случай, когда данные передаются модулю либо при обращении к нему как значения его параметров, либо как результат его обращения к другому модулю для вычисления некоторой функции. Такой вид сцепления модулей реализуется на языках программирования при использовании обращений к процедурам (функциям).

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

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

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

1.3.3. Модульная структура программных продуктов

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

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

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

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

Состав и вид программных модулей, их назначение и характер использования в программе в значительной степени определяются инструментальными средствами. Например, применительно к средствам СУБД отдельными модулями могут быть:

  1. экранные формы ввода и/или редактирования информации базы данных;
  2. отчеты генератора отчетов;
  3. макросы;
  4. стандартные процедуры обработки информации;
  5. меню, обеспечивающее выбор функции обработки и др.

1.3.4. Методы разработки структуры программы.

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

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

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

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

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

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

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


Рис. 1.3.1. Первый шаг формирования модульной структуры программы при конструктивном подходе.

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

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


Рис. 1.3.2. Второй шаг формирования модульной структуры программы при конструктивном подходе.

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

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


Рис. 1.3.3. Классификация методов разработки структуры программ.

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

1.3.5. Контроль структуры программы.

Для контроля структуры программы можно использовать три метода:

  • статический контроль,
  • смежный контроль,
  • сквозной контроль.

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

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

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

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

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

В концепцию модульного программирования обычно включают следующие положения:

1) каждый модуль реализует узкоспециализированную независимую функцию;

2) каждый модуль имеет единственную точку входа/выхода;

3) чем меньше размер модуля, тем лучше;

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

5) вся программа строится из модулей.

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

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

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

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

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

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

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

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

Интерфейс подпрограммы, т. е., информацию, необходимую для обращения к ней;

Совокупность описаний, определений ("локальные" объекты);

Последовательность операторов, решающая задачу подпрограммы.

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

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

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

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

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

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

3) если в некотором блоке описан объект, имя которого совпадает с именем объекта, описанного во внешнем блоке, последний становится недоступным в данном блоке. Иными

словами, имя, описанное в блоке, как бы "экранирует" одноименные объекты из внешних блоков.

Совокупность объектов, описанных в самом внешнем (основном) блоке, называется глобальным контекстом программы.

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

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

Наиболее выгодно оформлять в виде подпрограммы некий набор действий, который в процессе выполнения программы повторяется несколько раз. Однако современный подход к программированию поощряет оформление в виде подпрограммы любого достаточно самостоятельного и законченного фрагмента программы. Размеры такого модуля определяются и возможностями человеческого восприятия. Считается оптимальным, если модуль насчитывает не более 20 - 40 строк и не более 8 - 10 параметров. Разбиение любой программы на такие модули облегчает отладку программы и способствует ее лучшему пониманию. Приведем набор положений, которые следует использовать при составлении программ с модульной структурой:

Выявление относительно самостоятельных фрагментов алгоритма;

Определение наиболее рационального описания подпрограммы;

Формирование списка используемых параметров;

Установление мест программы, в которых необходимо предусмотреть обращение к подпрограммам;

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

Введение

1. Теоретическая часть

1.1.1 Процедуры и функции

1.1.2 Модули

1.1.3 Открытые массивы и строки

1.1.4 Нетипизированные параметры

1.2 Объектно-ориентированное программирование

Заключение

Список литературы

Введение

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

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

1. Построить таблицы по приведенным данным.

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

3. Результаты представить в виде консолидированной таблицы.

4. Сформировать и заполнить форму сводной ведомости.

5. Результаты представить в графическом виде.

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

1. Теоретическая часть

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

1.1.1 Процедуры и функции

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

Заголовок блока определяет форму вызова программы. В разделе описаний блока объявляют внутренние локальные ресурсы блока (переменные, типы, внутренние подпрограммы). Раздел операторов содержит инструкции подпрограммы в операторных скобках begin … end.

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

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

Из основной программы данные могут быть получены:

· Неявно – с использованием глобальных констант и переменных;

· Явно – через параметры.

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

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

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

В BorlandPascal параметры в подпрограмму могут передаваться тремя способами:

· Как значения – в подпрограмму передаются копии значений параметров, и никакие изменения этих копий не возвращаются в вызывающую программу;

· Как переменные – в программу передаются адреса фактических параметров, соответственно все изменения этих параметров в подпрограмме на самом деле происходят с переменными, переданными в качестве фактических параметров; такие параметры при описании помечаются служебным словом var; в качестве фактических значений параметров – переменных нельзя использовать литералы;

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

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

< переменная> :=< имя функции> (< фактические параметры> ).

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

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

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

Модуль

внешние – внутренние –

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

Unit < имя модуля>

Interface

<интерфейсная секция>

[ Begin

<секция инициализации>]

End .

Имя модуля должно совпадать с именем файла, в котором он содержится. Результат компиляции модуля помещается в файл с тем же именем и расширением.tpu.

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

· Compile – компилируется только основная программа, все модули должны быть предварительно откомпилированы в файлы <имя модуля> .tpu и размещены либо в текущем каталоге, либо в одном из каталогов, указанных как источники файлов.tpu в настройках среды;

· Make – модули, для которых не обнаружены файлы.tpu, компилируются из соответствующих файлов.pas, которые должны находиться в текущем каталоге или в каталогах, указанных в настройках среды в качестве источников исходных файлов модулей;

· Build – все ранее откомпилированные модули.tpu игнорируются и все модули компилируются из своих исходных файлов заново.

В процессе отладки модулей целесообразно использовать режим Build, а при отладке программы – режим Compile

Интерфейсная секция содержит объявление ресурсов (в том числе заголовки подпрограмм), к которым возможны обращения извне.

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

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

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

Uses <имя модуля 1>, <имя модуля 2>,

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

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

Вместе с системой программирования на BorlandPascal поставляются следующие библиотеки:

System – основная библиотека – содержит описание всех стандартных процедур и функций, таких, как математические функции, функции преобразований, процедуры и функции обработки строки и т.п. Ресурсы данной библиотеки доступны любой программе без специального указания. Crt – библиотека управления экраном в текстовом режиме – содержит описание переменных, констант и процедур и функций, обеспечивающих управление экраном, клавиатурой и динамиком. Graph – библиотека управления экраном в графическом режиме – содержит описание переменных, констант и процедур и функций, обеспечивающих управление экраном в графическом режиме. Dos – библиотека организации взаимодействия с операционной системой MSDOS – содержит описание процедур и функций, обеспечивающих обращение к функциям операционной системы.

Поставляемые вместе с описанными модули Turbo3, Printer, Graph3, Overlay устарели и практически не используются.

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

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

Открытый массив – это конструкция описания типа массива без указания типа индексов.

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

High (< идентификатор массива>) – для обычного массива возвращает верхнюю границу индекса массива, для открытого – максимальное значение индекса.

Low (< идентификатор массива>) – для обычного массива возвращает нижнюю границу индекса массива, для открытого – ноль.

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

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

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

Автоопределенное преобразование типов;

Наложенное описание переменной определенного типа.

При автоопределенном преобразовании типов тип выражения указывают явно, например:

Procedure Proc (Var: а);

b: = Integer (a) + 10;

Для наложения переменной определенного типа используют описание с absolute, например:

Procedure Proc (Var: а);

Var r: real absolute a;

При этом переменная r оказывается в памяти размещенной в том же месте, что и нетипизированный параметр а, и, соответственно, любое изменение r приведет к изменению а.

1.2. Объективно-ориентированное программирование

Формализованной основой ООП является модель с рядом базовых категорий:

· Абстрагирование – процесс выделения наиболее существенных характеристик некоторого объекта, которые отличают его особенности при дальнейшем анализе и использовании. При этом абстрагирование концентрирует внимание на внешних особенностях объекта, позволяя в значительной степени игнорировать детали реализации этих особенностей. Именно выбор эффективного набора абстракций для конкретной предметной области и представляет собой главную задачу ООП.

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

· Модульность – свойство системы, определяющее возможность ее декомпозиции на ряд слабо связанных между собой модулей. Совместно с инкапсуляцией модульность создает барьеры между абстракциями.

· Иерархия – расположение (упорядочивание) абстракций по ряду уровней. В рамках сложных систем основными видами иерархических структур являются

· структура классов (иерархия по номенклатуре введенных классов) и структура объектов (иерархия по составу).

Абстрагирование и инкапсуляция являются взаимодополняющими операциями: абстрагирование акцентирует влияние на внешних особенностях объекта, а инкапсуляция (или, иначе, ограничение доступа) не позволяют объектам-пользователям различать внутреннее устройство объекта. Такой подход позволяет программисту не знать частных деталей реализации программной системы и программировать, используя объекты с закрытой внутренней организацией. Инкапсуляция предполагает введение нового механизма структурирования и оптимизации данных – класса.

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

· Типизация – ограничение, накладываемое на класс объектов и препятствующее взаимозаменяемости различных классов (использованию объектов одного класса вместо другого);

· Параллелизм – свойство объектов находиться в активном или пассивном состоянии и, соответственно, возможность отличать друг от друга активные и пассивные объекты;

· Устойчивость – свойство объектов существовать во времени (вне зависимости от породившего данный объект процесса) и/или в пространстве (при перемещении объекта из области, в которой он был создан, в другую область).

К концептуальным понятиям в ООП относятся объекты и классы.

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

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

Важное значение для классов имеют свойства наследования и полиморфизма.

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

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

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

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

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

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

В качестве преимуществ ОПП отмечают:

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

· Естественность объектной модели, ориентированной на человеческое восприятие мира, а не на компьютерную реализацию;

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

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

Фактически, основное различие между объектно-ориентированным и «обычным» программированием состоит в том, что при обычном программировании программисты ограничены встроенными абстракциями, в то время как при использовании объектно-ориентированного программирования они могут определять свои собственные абстракции. Объектно-ориентированное проектирование – дело чрезвычайно сложное. Необходим большой опыт и здравый смысл, чтобы решить, что же заслуживает того, чтобы стать объектом. В целом ООП использует в качестве основной конструкции не только абстрактный тип данных, оно является более общим в целом и простирается до абстрагирования внешних устройств, моделей реального мира и т.д.

Следует отметить, что интегрированный пакет программ MSOffice также построен на основе объектно-ориентированного программирования, и его можно рассматривать как семейство классов и объектов.

Заключение

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

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

Все ресурсы модуля делятся на две группы: внешние – предназначенные для использования другими программными единицами, и внутренние – рабочие ресурсы данного модуля.

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

Объектно-ориентированное программирование стало необычайно популярным в последние годы. Оно определяет новое понимание процесса вычисления, а также то, как можно структурировать информацию внутри компьютера.


Список литературы

1. Бадд Тимоти Объектно-ориентированное программирование в действии/ [Пер. с англ. А Берднокова; Гл. ред. В. Усманов]. – СПб: Питер, 1997. – 460 с.: ил.

2. Басс Лен Архитектура программного обеспечения на практике [пер. с англ.] / Л. Басс 2-е – изд. – СПб: Питер, 2006. – 574 с.

3. Боровцов Е.Г. Введение в объектно-ориентированное программирование.: Учеб. пособие по курсу «Технология программирования для студентов специальностей 2204» - «Программное обеспечение вычислительной техники»/ Гос. ком. Рос. Федерации по высшему образованию, Алт. гос. техн. ун-т им. И.И. Ползунова. – Барнаул: Изд-во АлтГТУ, 1996. – 79 с.

4. Бутаков С.В. Высокоуровневые методы информатики и программирования. Учеб. пособие. : Министерство образования и науки Российской Федерации, Федеральное агентство по образованию, Алт. академия экономики и права – Барнаул: изд-во ААЭП, 2005. – 72с.

5. Иванова Г.С. Основы программирования [Учеб. для вузов] 2-е – изд. перераб. и дополнено. – М.: изд – во МГТУ им. Н.Э. Баумана, 2002. – 415 с. ил.

6. Непейвода Н.Н. Стили и методы программирования курс лекций: учеб. пособие: М.: 2005. – 316 с.: ил.

7. Окулов С.М. Основы программирования. М.: Лаборатория базовых значений 2002. – 424 с.

8. Пол Айра Объектно-ориентированное программирование на С++/ Пер. с англ. Д. Ковальчука. – 2-е – изд. – М; СПб: БИНОМ; Невский диалект 1999. – 461 с.

9. Солодкий О.Г. Основы программирования: сборник задач; М-во образования и науки Рос. Федерации по образованию, Алт. акад. экономики и права. – Барнаул: Изд. ААЭП, 2005. – 83 с.

10. Хореев П.Б. Технологии объектно-ориентированного программирования; учеб. пособие; - М.: Academia, 2004. – 447 с.

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

хорошую работу на сайт">

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

Размещено на http://www.allbest.ru/

МИНОБРНАУКИ РОССИИ

Реферат

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

Введение

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

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

Процедурное программирование. Основная идея этого стиля - алгоритмизация процесса решения задачи и выбор наилучшего алгоритма (по расходу памяти или по быстродействию.

Структурное программирование. Здесь основная идея прекрасно выражена Н. Виртом в его книге "Алгоритмы + структуры данных = программы". Это был ответ на кризис в области программирования, начавшийся в середине 60-х годив, когда объем исходного программного кода перешел рубеж в 1000 строк. В 1971 году появился алгоритмический язык Pascal и немного позже, в 1972 году, язык С..

Модульное программирование. Здесь основная идея заключалась в том, чтобы "спрятать" данные и процедуры внутри независимых программных единиц - модулей. Эту идею впервые реализовал Н. Вирт в алгоритмическом языке Modula (1975-1979 годы), а затем "подхватили" и остальные, распространенные в то время языки программирования. Например, известные системы программирования Turbo Pascal и Turbo С.

Объектно-ориентированное программирование. С середины 80-х годов объем исходного программного кода перешел рубеж в 100 000 строк. Нужно было сделать не случайное объединение данных и алгоритмов их обработки в единое целое, а - смысловое. То есть необходимо было создать модульное программирование нового уровня, когда основной акцент делается на смысловую связь структур данных и алгоритмов их обработки

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

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

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

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

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

2. Основные характеристики программного модуля

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

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

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

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

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

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

o всегда следует использовать рутинный модуль, если это не приводит к плохим (не рекомендуемым) сцеплениям модулей;

o зависящие от предыстории модули следует использовать только в случае, когда это необходимо для обеспечения параметрического сцепления;

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

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

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

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

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

3. 1 Функциональная декомпозиция

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

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

3.2 Минимизации количества передаваемых параметров

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

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

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

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

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

3.3 Минимизации количества необходимых вызовов

Одним из существенных преимуществ модульного программирования является то, что программа основного уровня очень часто может быть сконструирована для чтения как последовательность вызываемых процедур. Этот факт существенно повышает «понимаемость» программы, поскольку читатель может познакомиться с ее основным потоком и функционированием после прочтения только одной - двух страниц программного кода. Однако эта особенность может также иметь и недостатки. Одна из многих верхних статистических оценок программирования говорит о том, что 90% времени выполнения типовых программ расходуется в 10 % кода программы. При этом подразумевается, что если эти 10 % содержат большое количество цепочечных вызовов процедур, то суммарное время, затрачиваемое на управление выполнением программы, может стать непреодолимым препятствием на пути использования этого подхода.

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

Заключение

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

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

Все ресурсы модуля делятся на две группы: внешние - предназначенные для использования другими программными единицами, и внутренние - рабочие ресурсы данного модуля.

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

Размещено на Allbest.ru

Подобные документы

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

    реферат , добавлен 29.01.2016

    Характеристика модульного программирования: процедуры и функции, модули и их структура, открытые массивы и строки, нетипизированные параметры. Способы передачи параметров в подпрограммы в Borland Pascal. Объектно-ориентированное программирование.

    контрольная работа , добавлен 28.04.2009

    Сущность программирования с использованием среды Delphi 7 и ее основные графические возможности. Структура автономно компилируемого программного модуля и его принципы. Основные приемы работы с графическими процедурами, построение дуги, круга и эллипса.

    курсовая работа , добавлен 16.12.2011

    Появление первых вычислительных машин и возникновение "стихийного" программирования. Структурный подход к декомпозиции сложных систем. Развитие модульного и объектно-ориентированного программирования. Особенности компонентного подхода и CASE-технологий.

    презентация , добавлен 14.10.2013

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

    презентация , добавлен 05.11.2016

    Предмет исследования – современные методы разработки программ таких, как объектно-ориентированное программирование и визуальное проектирование, а также структурное и модульное программирование. C++ - универсальный язык программирования. Ключевые понятия.

    курсовая работа , добавлен 10.01.2009

    Почему C++. Возникновение и эволюция языка C++. Сравнение языков С++ и С. Эффективность и структура. Процедурное программирование. Модульное программирование. Абстракция данных. Объектно-ориентированное программирование. Улучшенный С.

    реферат , добавлен 03.06.2004

    Обзор технологий и систем геоинформационных систем. Системное и функциональное проектирование программного модуля, его разработка с использованием сред программирования Visual C++ 6.0, Qt 3.3.3. Технико-экономическое обоснование данного процесса.

    дипломная работа , добавлен 13.03.2011

    Проектирование программного модуля в среде программирования Borland Delphi 7.0. Схемы алгоритмов решения задач по темам "Символьные переменные и строки", "Массивы", "Работа с файлами", "Создание анимации". Реализация программного модуля, код программы.

    отчет по практике , добавлен 21.04.2012

    Проектирование информационной системы. Анализ языков программирования и существующих решений для администрирования системы управления базами данных. Разработка модуля взаимодействия и структуры программы. Модули авторизации и соединения с базой данных.

Статьи по теме: