Блочная структура. Структура программы: блочная Блочная структура программы

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

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

Структура модуля аналогична структуре программы на языке Паскаль. Заголовок для модуля обязателен и начинается со слова UNIT (вместо PROGRAM как в обычной программе):

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

Имя модуля должно совпадать с именем файла на языке Pascal. Когда Delphi автоматически генерирует различные модули, он делает так, чтобы имя модуля совпадало с именем файла.

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

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

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

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

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

Uses M1 , М2 ...;

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

Интерфейсная часть заканчивается с началом исполнительной части. Исполнительная часть начинается с ключевого слова Implementation. Она содержит тела всех процедур и функций, описанных в интерфейсной части. Она может включать локальные метки функций и разделов операторов. После слова Implementation также может следовать слово Uses со списком модулей, которые используются в исполнительной части. Далее указываются метки, типы, константы, переменные, процедуры и (Ьункпии модуля.

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

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

Кратко синтаксис описания модуля выглядит так:

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

<имя модуля>. <имя переменной>.

Пример 10.1. Рассмотрим возможности взаимосвязи модулей. Программа может получиться короче, если разрешить модулям использовать внутренние элементы друг друга.

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

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

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

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

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

Здесь основная программа Р разбивается на три основных модуля М1, М2, МЗ. Из этих модулей в программе используются интерфейсные элементы А, В, С (из первого модуля), D (из второго модуля), F, G, К, L (из третьего модуля). Каждый из этих модулей разбивается на более мелкие, например, М2 разбивается на М2.1, М2.2, М2.3 и т.д. Из этой схемы, например, видны перекрестные ссылки между модулями М2 и М3, а также между М2.2 и М2.3.

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

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

формула" src="http://hi-edu.ru/e-books/xbook691/files/ris-page173.gif" border="0" align="absmiddle" alt="

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

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

  • функциональный (сильная связность) - 10;
  • последовательная - 9;
  • коммуникативная - 7;
  • процедурная - 5;
  • временная - 3;
  • логическая - 1;
  • по совпадению (слабая связность) - 0.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

int1=5*x; int2=8*y;

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

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

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

Блочно-структурированные языки программирования

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

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

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

К строго блочно- структурированным языкам программирования относятся языки ALGOL 60, Pascal , PL/I .

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

Следующий пример иллюстрирует блочную структуру программы на языке Pascal .

program Project1; procedure P1(); procedure P2(); {Вложенная процедура} var i:Integer; begin end; begin {Код процедуры P1} end; begin {Код главной программы Project1} end.

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

Program Project2; {Начало программы} uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; {$R *.res} {$R *.dfm} {Имя DFM-файла должно совпадать с именем модуля (блока). } {Для получения единого модуля на языке Object Pascal при автоматическом создании приложения в среде Delphi файл Unit1.dfm следует переименовать в Project2.dfm, а код модуля Unit1.pas перенести в модуль Project2.pas} type {Объявление нового типа окна формы TForm1 } TForm1 = class(TForm) Button1: TButton; Button2: TButton; ListBox1: TListBox; Edit1: TEdit; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure ListBox1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var {Начало области объявлений } Form1: TForm1; i: Integer; procedure TForm1.Button1Click(Sender: TObject); begin Edit1.Text:="Button1"; end; procedure TForm1.Button2Click(Sender: TObject); var i:Integer; procedure P1(); {Вложенная процедура} var i:Integer; begin i:=5; Edit1.Text:= Edit1.Text+" i= " + IntToStr(i); end; begin Edit1.Text:="Button2"; i:=0; P1 (); end; procedure TForm1.ListBox1Click(Sender: TObject); begin Edit1.Text:="ListBox1"; end; begin {Начало выполнения программы} Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. Пример 5.1. Блочная структура программы на языке Object Pascal

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

Внешний блок – это блок, в который вложена подпрограмма. Внутренний блок - сама подпрограмма. Все описания, расположенные во внешних для данной подпрограммы блоках, называются глобальными по отношению к блоку, который образует данная подпрограмма. Все описания, расположенные во внутреннем блоке называются локальными. Можно ввести понятие уровень вложенности. Если в разделе описания процедур и функций описаны две или более подпрограмм, то говорят, что эти подпрограммы одного уровня вложенности. По отношению к внешнему блоку они являются внутренними. По отношению между самими подпрограммами мы не можем использовать термины внешняя или внутренняя, так как они одного уровня вложенности. Если в разделе описания процедур и функций внешнего блока вложена подпрограмма, внутри которой в таком же разделе расположена другая подпрограмма, то мы говорим о разном уровне вложенности этих подпрограмм. Для третьего блока, представляющего собой самую внутреннюю подпрограмму, оба блока, в которые она вложена, будут внешними. Уровень вложенности этой подпрограммы 2. Для второго блока третий блок будет внутренним, а первый - внешним. Уровень вложенности второго блока 1. Для первого блока (самого внешнего) второй и третий блоки будут внутренними. Уровень вложенности первого блока 0, т.е. этот блок является основной программой.

Для примера рассмотрим структуру блоков, предложенную автором языка (рис.16.16). Здесь в седьмой раздел программы A вложены две подпрограммы B и C. В подпрограмму В вложена подпрограмма D. В свою очередь в подпрограмму D вложена подпрограмма G. В подпрограмму С вложены две подпрограммы E и F.

Рис. 16.16. - Пример блочной структуры

Разберемся со сферой действия описаний. Описания меток действуют только внутри раздела операторов блока, в котором они описаны. Все остальные описания действуют не только внутри блока, в котором они описаны, но и во всех внутренних блоках, вложенных в данный блок (вне зависимости от глубины вложенности). При этом казалось, что могут возникнуть конфликты между глобальными и локальными описаниями , так как в разных блоках одинаковыми именами могут быть поименованы разные понятия. Для того чтобы таких конфликтов не возникало, принято следующее правило - все имена, определяемые в локальных описаниях, отменяют действия совпадающих имен, описанных в глобальных описаниях. На рис. 16.17 показано расположение блоков из примера по уровням. Здесь линиями со стрелками показано действие глобальных описаний. Так в блоке G действуют описания внешних блоков D, B, A.

Рис. 16.17. - Расположение блоков по уровням и действие глобальных описаний

Особо рассмотрим доступ к подпрограммам. Любая подпрограмма может быть вызвана:

    из раздела операторов блока, в котором она описана;

    из раздела операторов самой себя (прямая рекурсия);

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

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

Эти правила можем переформулировать следующим образом – любая подпрограмма может вызывать на исполнение:

    любую подпрограмму, описанную в разделе подпрограмм данной;

    саму себя (прямая рекурсия);

    все внешние подпрограммы по отношению к данной (косвенная рекурсия);

    подпрограммы, описанные ранее на том же уровне вложенности.

Взаимодействие блоков (подпрограмм) из примера показано на рис. 16.18.

Рис. 16.18 - Пример взаимодействия между блоками

Здесь линиями со стрелками показаны возможности вызова подпрограмм на выполнение (стрелки указывают направление вызова). Так, например, из программы А могут быть вызваны только подпрограммы В и С, которые вложены в седьмой раздел. Из подпрограммы F могут быть вызваны сама подпрограмма F (прямая рекурсия), подпрограмма С, в которую она вложена (косвенная рекурсия), и подпрограмма Е (находится на одном уровне и описана ранее). з программы А могут быть вызваны подпрограммы B и С. В таблице 16.9 для перечислены все возможные взаимодействия между блоками. Здесь основной алгоритм – блок, из которого производится вызов подпрограммы, вспомогательный алгоритм – вызываемая подпрограмма.

Таблица 16.9. Пример взаимодействия между блоками

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

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

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

Си-программа является отдельным программным модулем, который оформляется и записывается во внешнюю память как исходный файл с расширением “.c”, например, myprog.c.

Структуру модуля программы и области действия её объектов можно представить следующей схемой:

/* Глобальные объекты и описания */ /* Область действия */

Директивы предпроцессора глобальная макроопределения

прототипы функций

описания типов

описания глобальных переменных

заголовок функции локальная

{внешние переменные блока;

операторы;

{ внутренний блок локальная

описания других функций

/* конец программы */

Пример. Применение вложенных блоков с одноимёнными переменными.

Программа :

{ int i=2; /* i – переменная внешнего блока */

int count=0; /* count – внешняя переменная */

while (count <= i) /* цикл внешнего блока */

{ int=0; /* i – локальная переменная внутреннего блока */


count++; /* счётчик циклов */

printf (“В цикле: count=%d; i=%d\n”, count, i);

/* конец внутреннего блока, возврат к переменной i внешнего блока */

printf (“Вне цикла: count=%d, i=%d”, count, i);

Результат программы :

В цикле count=1 i=0

В цикле count=2 i=0

В цикле count=3 i=0

Вне цикла count=3 i=2

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

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

Память для переменных с классом static отводится в сегменте данных (статическая память программы), а не в стеке, благодаря чему они сохраняют своё значение при выходе из блока. Если отсутствует явная инициализация таких переменных, то по умолчанию они устанавливаются в 0. Инициализация выполняется один раз и не повторяется при новом входе в блок. Объекты класса static имеют локальную область действия (блок) и глобальное время жизни (время выполнения программы).

Пример . Использование статических переменных.

Программа :

void example (int c); /* прототип функции */

void main () /* главная функция */

{ int count; /* локальная переменная блока */

for (count=9; count >= 5; count -= 2) /* цикл счетчика */

example (count); /* вызов функции */

void example (int c) /* заголовок функции */

{ int f=1; /* локальная переменная */

static int stat=1; /* статическая переменная */

printf (“c=%d, f=%d, stat=%d\n”, c, f ,stat);

stat++; /* изменение статической переменной */

Результаты программы : c=9, f=1, stat=1

c=7, f=1, stat=2

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

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

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

Спецификация программного модуля содержит:

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

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

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

Модульная структура программы представлена на (схема 1)


Схема 1.Модульная структура программы

ПРОГРАММИРОВАНИЕ

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

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

Структурное кодирование.

Проектирование сверху вниз.

Модульное программирование – это процесс разделения программы на логические части. Использование модулей приводит к снижению сложности. Модульную программу легче написать и протестировать.

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

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

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

Объекты – некоторые элементы, из которых строится программное приложение.

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

Событие – это то, что происходит в реальном времени и может вызвать те или иные ответные действия.

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

Методы объектов иметь любой из типов:

Статический

Виртуальный

Динамический

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

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

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

В процессе построения приложения необходимо выбирать из палитры компоненты, на основе которых будет строиться проект. Еще до компиляции видно результаты своей работы. В этом смысле проектирование в Delphi мало чем отличается от проектирования в интерпретирующей среде, однако после выполнения компиляции получаем код, который исполняется в 10-20 раз быстрее, чем то же, самое, сделанное при помощи интерпретатора. Cреда Delphi включает в себя полный набор визуальных инструментов для скоростной разработки приложений (RAD - rapid application development), поддерживающей разработку пользовательского интерфейса.

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

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

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

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

Image- предназначен для отображение на форме графических изображений по умолчанию выводит на поверхность формы изображения представленных в bmp формате. Для вывода изображений в jpg формате необходимо в дерективе uses подключить модуль JPEG. После размещения на форме компонента Image, он принимает вид выделенной прямоугольной области

MainMenu- не визуальный компонент delphi(место размещения которого на форме не имеет значения для пользователя так как он увидит не сам компонент, а меню, с генерированное им), предназначенный для вывода главного меню на форме

Memo- являются окном редактирования многострочного текста который можно загружать из файла либо сохранять введенную информацию в файл текстового формата

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

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

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

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

ТЕСТИРОВАНИЕ И ОТКЛАДКА

Тестирование – это динамический контроль программы, т.е. проверка правильности программы при ее выполнении на компьютере.

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

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

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

Учитывая разнообразие источников ошибок, при составлении плана тестирования классифицируют ошибки на два типа: 1 – синтаксические; 2 – семантические (смысловые).

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

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

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

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

TmrLabel: TLabel;

if TimeToAnswer = 0 then

dec(TimeToAnswer);

TmrLabel.Caption:= Format("Время на ответ: %b сек.", );

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

procedure TForm3.Timer1Timer(Sender: TObject);

TmrLabel: TLabel;

if TimeToAnswer = 0 then

dec(TimeToAnswer);

TmrLabel:= TLabel(PageControl1.ActivePage.FindComponent("Panel1").FindComponent("TmrLabel"));

TmrLabel.Caption:= Format("Время на ответ: %d сек.", );

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

Password: String;

if Password <> "1234" then

if not InputQuery (Form2) then

Form2.BringToFront;

Ошибка заключалась в том, что для вывода пароля использовалась процедура InputQuery, а нужно было использовать Assigned. Код после использования выглядит так:

procedure TForm1.N2Click(Sender: TObject);

Password: String;

if Password <> "1234" then

ShowMessage("Неверный пароль!");

if not Assigned(Form2) then

Application.CreateForm(TForm2, Form2)

Form2.BringToFront;

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

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

ДОКУМЕНТИРОВАНИЕ

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

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

АИС «Конструктор теста» предназначена для создания тестов, для очного итогового контроля качества усвоения теоретического материала, приобретенных знаний и практических навыков обучаемых в учебных заведениях по дисциплинам относящимся к информационным технологиям.

Главная форма (рис. 1) представляет собой меню где выбираешь между конструктором и тестом.

Рис. 1. Первоначальная форма

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

Рис. 2. Конструктор

При нажатии на вкладку тест открывается форма, где можно пройти тестирование по выбранному вами тестом (рис. 3).

Рис. 3 Тест


ЗАКЛЮЧЕНИЕ

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

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

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

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

В процессе выполнения курсовой работы были осуществлены следующие задачи:

Закрепились и углубились теоретические знания;

Приобретены практические навыки при разработке программного продукта;

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


СПИСОК ЛИТЕРАТУРЫ

1. Вигерс И.К. Разработка требований к программному обеспечению: «Русская редакция», 2010, 576 с.

2. Бобровский С. Delphi 5: Учебный курс. - СПб.: Издательство "Питер", 2010. - 640 с.

3. Вонг, Уоллес. Основы программирования. М. 2011, 336 с.

4. П.П. Беленький. Учебное пособие по информатике - Ростов на дону «Феникс» 2012. – 448c.

5. Дантеманн Дж., Мишел Д., Тэйлор Д. Программирование в среде Delphi.- К.: НИПФ-"Diasoft-Ltd.",2011. - 608с.

6. Рубенкинг. Программирование в Delphi для "чайников". - К.: Диалектика, 1996. - 304с.

7. Дарахвелидзе П.Г., Марков Е.П. Delphi - среда визуального программирования.- СПб: BHV-Санкт-Петербург, 2011. - 352с

8. Сурков К.А., Сурков Д.А., Вальвачев А.Н. Программирование в среде DELPHI 2.0. - Минск: ООО "Попурри", 2012. - 640с.

9. Савицкая, Г.В. Анализ программной деятельности: Учебник / Г.В. Савицкая. - Минск: ООО «Новое знание», 2010;

10. Дж.Хьюз, Дж.Мичтом. Структурный подход к программированию. М.: Мир, 2011. - С. 29-71.

11. Диплом-Экспресс. Руководство пользователя. Версия 1.8. НТЦ «АРМ-Регистр», 2010, 41 с.

12. Коржинский С.Н Самоучитель работы на компьютере.- 2-е изд., перераб. и доп.- М.: ТК Велби, Изд-во Проспект, 2011, 370 с.

13. Леонтьев В.П. Новейшая энциклопедия ПК, 2011, 960 с.

14. Мазуркевич А., Еловой Д. РНР: настольная книга программиста, 2011, 480с.

15. Максимов Н.В. Архитектура ЭВМ и вычислительные системы, 2013, 512с.

16. Орлов С.А. Технология разработки программного обеспечения. – М.: Питер, 2013, 474 с.

17. Симонович С.В. Общая информатика. - М.: «Инфорко-Пресс», 2010, 428с.

18. Ташков П. Защита ПК на 100%: сбои, ошибки и вирусы, 2010, 288 с.

19. Шалин П.А. Энциклопедия Windows XP. - СПб.: «Питер», 2012, 688 с.

20. Культин Н.Б. - Основы программирования в Delphi 7, – СПб.: БХВ-Петербург, 2013

21. Ревич Ю. - Нестандартные приемы программирования на Delph. – СПб.: БХВ-Петербург, 2012

22. Сухарев - Основы Delphi. Профессиональный подход. – СПб.: Наука и Техника, 2011

23. Фленов - Библия Delphi. – СПб.: БХВ-Петербург, 2011

24. Ремизов Н. Delphi – М.: Питер, 2013.

25. Шпак Ю.А. - Delphi 7 на примерах. – К.: Издательство Юниор, 2012

26. Дарахвелидзе П., Марков Е. - Программирование в Delphi 7 (+ дискета). – СПб.: БХВ-Петербург, 2013

27. Кэнту - Delphi 7 для профессионалов. – СПб. Питер, 2012.