Язык программирования C++ от Страуструпа

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


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

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

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

[1]    Предоставить пользователю интерфейс для стека (например, функции push () и pop ()).

[2]    Гарантировать, что представление стека (например, в виде массива элементов) будет доступно лишь через интерфейс пользователя.

[3]    Обеспечивать инициализацию стека перед первым его использованием.

Язык Модула-2 прямо поддерживает эту парадигму, тогда как С только допускает такой стиль. Ниже представлен на С возможный внешний интерфейс модуля, реализующего стек:

// описание интерфейса для  модуля, реализующего стек символов:

void push ( char );

char pop ();

const int stack_size = 100;

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

#include "stack.h"                 // используем интерфейс стека



static char v [ stack_size ];      // ``static'' означает локальный

                                   // в данном файле/модуле

static char * p = v;               // стек вначале пуст

void push ( char c )

{

  //проверить на переполнение и поместить в стек

}

char pop ()

{

  //проверить, не пуст ли стек, и считать из него

}

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

#include "stack.h"                 // используем интерфейс стека

void some_function ()

{

  push ( 'c' );

  char c = pop ();

  if ( c != 'c' )  error ( "невозможно" );

}

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



Содержание раздела