ВІКІСТОРІНКА
Навигация:
Інформатика
Історія
Автоматизація
Адміністрування
Антропологія
Архітектура
Біологія
Будівництво
Бухгалтерія
Військова наука
Виробництво
Географія
Геологія
Господарство
Демографія
Екологія
Економіка
Електроніка
Енергетика
Журналістика
Кінематографія
Комп'ютеризація
Креслення
Кулінарія
Культура
Культура
Лінгвістика
Література
Лексикологія
Логіка
Маркетинг
Математика
Медицина
Менеджмент
Металургія
Метрологія
Мистецтво
Музика
Наукознавство
Освіта
Охорона Праці
Підприємництво
Педагогіка
Поліграфія
Право
Приладобудування
Програмування
Психологія
Радіозв'язок
Релігія
Риторика
Соціологія
Спорт
Стандартизація
Статистика
Технології
Торгівля
Транспорт
Фізіологія
Фізика
Філософія
Фінанси
Фармакологія


Понятие модуля. Преимущества модульного программирования. Структура модуля.

Понятие модульности

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

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

 

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

 

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

 

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

 

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

 

В разных языках программирования модульность поддерживается по-разному. Например, в С++ модулями являются файлы, которые компилируются отдельно. Для С/с++ традиционным является размещение интерфейсной части модулей в отдельные файлы с расширением .п (так называемые файлы-заглавия). Реализация, то есть текст модуля, сохраняется в файлах с расширением .с (в программах на С++ часто используются расширения .ее, .ср и .срр). Связь между файлами объявляется директивой макропроцессору #include. Такой подход строится исключительно на соглашении и не является строгим требованием самого языка. В языке Object Pascal принцип модульности формализированный немного строже. В этом языке определен особенный синтаксис для интерфейсной части и реализации модуля (unit). Язык Ada идет еще на шаг дальше: модуль (что называется package) также имеет две части - спецификацию и тело. Но, в отличие от Object Pascal, допускается раздельное определение связей с модулями для спецификации и тела пакета. Таким образом, допускается, чтобы тело модуля мало связки с модулями, невидимыми для его спецификации. Со временем при в проектировании программ акцент сместился с организации процедур на организацию структур данных. Помимо всего прочего это вызвано и ростом размеров программ. Модулем обычно называют совокупность связанных процедур и тех данных, которыми они управляют.

Парадигма программирования приобрела вид:

Определите, какие модули нужны; поделите программу так, чтобы данные были скрыты в этих модулях

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

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

 

Пример модуля. Способ использования модуля.

26.Массивы в языке С++. Связь указателей и массивов в С++.

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

 

float а [10]; // описание массива из 10 вещественных чисел

 

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

 

int b[5] = {3, 2, 1}; / / b[0]=3, b[l]=2, b[2]=l, b[3]=0, b[4]=0

 

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

Внимание

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

 

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

 

#include <iostream.h>

int main(){

const int n = 10;

int i,. sum;

int marks[n] = {3, 4, 5, 4, 4};

for (i = 0, sum = 0; i<n; i++) sum += marks[1];

cout << "Сумма элементов: " << sum;

return 0;

}

 

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

Внимание

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

 

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

#include <iostream.h>;

int main(){

const int n = 20; // количество элементов массива

int b[n]; // описание массива

int i;

for (i = 0; i> b[i]; // ввод массива

for (i = 0; i<n-1; i++){ // n-1 раз ищем наименьший элемент

// принимаем за наименьший первый из рассматриваемых элементов:

int imin = 1;

// поиск номера минимального элемента из неупорядоченных:

for (int j = i + 1; j<n; j++)

// если нашли меньший элемент, запоминаем его номер:

if (b[j] < b[imin]) imin = j;

int a = b[i]; // обмен элементов

b[i] = b[imin]; // с номерами

b[imin] = a; // i и imin

}

// вывод упорядоченного массива:

for (i = 0; 1<n; i++) cout << b[i] << ' ';

return 0;

}

Идентификатор массива является константным указателем на его нулевой элемент. Например, для массива из предыдущего листинга имя b — это то же самое, что &Ь[0], а к i-му элементу массива можно обратиться, используя выражение *(b+1). Можно описать указатель, присвоить ему адрес начала массива и работать с массивом через указатель. Следующий фрагмент программы копирует все элементы массива а в массив b:

int а[100], b[100]:

int *ра = а; // или int *р = &а[0];

int *pb = b;

for (int i = 0; i<100; i++) *pb++ =>*pa++; // или pb[1] = pa[1];

© 2013 wikipage.com.ua - Дякуємо за посилання на wikipage.com.ua | Контакти