Модули – одна из важных особенностей
Полезная статья? Пожалуйста, поставьте "+"
Языки программирования и методы трансляции - Содержание
Модули – это, пожалуй, самая интересная часть языка. Да и названием своим язык обязан именно этому понятию (Modula – modular language). Разбиение программы на модули выполняется для удобства разработки и получения качественных программ большого размера.
Под качеством программы можно понимать многие аспекты, но эта сторона очень расплывчата и неуловима. Пользователь может судить о качестве по эффективности программы, ее надежности и удобству. Наряду с этими свойствами существует чрезвычайно важная характеристика программы – ее ясность. Ясность, или читаемость программы важна при рассмотрении языка программирования как языка общения, предполагая, что текст программы будет читаться человеком. Чем сложнее решаемая задача, тем сложнее алгоритмы, и тем важнее организация правильной структуры программы, которая при определенной ясности позволит продемонстрировать правильность и надежность алгоритмов. На самом нижнем уровне элементами структуры являются операторы, на следующем – процедуры, а на верхнем – модули.
Как уже говорилось, структурный подход к программированию сильно повлиял на процесс разработки программы. Один из доводов Дейкстры к использованию структурного программирования состоял в том, что упрощение логики позволит упростить доказательство корректности программ. При этом, он утверждал, что формальная верификация может быть достаточно надежным средством проверки правильности программ, что подтверждается эмпирическими данными [17]. Фактически, структурное программирование, включающее верификацию корректности программистом, может стать основой разработки программного обеспечения при статистическом контроле качества (statistical quality control) [18].
В основу структурного подхода положен принцип алгоритмической декомпозиции, в соответствии с которым производится разделение функций программы на модули (блоки) по функциональной принадлежности, когда каждый модуль системы реализует один из этапов общего процесса [19].
Модуль – это единица компиляции, которая заключает в себе описание объектов программы – типов, констант, переменных и процедур. Из одного модуля можно обращаться к объектам, описанным в других модулях, если эти объекты сделаны доступными, т.е. импортированы в рассматриваемый модуль. Ключевая идея состоит в том, что модули могут храниться в «библиотеке» программ и к ним должно производится автоматическое обращение при загрузке и выполнении программы, непосредственно написанной программистом. Таким образом, возможно заранее подготовить набор часто используемых операций для повторного использования. Более сложные реализации языка предлагают средство, называемое раздельной компиляцией – модули запоминаются в «библиотеке» программ не в виде исходных текстов, а в откомпилированной форме.
Можно выделить два принципиальных соображения, лежащих в основе разбиения программы на модули: использование раздельной компиляции (а так же использование модулей, написанных другими программистами) и необходимость установления иерархии абстракций. Пусть имеется программа на некотором языке программирования, которая состоит из нескольких единиц компиляции. Каждая из этих единиц находится в отдельном файле, и в ней определяются объекты программы. Оттранслировав с помощью компилятора такой файл, можно получить объектный код. Все объектные файлы, необходимые для программы, затем собираются с помощью компоновщика в исполняемую программу. Важно здесь то, что когда компилятор обрабатывает очередную единицу компиляции, то он ничего не знает о ее связях с другими и на основании этого генерирует код, оставляя неопределенными ссылки на внешние объекты (на процедуры и переменные), которые доопределяются на этапе компоновки. При раздельной компиляции, поддерживаемой в языке Modula-2, компилятор имеет доступ к спецификации всех внешних объектов единицы компиляции; раздельно компилируются интерфейс модуля и его реализация. При этом осуществляется полный статический контроль типов и параметров процедур, а также проводится контроль областей видимости. Вообще говоря, при компиляции исполнительных модулей получаются объектные файлы, а для интерфейсных модулей – так называемые SYM-файлы. Это поддерживается в первоначальной реализации Вирта и его коллег – компиляторе Modula-2 в операционной системе RT-11 для компьютеров типа PDP-11, а также в Logitech Modula-2. В TopSpeed-реализации это не так. Разработчики среды упростили себе задачу, и компилятор каждый раз транслирует все необходимые интерфейсные модули.
Абстрагирование означает пренебрежение содержимым и тем самым игнорирование конкретных деталей. Например, для процедур ввода-вывода на экран программисту часто не нужно знать, как конкретно работают эти процедуры. Каждый модуль представляет собой абстракцию, если рассматривать его «снаружи». Можно говорить даже больше – не о абстрагировании данных, а о скрытии их. Это, во-первых, защита внутреннего содержания модуля – разграничение областей, а во-вторых, возможность изменения (улучшения) внутренней структуры импортируемого модуля без изменения импортирующего модуля. Такая эффективная декомпозиция модулей просто необходима при разработке больших программ, в особенности, если модули разрабатываются разными людьми (возможно на разных языках программирования).
Кроме возможности раздельной компиляции и абстракции данных и процедур, модули позволяют хранить значения переменных между вызовами процедур и разделять глобальные переменные. В модуле могут определяться переменные, инициализируемые при инициализации самого модуля, время жизни которых равно времени жизни модуля. В них могут храниться данные, необходимые для работы модуля и отделенные от глобальных переменных основной программы.
Одно из интересных следствий концепции модуля – проблема инициализации библиотечных модулей. До выполнения первого оператора основного модуля должна быть проведена инициализация всех прямо и косвенно импортируемых модулей. В какой же последовательности ее осуществлять? Это – чисто математическая задача, носящая название топологической сортировки. Для решения ее нужно проанализировать зависимость модулей друг от друга. При этом возможен взаимный импорт. Затем нужно построить цепочку инициализации. Это не простая проблема: в TopSpeed-реализации она решается довольно сложно. В Logitech это сделано намного элегантнее – в тело инициализации компилятор подставляет вызовы процедур инициализации всех импортируемых модулей, и, кроме того, гарантирует, что инициализация конкретного модуля производится ровно один раз. Но в любом случае все это делает сама система поддержки, а потому повода для беспокойства у программиста быть не должно.
|
Категория: Языки программирования и методы трансляции | Добавил: Ni-Cd (08 Декабря 2011)
|
Просмотров: 1779
| Рейтинг: 0.0/0 |
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]
|
|
Онлайн |
Онлайн всего: 2 Гостей: 2 Пользователей: 0 |
|
|