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

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

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

Вопрос. Когда полезна такая спецификация?

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

НЕ нашли? Не то? Что вы ищете?

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

Вопрос. Зачем могут понадобиться такие спецификации?

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

3.2. Связывание

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

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

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

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

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

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

По-видимому, все эти примеры хорошо известны. Но общая концепция связывания способна привести и к совершенно новому понятию, отсутствующему в традиционных ЯП.

3.3. От связывания к пакету

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

Рассмотрим подробнее путь к пакету на конкретном примере.

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

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

Как уже сказано, впервые нужная абстракция была осознана и оформлена соответствующим конструктом в языке Симула-67. Основная идея в том, что совокупность объявлений можно синтаксически оформить (в качестве "класса"), предварив их ключевым словом class и снабдив индивидуальным именем. Так можно получить, например, класс с именем обработка_строк, в котором будут объявлены одномерный массив и процедуры для работы с этим массивом как со строкой символов. Чтобы воспользоваться такими объявлениями (в совокупности!), достаточно перед началом программы указать в качестве приставки имя нужного класса. Объявления из такого класса считаются выписанными в фиктивном блоке, объемлющем создаваемую программу (т. е. доступны в ней). Например, программу нормального алгоритма достаточно предварить приставкой обработка_строк.

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

Вопрос. Чем идея пакета (модуля-контекста) отличается от идеи простого копирования контекста? От идеи макроопределений?

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

3.4. Связывание и специализация

Не только отдельные языковые конструкты обязаны своим возникновением тому, что связывание было осознано как самостоятельная абстракция. На его основе возникло целое направление в программировании - так называемое конкретизирующее программирование (как было отмечено, связывание обобщает основные виды конкретизации). Когда говорят о конкретизирующем программировании, часто приводят такой пример.

Рассмотрим операцию "**" возведения основания х в степень n. Если понятно самостоятельное значение связывания, то легко представить себе ситуацию, когда с операцией "**" уже связан один операнд и еще не связан другой. С точки зрения итогового возведения в степень такая ситуация запрещена - еще нельзя совершить запланированный акт поведения (операнды не готовы). Но если понимать связывание как многоэтапный процесс подготовки этого акта, то рассматриваемая ситуация может соответствовать одному из этапов этого процесса. Более того, на аналогичном этапе связывания могут задерживаться целые классы таких процессов. Это повторяющееся следует выделить, обозначить и применить (пользуемся одним из важнейших общих принципов абстрагирования - принципом обозначения повторяющегося). Так получается целый ряд одноместных операций ("1**","2**","3**"...) при фиксированном основании и ряд одноместных операций ("**1","**2","**3"...) при фиксированном показателе степени. Но, например, операцию "**3" можно реализовать просто как х*х*х, что короче, проще и эффективней общей программы для "**".

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24