Это старая версия документа!
Эта парадигма программирования направлена прежде всего на повышение надёжности открытых динамических систем. Суть компонентно-ориентированного программирования (далее КОП) сводится к возможности контролировать взаимодействие проектируемых и выполняемых частей программы на предмет согласованности информационных структур. Идея является относительно новой. Частично идеи КОП воплощены в такие языки как Ада, C#, прямым применением идей КОП являются языки программирования Modula-2, Оберон, Оберон-2, и наиболее известный из семейства КОП — Компонентный Паскаль.
Не смотря на свою относительную молодость — КОП имеет свои особенности, которые регулируют не только особенности языка, но и всю экосистему КОП. К таким отличительным чертам следует отнести:
Как и в функциональном программировании, в компонентно-ориентированном не только возможно, но и приветствуется использование функций и процедур. В обоих видах декомпозиции1) возможно использование функций внутри других функций2), статических и динамических переменных 3), глобальных и локальных структур. В виду явной необходимости в функциональном программировании введены такие абстракции, как например:
Ряд средств в функциональном программировании на самом деле избыточен, но другая часть действительно нужна, но это только усугубляет проблему: из-за различных эффектов характерных для функционального программирования, программисту легко потерять логику рассуждений и совершить какую-нибудь досадную ошибку, на выявление которой может уйти огромная часть времени. На практике, отладка программы и выяснение различных непонятных эффектов уходит львиная доля рабочего времени программиста. Такой язык, как Си вполне соответствует циклу «код-поиск ошибок-отладка». Мощный, как трёхлинейная винтовка, и такой же опасный — можно шутя выстрелить себе в ногу с более чем фатальными последствиями. В целом, про функциональное программирование можно сказать, что оно отлично применимо к несложным проектам, которые должны работать с высочайшей скоростью на относительно простых аппаратных платформах. Конечно, при соответствующей сноровке можно писать и сложные программы на сложном оборудовании, но стоимость такой работы будет относительно дорогой 4)
> сахар = вода + углекислый_газ + ультрафиолетНо стало ли понятней, что происходит в таком коде? Давайте взглянем на код написанный в функциональном стиле
> сахар = СинтезироватьСахар(вода, углекислый_газ, ультрафиолет)Здесь уже вполне видно, что суть сахара не равна сути воды, углекислого газа или ультрафиолета. Между этими понятиями знак равенства слегка неадекватен. В указанном примере идёт явное превращение нескольких свойств в новое свойство, более неприводимое ни к одному из предыдущих. В самом деле, запись
> вода = сахар - (углекислый_газ + ультрафиолет)в корне не верна и даже эмоционально вызывает чувство протеста. Кроме того, до сих пор идут жаркие споры, а на сколько полиморфизм вообще является частью ООП? Существует достаточное число языков программирования в которых полиморфизм есть, а объектов – нет!) Обратное утверждение также верно: существуют языки с парадигмой ООП, но в них нет перегрузки операторов. Очень спорно назвать такие языки не полностью отвечающими парадигме ООП. КОП решает проблему объектов через принятие за факт, что данные – это самостоятельная сущность – объект, а программа, по отношению к ним – является субъектом. КОП разрешает и поощряет привязку к данным разных сложных типов действий, по их обработке, и запрещает применять те действия, которые применить невозможно. Такое разделение не может быть нарушено никаким исключением, так как это – краеугольный камень компонентно-ориентированного программирования. ==== 5. Контроль во время компиляции и исполнения ==== Эти две фазы гораздо более тесно связаны, чем в случае других парадигм программирования. Так как, например C++ не гарантирует исполнения кода во всех возможных случаях, в него с неизбежностью введены лексемы, служащие для перехвата исключений. И это, в целом, плохо. Такие лексемы говорят о том, что язык не был сконструирован, а скорее сочинён. Более того, наличие инструкций перехвата управления, вовсе не гарантирует отсутствие таких эффектов как улететь в космос (неправильное исполнение программы, которое может нанести существенный ущерб целостности структур данных). В КОП нет ничего подобного. Подобные лексемы избыточны и в-общем случае – бессмысленны. В то же время, вполне возможна ситуация, когда интерфейс модуля в КОП был изменён. В такой ситуации надстройка над средой исполнения, отвечающая за состыковку различных модулей в режиме исполнения заметит несоответствие типов и запретит передачу данных между несовместимыми модулями. Это позволит своевременно остановить распространение ошибки по всей программе между модулями, которые, возможно, даже не участвовали во взаимодействии двух первых несовместимых модулей. Такое правило контроля во время исполнения приводит к важному следствию: взаимодействие между модулями происходит только с помощью базовых типов (такие как, целые числа, вещественные числа, массив литер). Во время компиляции, все задействованные модули для разработки проверяются на согласованность со вновь создаваемым модулем, а если уже существующий модуль необходимо изменить — создаётся новый (с другими интерфейсами), либо изменяется содержимое существующего модуля (с учётом возможных последствий для зависимых модулей). Так, например, решается проблема «ада динамических библиотек». Кроме того, для контроля правильности исполнения программы, введены специальные средства контроля содержимого переменных на допустимые значения — инварианты (использование таких средств считается хорошим тоном). Инварианты в КОП используются в форме предусловий (в начале участка кода), постусловий (в конце участка кода), условий (в произвольном месте кода). Различные модули в КОП, которые нужны для исполнения программы – «связываются» на этапе активации программы (или даже во время её исполнения). В отличии от КОП, в подавляющем числе других языков программирования это происходит на этапе компиляции. Такая жёстко «сшитая» программа уже не подлежит изменению, и это не редко бывает очень неудобным. ==== 6. Отличительные особенности компонентно-ориентированного программирования ==== КОП, в чём-то расширяет, а в чём-то ограничивает другие идиомы программирования. Так, поддерживается функциональный стиль, но ограничиваются сторонние эффекты. Как такого в КОП нет понятия класса, но в то же время, структуры данных, и привязанные к ним процедуры в рамках модуля — вполне описывает понятие класса в ООП. Достаточно простые исходные лексемы позволяют строить (и поощряют такое построение) код, который хорошо согласуем, сильно типизирован, может быть расширен (как через исходный код, так и через скомпилированный в машинном виде). КОП, прежде всего, нацелен на устойчивую динамичную среду. Так например, возможна ситуация в ОС Linux, когда с помощью специальных механизмов в ряде случаев можно внести исправления прямо в работающее ядро, в Компонентном Паскале – динамически заменить один работающий модуль на другой не представляет сложности (за исключением тех случаев, когда происходит взаимодействие с внешними ресурсами, которые Компонентный Паскаль контролировать, по понятным причинам, – не может). Также следует упомянуть о том, что в компилируемых языках автоматическая уборка мусора не такая простая вещь. В динамических системах потребность в сборщике мусора обязательна. По сути, операционная система сама и является таким глобальным сборщиком мусора. Обычно, программист сам должен контролировать низкоуровневые операции с памятью, так как языки программирования и операционные системы, обычно, не имеют развитых средств управления памятью (хотя, изредка и попадаются приятные исключения, например операционная система Aos, написанная на прямом родственнике Компонентного Паскаля – Активном Обероне). И здесь не нарушается принцип абстракции. Используя КОП можно построить систему, в которой уборка мусора будет выполняться автоматически и абсолютно точно. Это можно достигнуть несколькими способами, и самый доступный из них – подсчёт ссылок на структуры данных. Если модуль, который обрабатывает какую-либо структуру выгружен из памяти – очевидно, эти данные уже никто не сможет обработать). ==== 7. Примеры реализации компонентно-ориентированного программирования ==== Существует несколько языков программирования, которые следуют принципу КОП. Так или иначе, они связаны с именем Никлауса Вирта. Наиболее известные реализации можно представить в виде следующей таблицы:
Oberon | |||
---|---|---|---|
Oberon-SA | Oberon-2 | Активный Оберон | Zonnon |
Revised Oberon | Компонентный Паскаль |