Идеология компонентно-ориентированного программирования
Invite pending
ООП-подход в разработке ПО хорошо себя зарекомендовал. Инкапсуляция, наследование и полиморфизм помогают программисту повторно использовать функциональность базового класса и скрыть детали реализации. Но при разработке сложных систем, особенно систем, моделирующих процессы окружающего мира, ООП-программист сталкивается с рядом новых проблем, для решения которых необходим принципиально иной подход.
Недостаточный контроль за безопасностью. Опасность утечек памяти. Если в языке программирования нет автоматической сборки мусора, то программист может забыть освободить память, выделенную под объект, или освободить память несколько раз.
Взаимозависимость объектов и проблема хрупкого базового класса. В изменчивых средах или в средах с непредсказуемым поведением становится сложно обеспечить надлежащее функционирование системы с помощью ограниченного набора специализированных классов. Ради небольшого изменения функциональности подчас приходится перестраивать архитектуру всей системы. При изменении базового класса могут возникнуть ошибки в работе унаследованных классов (т.н. проблема хрупкого базового класса).
Зависимость от языка программирования и платформы. Функциональность объекта записывается в виде кода шаблона объекта – класса — на некотором языке программирования. Объекты, написанные на разных языках, могут иметь свою специфику и оказаться в конечном итоге несовместимы между собой.
Высокие требования к квалификации ООП-программиста. В сложных системах, состоящих из большого числа взаимодействующих объектов, от программиста требуются высокая квалификация и большой опыт.
Сложность контроля жизненного цикла объекта. Жизненный цикл объекта начинается с вызова конструктора и заканчивается вызовом деструктора. После уничтожения объекта вся информация о его состоянии теряется. В случае необходимости сохранять состояние объекта, программисту необходимо самому реализовывать часть функциональности CRUD и контролировать жизненный цикл объекта.
Главное отличие компонента от объекта заключается в том, что компонент функционирует в среде как часть единой системы – «фреймворка». Фреймворк предоставляет унифицированный способ доступа к ресурсам среды в рамках компонентной модели. Под средой (или окружением) обычно понимается среда выполнения — вычислительное окружение, необходимое для выполнения программы. В конечном итоге компонент взаимодействует как с операционной системой/виртуальной машиной, так и с пользователем, БД, периферийными устройствами и прочими объектами реального мира, используя возможности фреймворка. В контексте жизненного цикла разработки ПО, под средой также может пониматься среда разработки, среда выполнения и т.п.
Компонент может рассматриваться как объект, к которому предъявлен ряд дополнительных требований для функционирования в сложных средах с элементами неопределенности. Базовый класс компонента должен содержать всю необходимую функциональность, которая позволяет называть компонент компонентом.
Если жизненный цикл объекта в ООП, как правило, известен заранее вплоть до мельчайших деталей еще на этапе разработки архитектуры системы, то компоненты, являющиеся частью сложной системы, могут инициировать взаимодействие друг с другом в различное время «по требованию». При этом они изначально могут ничего не знать друг о друге — на этапе написания компонента программист ограничен возможностями компонентной модели. Поэтому компоненты должны уметь динамически «обрабатывать» события и обмениваться информацией о своих свойствах и умениях с другими компонентами.
Вот некоторые особенности, в той или иной мере присущие компонентно-ориентированному программированию: интроспективность (способность компонентов к самоописанию), модульность и разграничение уровней доступа, автоматическая обработка исключительных ситуаций, автоматическое управление памятью, позднее связывание и динамический контроль типов, обработка событий, персистентность (способность компонентов сохранять и восстанавливать состояние), простота повторного использования.
Компоненты могут представлять сущности моделируемой системы, ресурсы среды (предоставлять доступ к файловой системе, базам данных), управлять рабочим потоком, предназначаться для выполнения определенных задач.
С точки зрения аспекта разработки ПО, жизненный цикл компонента обычно начинается после того, как код на некотором языке программирования скомпилирован в виде модуля (сборки) и установлен в среду проектирования.
После этого компонент готов к взаимодействию со средой проектирования и используется разработчиком на этапе проектирования целевой информационной системы.
После развертывания целевой системы компонент взаимодействует с исполняемой средой и обычно с пользователем, для которого, как правило, и предназначена спроектированная система.
Компоненты в КОП-мире функционируют не сами по себе, а в рамках системы («фреймворка»). Поэтому им необходимо иметь способ предоставлять информацию о себе, например, с помощью метаданных, и получать информацию от других компонентов системы. Метаданные могут содержать описание возможностей компонента, их доступности в каждой поддерживаемой среде и особенностей работы с ними.
В дополнение к привычным сущностям ООП мира – полям и методам, КОП предлагает новые концептуальные понятия – свойства, события, команды, модули и т.д.
Изменение внутреннего состояния компонента производится с помощью изменения соответствующих свойств.
Для реакции на события внешней среды в КОП используются обработчики событий. Могут потребоваться дополнительные способы контроля поведения компонента, реализованные в виде правил и ограничений.
Полный набор правил, описывающих взаимодействие компонентов друг с другом в рамках фреймворка, образует компонентную модель.
При переходе из одной среды в другую между жизненными циклами, компоненты должны иметь возможность где-то хранить свое состояние. Для этого от разработчика компонента может потребоваться реализация определенных интерфейсов или применение паттернов проектирования. Обычно это достигается за счет сериализуемости компонента (Serializable).
Архитектура КОП-системы построена таким образом, что компоненты не зависят друг от друга и являются взаимозаменяемыми. Архитектор может собирать требуемую систему из компонентов как из кубиков детского конструктора. В случае изменения функциональности компонента, от программиста может потребоваться перекомпилировать отдельный компонент, но не все приложение.
При этом компонент не автономен – он находится в тесном взаимодействии со средой. О среде компонент знает ровно столько, сколько ему необходимо для реализации заявленной функциональности.
В КОП принято говорить об установке компонентов, когда скомпилированные сборки, или пакеты, содержащие компоненты, устанавливаются в среду проектирования. Компоненты готовы к использованию сразу после попадания в среду.
Теоретически в КОП может и вовсе отсутствовать привычный этап компиляции. Функциональность компонента может «виртуально» существовать в базе данных или в файловой системе и загружаться или даже меняться по мере необходимости.
При сборке системы из компонентов становится возможным создавать сложные информационные системы без единой строки кода!
Управление памятью, в том числе сборка мусора, может осуществляться внутри среды автоматически или другим способом (например, благодаря иерархической организации структуры компонентов фреймворка).
Недостатки ООП и трудности, возникающие при моделировании сложных систем
Недостаточный контроль за безопасностью. Опасность утечек памяти. Если в языке программирования нет автоматической сборки мусора, то программист может забыть освободить память, выделенную под объект, или освободить память несколько раз.
Взаимозависимость объектов и проблема хрупкого базового класса. В изменчивых средах или в средах с непредсказуемым поведением становится сложно обеспечить надлежащее функционирование системы с помощью ограниченного набора специализированных классов. Ради небольшого изменения функциональности подчас приходится перестраивать архитектуру всей системы. При изменении базового класса могут возникнуть ошибки в работе унаследованных классов (т.н. проблема хрупкого базового класса).
Зависимость от языка программирования и платформы. Функциональность объекта записывается в виде кода шаблона объекта – класса — на некотором языке программирования. Объекты, написанные на разных языках, могут иметь свою специфику и оказаться в конечном итоге несовместимы между собой.
Высокие требования к квалификации ООП-программиста. В сложных системах, состоящих из большого числа взаимодействующих объектов, от программиста требуются высокая квалификация и большой опыт.
Сложность контроля жизненного цикла объекта. Жизненный цикл объекта начинается с вызова конструктора и заканчивается вызовом деструктора. После уничтожения объекта вся информация о его состоянии теряется. В случае необходимости сохранять состояние объекта, программисту необходимо самому реализовывать часть функциональности CRUD и контролировать жизненный цикл объекта.
Основные особенности КОП и отличие компонента от объекта
Компонент как объект, функционирующий в рамках сложной системы с непредсказуемым поведением и большим временем жизни
Главное отличие компонента от объекта заключается в том, что компонент функционирует в среде как часть единой системы – «фреймворка». Фреймворк предоставляет унифицированный способ доступа к ресурсам среды в рамках компонентной модели. Под средой (или окружением) обычно понимается среда выполнения — вычислительное окружение, необходимое для выполнения программы. В конечном итоге компонент взаимодействует как с операционной системой/виртуальной машиной, так и с пользователем, БД, периферийными устройствами и прочими объектами реального мира, используя возможности фреймворка. В контексте жизненного цикла разработки ПО, под средой также может пониматься среда разработки, среда выполнения и т.п.
Компонент может рассматриваться как объект, к которому предъявлен ряд дополнительных требований для функционирования в сложных средах с элементами неопределенности. Базовый класс компонента должен содержать всю необходимую функциональность, которая позволяет называть компонент компонентом.
Если жизненный цикл объекта в ООП, как правило, известен заранее вплоть до мельчайших деталей еще на этапе разработки архитектуры системы, то компоненты, являющиеся частью сложной системы, могут инициировать взаимодействие друг с другом в различное время «по требованию». При этом они изначально могут ничего не знать друг о друге — на этапе написания компонента программист ограничен возможностями компонентной модели. Поэтому компоненты должны уметь динамически «обрабатывать» события и обмениваться информацией о своих свойствах и умениях с другими компонентами.
Вот некоторые особенности, в той или иной мере присущие компонентно-ориентированному программированию: интроспективность (способность компонентов к самоописанию), модульность и разграничение уровней доступа, автоматическая обработка исключительных ситуаций, автоматическое управление памятью, позднее связывание и динамический контроль типов, обработка событий, персистентность (способность компонентов сохранять и восстанавливать состояние), простота повторного использования.
Компоненты могут представлять сущности моделируемой системы, ресурсы среды (предоставлять доступ к файловой системе, базам данных), управлять рабочим потоком, предназначаться для выполнения определенных задач.
Различные жизненные циклы и среды
С точки зрения аспекта разработки ПО, жизненный цикл компонента обычно начинается после того, как код на некотором языке программирования скомпилирован в виде модуля (сборки) и установлен в среду проектирования.
После этого компонент готов к взаимодействию со средой проектирования и используется разработчиком на этапе проектирования целевой информационной системы.
После развертывания целевой системы компонент взаимодействует с исполняемой средой и обычно с пользователем, для которого, как правило, и предназначена спроектированная система.
Способность компонента к описанию собственных свойств и умений
Компоненты в КОП-мире функционируют не сами по себе, а в рамках системы («фреймворка»). Поэтому им необходимо иметь способ предоставлять информацию о себе, например, с помощью метаданных, и получать информацию от других компонентов системы. Метаданные могут содержать описание возможностей компонента, их доступности в каждой поддерживаемой среде и особенностей работы с ними.
В дополнение к привычным сущностям ООП мира – полям и методам, КОП предлагает новые концептуальные понятия – свойства, события, команды, модули и т.д.
Изменение внутреннего состояния компонента производится с помощью изменения соответствующих свойств.
Для реакции на события внешней среды в КОП используются обработчики событий. Могут потребоваться дополнительные способы контроля поведения компонента, реализованные в виде правил и ограничений.
Полный набор правил, описывающих взаимодействие компонентов друг с другом в рамках фреймворка, образует компонентную модель.
Способность компонента сохранять и восстанавливать свое состояние
При переходе из одной среды в другую между жизненными циклами, компоненты должны иметь возможность где-то хранить свое состояние. Для этого от разработчика компонента может потребоваться реализация определенных интерфейсов или применение паттернов проектирования. Обычно это достигается за счет сериализуемости компонента (Serializable).
Способность к взаимодействию, при этом независимость компонентов друг от друга
Архитектура КОП-системы построена таким образом, что компоненты не зависят друг от друга и являются взаимозаменяемыми. Архитектор может собирать требуемую систему из компонентов как из кубиков детского конструктора. В случае изменения функциональности компонента, от программиста может потребоваться перекомпилировать отдельный компонент, но не все приложение.
При этом компонент не автономен – он находится в тесном взаимодействии со средой. О среде компонент знает ровно столько, сколько ему необходимо для реализации заявленной функциональности.
Миграция компонентов между средами вместо компиляции
В КОП принято говорить об установке компонентов, когда скомпилированные сборки, или пакеты, содержащие компоненты, устанавливаются в среду проектирования. Компоненты готовы к использованию сразу после попадания в среду.
Теоретически в КОП может и вовсе отсутствовать привычный этап компиляции. Функциональность компонента может «виртуально» существовать в базе данных или в файловой системе и загружаться или даже меняться по мере необходимости.
Дизайн вместо программирования
При сборке системы из компонентов становится возможным создавать сложные информационные системы без единой строки кода!
Безопасное управление памятью
Управление памятью, в том числе сборка мусора, может осуществляться внутри среды автоматически или другим способом (например, благодаря иерархической организации структуры компонентов фреймворка).