лекции (2015) (1160856), страница 9
Текст из файла (страница 9)
Экспортирующие -> Библиотечные.Удовлетворение зависимостей импортаНисходящий подход - сначала проектируется верхний модуль в иерархии импортовВосходящий подход - сначала проектируется нижний модуль в иерархии импортовАдаpackage P is← Описание экспортируемых ресурсовType T is record …end T;procedure init (X: out T);procedure destroy(X: inout T);...end P;package body Pprocedure init(X: inout T)…begin....end init;…end P;Очень похоже на Модулу-2Все имена испортируются последовательноВложенные модули (Ада, Модула-2)АдаПакеты могут быть вложеныpackage Outer isprocedure P;package Inner isprocedure Y;end Innerend OuterВо внутреннем пакете доступно все содержимое внешнего пакета, но не наоборот.Еще можно писать Outer.Inner.YМожно даже вкладывать определение пакета в реализацию другого пакета:package body Outer ispackage P is….end P;40package body P is….end P;end Outer;Это типа нисходящий подход.
(см. выше)Современный термин - тесно связанные модули (Closely Coupled Modules)Их реиспользование ограниченоМодула-2IMPLEMENTATION MOD:MODULE M[4]EXPORT P1, P2;END M;END MOD;Лев ([925-946], завершено)Абстрактный тип данных (АТД)Ранее (годов до 70-х) считалось, что тип данных (ТД) – это множество объектов.Начиная с 70-х появилось понятие Абстрактного Типа Данных – это просто интерфейс –перечисление операций, которые можно делать с объектами этого типа.Во многих стареньких языках это реализуется с помощью модулей:Модула-2 – скрытый тип данных (opaque).
В модуле определений пишется:DEFINITIONM;TYPE T; <---- Скрытый (Opaque) тип данныхCONST N; <---- ПростоCONST, без типа!PROCEDURE INIT(VAR X: T) <---- Обратитевнимание на тип!. . . . .END M.Объекты скрытого типа можно передавать в функции, делать операции :=, =, # (это значит “неравно”). Обычно это реализуется с помощью указателей. Поэтому оператор:= может иметь две семантики: глубокое и поверхностное копирование.В Обероне похожее дело, тоже структуры могут быть скрыты. Однако присваивание уже побитовое,т.е. есть единственная семантика.В Модуле-2 для компиляции модуля С с импортом модуля M достаточно модуля объявлений, т.е.компилятор может всё необходимое вычислить по нему. Это минимизирует затраты наперекомпиляцию, т.к.
при изменении модуля реализации требуется скомпилировать лишь его иперелинковать.В C и C++ есть трюк под названием .pch – Precompiled Headers – просто сериализация таблицкомпилятора, для экономии времени на компиляцию заголовочных файлов.Вот пример стека на Аде:package Stacks istype Stack is private;procedure Push(S:inout Stack; X:T);procedure Pop(S:inout Stack; X:out T);procedure IsEmpty(S: in Stack) return Boolean;41private:<структура приватного типа>Type Stack is recordBody:array(1..128) of T;top:integer := 1;end record;end Stacks;По-прежнему есть операции присваивания и сравнения. Опять появляются две семантикикопирования.
Можно сделать совсем настоящий АТД:type Stack is limited private; - целиком закрыть всю структуру данных.Тогда все операции нужно реализовывать самостоятельно.Эквивалентность типов данныхВ Аде и Си – именная эквивалентность (совместимы только типы с совпадающими именами).Ада:type Newint is new Integer; ----> Newint != IntegerС:struct C {int a;} != struct S {int s;}C++: всё переводит в типы Си:class X { struct X {…};void f(); ---> void f_X( X *this);}Для генерации имени функции используется mangling (генерация уникальных имён), поэтомудостаточно именной эквивалентности.Виды трансляции1. Цельная – модульность отсутствует.
(стандартный Паскаль)2. Пошаговая или инкрементальная – транслятору предъявляется лишь очередноеисправление или дополнение (REPL – read – eval – print – loop)3. Независимая – транслятору предъявляют отдельные модули, а связываниеоттранслированных модулей выполняет редактор связей или загрузчик (Фортран)Раздельная трансляция1. Зависимая – при трансляции используется контекст. Контекст используется для контролямежмодульных связей. Нужно, если есть двусторонние связи между модулями.2.
Независимая – никакого контекста нету (например, ассемблер и Си – Си++)Зависимая трансляцияАда. Модули бывают● Первичные – спецификация пакетами● Вторичные – реализация (тело)Стандартная двусторонняя связь устанавливается между модулем спецификации и модулемреализации.Когда же сами спецификации представляют собой внутренние компоненты других модулей,то по-прежнему можно оформлять соответствующие таким спецификациям тела пакетов, процедури задач как вторичные модули, но для этого нужно явно указать уже двустороннюю связь. Именно: втом модуле, где находится спецификация, применяют так называемую заглушку, указывающую навторичный модуль, а в заголовке вторичного модуля явно указывают имя того модуля, где стоитзаглушка.
Признаком двусторонней связи служит ключевое слово separate.42Например, можно оформить как вторичный модуль тело любой процедуры из пакетауправление_сетями. Выберем процедуру "вставить" и функцию "перечень_связей". Тогда в телепакета вместо объявления этих подпрограммнужно написать заголовки видаfunction перечень_связей (узел: имя_узла)return BOOLEAN is separate;procedure вставить (узел: in имя_узла) is separate;-- перед нами две ссылки на вторичные модули,-- две заглушки.Соответствующие вторичные модули нужно оформить так:separate (управление_сетью) -- указано местонахождение заглушкиfunction перечень_связей (узел: имя_узла) return BOOLEAN is.
. . -- тело как обычноend перечень_связей;separate (управление_сетью)procedure вставить (узел: in имя_узла) is. . . -- тело как обычноend вставить;Теперь вторичные модули можно транслировать отдельно. В Аде предписан определенный(частичный) порядок раздельной трансляции. В частности, все вторичные (secondary) модулиследует транслировать после модулей с соответствующими заглушками (т.е.
после "старших"модулей, которые в свою очередь могут быть как первичными, так и вторичными)Пакеты JAVAПакет – совокупность типов, предоставляющая защиту доступа и пространство имён. Если хотитеобъединить несколько типов, нужно написать в начале файла:package <имя пакета>;Есть переменная окружения CLASSPATH.
От неё отсчитывается иерархия пакетов (сами пакеты неиерархичны, это всего лишь имена, содержащие точку, т.е. если есть пакеты X.Y и X.Z, то import X.*не подключит их). Когда есть запись вида import X.Y.Z, происходит поиск файлаCLASSPATH/X/Y/Z.jarПосле этого надо писать X.Y.Z.Class… Можно избавиться от этого, если написатьimport X.Y.Z.* или X.Y.Z.ClassC++. namespace. Пространства имён.namespace X {namespace Y {…} <===> namespace X::Y {…}}С#. Аналогично.namespace X.Y {…}X.Y.Myclass <=> using X.Y;Единица компиляции и единица дистрибуции -Понятие единицы дистрибуции характерно для промышленного программирования – единицараспространения.C++.
Файл .src – единица компиляции, .obj – дистрибуции.C#. ЕД – assembly (сборка). – .exe или .dll43Модули в интерпретируемых языкахЕдиницы дистрибуции – тексты программ (на крайняк – промежуточное представление).Python. Модуль – файл.py. У каждого – глобальное пространство имён и стандартный контекст(встроенные функции).L = [1,2,3] ---> L поместили в глобальное пр-воdef foo(): ---> foo тоже…По сути – инкрементальная трансляция (пошаговая).Экспортируется вся глобальная таблица.import <имя модуля>подгружает в текущую таблицу всю таблицу <имя модуля> (кроме начинающихся на _), т.е.
именабудут видны как <имя модуля>.<имя>from <имя модуля> import * ---> имена копируются в тек. таблицу(кроме конфликтов)Есть и пакеты – просто директория + файл __init__.py В нём прописано, что делать при загрузкепакета. Можно определить переменную __all__ – список подпакетов. Автоматически загрузятсямодули из данной директории + подпакеты из __all__Javascript. Изначально не было модулей.
Поэтому появилась сторонняя спецификация модулейпод названием CommonJS. Используется в node.jsmod.jsmodule.exports.x = 0;module.exports.foo = function(x) {return x + 1;}b.jsm = require('mod.js') ---> возвращает объект module.exportsm.x == 0m.foo(1) == 2В новом стандарте JavaScript под названием ES6 (ES2015) появилась официальная спецификациямодулей:mod.jsexport function sayHello(t) { console.log(“Hello world - ” + t); }export var value = 5;b.jsimport { sayHello, value } from ‘mod.js’sayHello(value);Обработка ошибок(аварийных ситуаций)Ошибки есть всегда!Вопросы:1. Объявление исключительных ситуаций (далее ИС).2. Возникновение ИС3. Распространение ИС4.
Реакция на ИС[Кстати! Накладные расходы на обработку ИС очень велики – в нормальной жизни не используем.]44Ада. Первый язык, в котором появились исключения (попытки были в PL/1).Вводится псевдотип exception. Вводится 6 стандартных исключений (напр., RANGE_ERROR).Правила видимости обычные. Одна операция – возбуждение.raise <имя исключения>.C++.