Наука — Школе |
В индустрии программирования технологические новшества приходят "волнами", каждая из которых проявляется как мода на новые средства и словечки (buzz-words) и длится несколько лет. Каждый раз новая порция технологий преподносится как панацея от всех бед программирования, но реальность никогда полностью не оправдывает ожиданий, хотя несомненный прогресс каждый раз налицо.
Первая такая волна пришла во второй половине 50-х
гг. и была связана с введением языков программирования высокого уровня (фортран,
кобол, лисп, алгол-60 ...).
Затем с конца 60-х началась эпоха структурного программирования, нашедшая
отражение в дизайне сначала Паскаля, а затем и Модулы-2.
В 80-е гг. все говорили об объектно-ориентированном программировании
(изобретенном еще в 60-х гг. в алголоподобном языке Симула-67).
В 90-е — о компонентно-ориентированном программировании (впервые практически
реализованном в системе Оберон Вирта и Гуткнехта в конце 80-х). В контексте Интернета эта идея трансформировалась в идею сетевых услуг (web
services).
Здесь нет возможности подробно обсуждать, что такое объектно-ориентированное программирование (ООП = OOP = object-oriented programming).
Центральным понятием здесь являются объекты (по-существу являющиеся записями в традиционной терминологии) и классы объектов (=типы записей), которые могут быть связаны отношениями наследования. Например, все односвязные списки состоят из элементов (записей), имеющих поле-указатель на следующую запись. Процедурам, работающим со списками в простейшем случае, достаточно знать только о наличии этого поля. Все типы записей, у которых кроме этого поля есть еще и другие, "содержательные" поля, можно объявить "потомками" ("расширениями") некоего общего типа-предка, у которого только и есть поле-указатель. Если написать процедуру, скажем, добавления в список нового элемента типа-предка, то она будет использовать только поле-указатель. Но такая процедура будет в принципе работать корректно, если вместо параметра типа-предка подставить любую запись любого расширенного типа-потомка. Языковый механизм, обслуживающий подобное абстрагирование, и есть механизм ООП: связь между типом-предком и типами потомками называется не вполне удачным термином наследование [inheritance], а возможность подставлять потомков вместо предка — полиморфизм [polymorphism]. Этот достаточно простой смысл ООП (изначально явный в Симуле-67) был затемнен в языках типа Smalltalk, где ему в порыве типичного энтузиастического восторга был придан универсальный статус. В частности, множественное наследование (С++ и т.п.) уже невозможно рассматривать как естественно-неизбежное развитие языковых средств — оно и приводит к большим трудностям как при реализации, так и в использовании.
Вирт включил базовые, фундаментальные механизмы ООП в Оберон, добившись его точной интеграции с остальными средствами языка.
Компонентно-ориентированное
программирование (КОП = COP = component-oriented programming)
возникло как своего рода дисциплина, т.е. набор определенных ограничений,
налагаемых на механизм ООП, когда стало ясно, что бесконтрольное использование
ООП приводит к проблемам с надежностью больших программных комплексов.
Это т.наз. проблема хрупких базовых типов
[fragile base class problem]; проблема может проявиться
при попытке изменить реализацию типа-предка, когда может оказаться, что изменить
реализацию типа-предка даже при неизменных интерфейсах его методов невозможно,
не нарушив корректность функционирования типов-потомков.
Вспоним, что структурное программирование тоже возникло как некоторая
дисциплина использования структур управления, исключающая бесконтрольные
неупорядоченные переходы управления с помощью оператора GOTO.
Можно сказать, что КОП — это такое ООП, которое подчинено требованиям безопасности "старого" структурного и модульного программирования примерно в том виде, в каком эти требования были реализованы в классической Модуле-2 (в отличие от языков типа Smalltalk, в которых ООП является основным механизмом, который применяется без ограничений).
КОП можно описать примерно такой формулой:
КОП = ООП
+ модульность (включая упрятывание
информации и позднее связывание модулей, т.е. возможность подгружать необходимые
модули в процессе выполнения программы, а не заранее, как это обычно делается в
старых системах программирования)
+ безопасность (статический контроль
типов переменных и автоматическое управление памятью)
- наследование реализации через границы модулей.
Последняя строчка означает, что в КОП запрещено наследование от типов, реализованных в других модулях; наследовать можно только абстрактным, чисто интерфейсным типам (помеченных атрибутом ABSTRACT в Компонентном Паскале).
Между прочим, Оберон-2 не удовлетворяет в полной мере требованиям КОП: в нем любой тип может
быть расширен. Это делает программы, написанные на нем, уязвимыми для
проблемы хрупких базовых классов. Именно для устранения этой "дыры" в системе
безопасности Оберона-2 и были в первую очередь предприняты модификации языка, реализованные в
Компонентном Паскале.
В классическом Обероне тоже можно расширять любой тип, но там
нет методов, так что и проблема менее остра.
Ведущим мировым специалистом по компонентному ПО является ученик Н.Вирта и со-архитектор системы Блэкбокс Клеменс Шиперский, автор мирового бестселлера (C.Szyperski "Component Software. Beyond Object-Oriented Programming", Addison Wesley Longman, 1998, 2002). Книга по сути описывает архитектурные принципы, заложенные в Блэкбокс (и Оберон), так что сам Блэкбокс является наглядным пособием по современной программной архитектуре.
Наука — Школе |