Научная статья на тему 'Эволюция идей объектно-ориентированных технологий'

Эволюция идей объектно-ориентированных технологий Текст научной статьи по специальности «Компьютерные и информационные науки»

CC BY
248
76
i Надоели баннеры? Вы всегда можете отключить рекламу.
i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

Текст научной работы на тему «Эволюция идей объектно-ориентированных технологий»

УДК 004.432

ЭВОЛЮЦИЯ ИДЕЙ ОБЪЕКТНО-ОРИЕНТИРОВАННЫХ ТЕХНОЛОГИЙ1

Добряк Павел Вадимович, к.т.н., Уральский Федеральный Университет,

Россия, Екатеринбург, goodsoul@mail.ru

Объектно-ориентированные технологии лидируют сегодня при разработке программного обеспечения. Большинство технологий являются в той или иной степени объектно-ориентированными, их создатели часто заявляют об «объектной ориентации» в рекламных целях. Полезно проанализировать технологии не с той точки зрения, в какой степени они являются объектно-ориентированными, а чтобы проследить, как развиваются в них идеи объектно-ориентированной парадигмы; показать, что под объектноориентированными языками скрывается несколько, вообще говоря, разных стилей программирования; обратить внимание на идеи, которые находятся пока на обочине без реализации в лидирующем семействе языков С++, Java, C#, но могут быть востребованными; и сделать прогнозы.

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

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

2. инкапсуляция - совместное определение данных и кода внутри одной языковой конструкции;

3. полиморфизм - способность одного и того же кода описывать объекты разной природы.

К дополнительным принципам можно отнести:

1. наследование (фактически - способность одного описания пользоваться другим как самим собой без повторного кодирования; тесно связано с полиморфизмом);

2. агрегация (вложенные объекты).

Посмотрим, как эти принципы приводят к разным стилям программирования, проанализировав программы.

Изначально программа на объектно-ориентированном языке должна была представлять собой множество объектов, обменивающихся сообщениями. То есть классы, вообще говоря, необязательны (иногда такие «бесклассовые» технологии называют не объектноориентированными, а объектными). Уже на Smalltalk [1] обмен сообщениями маскируется под вызов методов. Программа на C++ представляет собой объекты - экземпляры классов, организованных в иерархию наследования, вызывающие друг у друга свойства и методы (уже довольно далеко от «объектов, обменивающихся сообщениями»!).

Объектно-ориентированные языки из экзотики стали обыденностью при появлении графического пользовательского интерфейса. Элементы оконного интерфейса (кнопки, формы и прочее) очень удобно описывать в виде объектов со свойствами и методами. При этом ООП поглотило другую парадигму - событийную (программисты, переходящие с С++ Builder на Visual C++ с удивлением видели в своем коде таблицы событий, которые в Visual C++ открыты для программиста, и учились не обращать на них внимание). События и сообщения - родственные механизмы. Только, если у сообщения есть адресат, то событие генерируется «в эфир» и у него есть подписчики (которых может быть много), которые реагируют на это событие. Событие само может быть описано как объект. Изменяется само понятие объекта как совокупности свойств и методов. Заодно добавляются внутренние

1 Статья рекомендована к опубликованию в журнале "Информационные технологии и вычислительные системы"

10

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

Распределенные приложения и технологии повторного использования кода также обогатили идеями ООП. По аналогии с компьютерами, построенными по магистральномодульному принципу, когда различные компоненты взаимозаменяемы и могут соединяться в разных конфигурациях, в ООП пришло понятие интерфейса - класса без полей, целиком состоящего из абстрактных (не реализованных) методов. Объекты могут взаимодействовать, если есть интерфейсы, который они реализуют. То есть класс, к экземпляру которого обращается другой объект, наследует интерфейс, обязательно определяя каждый метод интерфейса. Программа представляет собой классы, организованные в иерархию наследования и реализующие интерфейсы, экземпляры которых вызывают друг у друга свойства и методы, генерируют и подписываются на события. При этом нужно обратить внимание на то, что принцип инкапсуляции несколько нарушается. Если мы до этого данные и код, который их обрабатывает, описывали вместе внутри класса, то теперь, группируя методы в интерфейс, мы удаляем методы от класса на «некоторое расстояние». Назовем эту проблему «вечным дуализмом данных и кода». С одной стороны, у программистов есть стремление для усиления ясности и простоты отделить данные и код, с другой стороны, есть потребность в манипулировании кодом, как данными (например, в эволюционных алгоритмах). В Lisp [2] переменных нет вообще, в то же время есть обозначения. К этой проблеме мы еще вернемся.

Такие технологии, как CORBA и ActiveX [3], также изменили понятие объекта. Если рассматривать DLL (предка ActiveX) как множество функций, откомпилированных и повторно используемых, то откомпилированный и повторно используемый объект -компонент - делает программирование более изощренным. Компонент может быть активным, он сам может вызывать что-нибудь из контейнера. Значит, необходимы события. Для удобства программист может добавить свойства и методы откомпилированному компоненту (расширенные свойства и методы). Фактически объявленные внутри контейнера, расширенные свойства и методы вызываются у компонента, как если бы они были настоящими свойствами и методами компонента. Кроме того, компонент может потребовать, чтобы контейнер предоставил ему доступ к ряду свойств контейнера, называемых свойствами окружения (например, когда компонент хочет подстроиться по цвету и шрифту к контейнеру). Расширенные методы появляются в С# для несколько другой задачи - более короткой записи вызова цепочки методов, что затем применяется в LINQ [4]. Если в C# добавить слово this у аргумента функции в её сигнатуре, то мы сможем у объекта класса, к которому принадлежит аргумент, вызвать этот метод, как будто это собственный метод этого класса. Получается, что метод как будто «отсоединился» от класса и стал принадлежать нескольким классам. Это еще один случай «вечного дуализма данных и кода» (похожая ситуация в языке CLOS [2], там классы и методы понимаются не так, как в языке C++, метод - отдельная от класса сущность).

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

11

90-е годы стали временем интеграции трех ответвлений отрасли ИТ: программирования на языках ООП, баз данных и систем искусственного интеллекта. Эта интеграция не закончилась до сих пор, порождая множество идей. Так, например, объектное расширение Lisp - CLOS, содержит идеи, отсутствующие пока в языках семейства C++ (рассмотрим их ниже). В реляционные базы данных добавились методы, связи наследования и агрегации (получились объектно-реляционные базы данных). В языки программирования добавились перманентность (персистентность) объектов [5] - способность объекта сохранять свое состояние между запусками программы, а впоследствии транзакции и триггеры (получились объектно-ориентированные базы данных). Разновидностью триггеров можно считать конструкторы и деструкторы.

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

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

До сих пор мы определяли объект через его составные части - свойства, методы, события и пр. Можно взглянуть на объекты по их разновидностям. Часто в литературе по C++ написано, что объект - это экземпляр класса или класс. Является ли класс полноценным объектом? Нет, во всяком случае, не в языках семейства C++. Проведем анализ на основе C++. У класса нет свойств и методов (хотя статические свойства и методы можно считать свойствами и методами класса). Не существует полноценных указателей на класс, хотя много суррогатов указателей - шаблоны и идентификаторы класса в ActiveX (можно спорить, нужны ли вообще указатели и их заменители). Нет операций над классами, хотя множественное наследование можно рассматривать как сумму классов-предков. У класса нет своего класса, к которому он мог бы принадлежать (то есть метакласса). Служебные метаклассы есть в Smalltalk. Полноценные многоуровневые метаклассы, создаваемые программистом, есть в языке CLOS.

Полноценные метаклассы переносят нас из двумерного мышления (наследование, агрегация) к трехмерному (наследование, агрегация, метаклассы). Это более трудное мышление. Может быть, поэтому метаклассы плохо приживаются в языках программирования. Пример трехмерного мышления: бакалавр -> студент -> человек

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

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

12

языках семейства C++ нет. В языке CLOS у методов стоят модификаторы before, after и around - куда поставить метод: в начало, конец или даже вокруг. Результирующий метод собирается из всех методов по цепочке наследования в зависимости от модификаторов расположения.

До сих пор идут споры, нужно ли полноценное множественное наследование [7,8] (разработчики Java и C# убрали полноценное множественное наследование). Противники говорят о том, что множественное наследование на практике порождает большое количество проблем при совпадении имен, сторонники - что есть предметные области, особенно в системах искусственного интеллекта, когда без множественного наследования не обойтись. Но можно придумать и более сложные виды наследования. Использование и переопределение свойств и методов не обязательно должно быть иерархическим, теоретически, оно может быть и циклическим.

Бывают случаи, когда мы не можем четко сказать, использовать наследование или агрегацию. Это происходит тогда, когда часть подобна целому. Например, административнотерриториальное деление: страна состоит из областей, но структурно области подобны стране (столица, площадь, количество населения - свойства те же). Особая семантика для гибридных связей наследования и агрегации есть в проекте Orion [5].

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

Интерпретаторы и виртуальные машины позволяют разработчикам языков делать программы более гибкими - изменять структуру классов во время выполнения программы. На С# можно добавлять в класс новые свойства и методы или создавать новый класс во время выполнения программы. Для реализации функционального программирования в С# введены деревья решений (формулы можно представить в виде объектов, «замораживать» их выполнение, изменять и компилировать - пример «вечного дуализма данных и кода»). Язык тем более объектно-ориентирован, чем большее количество элементов представляют собой объекты. В языке Smalltalk, считающимся наиболее чистым объектно-ориентированным языком, структурные операторы являются методами у служебных классов, например, оператор условия - метод у объекта истина. Можно сформулировать идею, что программа и её части - это тоже объекты. Таким образом, объектами будут классы и их экземпляры, события, связи между классами и части программы.

В 21 веке понятия класса разработчикам информационных систем стало явно не хватать. Группа разработчиков, называемая «бандой четырех», выявила стандартные ситуации при объектно-ориентированном проектировании - паттерны проектирования -конфигурации классов, часто встречающиеся при разработке [9]. Впоследствии ряд паттернов был встроен в языки на уровне синтаксических конструкций. Например, паттерн синглтон (требование единственности экземпляра класса), был встроен в С#. Развитием концепций сообщений и событий являются паттерны «команда», «наблюдатель» и «цепочка обязанностей», можно предположить, что в будущем появятся языковые конструкции, их реализующие.

В языке BETA [10] есть интересная конструкция, являющаяся обобщением понятий «класс» и «функция», также названная паттерном (еще один пример «вечного дуализма данных и кода»). Программисты на языках семейства С++ привыкли к различиям между функциями и классами, не замечая, что между этими понятиями сходства больше, чем

13

различий. Так, статические поля функции можно считать свойствами, вызову функции соответствует вызов конструктора класса. Осталось только добавить полям функции модификаторы доступа и экземпляризацию функции, и получится класс. Между паттернами объектно-ориентированного проектирования и паттернами языка BETA есть родство, если паттерны проектирования рассматривать не как стандартные ситуации, а как конфигурации классов. Интересно то, что, находясь в объектно-ориентированной парадигме, мы отошли от самого понятия «объект» и перешли к понятию паттерн.

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

Если к предыдущим идеям добавить паттерны, то программы будут представлять собой динамические сети паттернов (формирующихся на основе нескольких описаний) внутри других сетей, обменивающихся сообщениями и генерирущих события (тоже считающиеся паттернами), при этом код программы также представляет собой паттерны. Это программирование, в котором иерархии заменяются сетями, что приводит к совсем другому взгляду на программы [11]. Этот переход (от иерархий к сетям) соответствует сдвигу парадигм в разных отраслях науки, например - в экологии, экономике и квантовой физике [12].

Когда мы говорим об объектно-ориентированных языках, нужно обязательно обратить внимание на то, что распространенные языки являются мультипарадигменными, что не удивительно (например, формулы удобно писать на математическом языке, а не предикатами Пролога). При распространении ООП объектные надстройки появились над самыми разными языками, например, над Lisp. В C++ можно выделить четыре уровня: математические и логические формулы, структурное программирование, функции, классы. По всей видимости, объектно-ориентированная надстройка не всегда будет верхним уровнем. Уже сейчас при программировании Интернет-страничек код на языках высокого уровня обрамляется тегами. В С# встраивается функциональное программирование и декларативное программирование LINQ. «Матрешка» вложенных друг в друга парадигм заменяется перетеканием одной парадигмы в другую. Конструкции одного стиля встраиваются внутрь другого. Совсем не обязательно, что ООП сохранит свое «привилегированное» положение верхнего уровня в мультипарадигменном программировании.

Литература

1. Кирютенко Ю.А., Савельев В.А. Незнакомый Smalltalk. Ростовский государственный университет, 1997.

2. Jeff Dalton. A Brief Guide to CLOS. http://www.aiai.ed.ac.uk/~jeff/clos-guide.html

3. Деннинг А. ActiveX для профессионалов - СПб: Питер, 1998. - 624 с.: ил.

4. Трей Нэш. C# 2010. Ускоренный курс для профессионалов - Издательство: Вильямс, 2010 г.

5. Кузнецов С. Объектно-ориентированные базы данных - основные концепции, организация и управление: краткий обзор. http://www.citforum.ru/database/articles/art_24.shtml

6. М. Минский. Фреймы для представления знаний. М.: Мир, 1979.

7. Легалов А. О стрельбе по множественному наследованию. // Открытые системы №5-6, 2001 г.

8. Труб И. О проблемах множественного наследования. // Открытые системы №2, 2001 г.

9. Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования. Издательство: Питер, 2007 г.

10. Ole Lehrmann Madsen, Birger M0ller-Pedersen, Kristen Nygaard. Object-Oriented Programming in the BETA Programming Language. Addison-Wesley, June 1993, ISBN 0-201-62430-3, 350 pages

14

11. Люри Дж., Мансур Ш. Преодоление иерархий. //Открытые системы, 24.10.2001.

12. Добряк П.В., Калмыков А.А. Альтернативный подход по организации структур данных в объектно-ориентированных языках. Практика приборостроения №4[9], 2004. - с. 76 - 79.

УДК 004.4

ПРИМЕНЕНИЕ РАСПРЕДЕЛЕННЫХ СИСТЕМ УПРАВЛЕНИЯ В

ПРОМЫШЛЕННОСТИ

Лучкин Николай Анатольевич, аспирант, Омский государственный технический университет,

Россия, Омск, niko1a.v.1iichkin@gmail.com

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

На сегодняшний день в области автоматизации промышленных предприятий выпускается все больше необходимого оборудования для проектирования распределенных систем управления (РСУ), которые внедряются на предприятиях разного направления вида производства. Первые РСУ были представлены на рынок в 1975 г. компаниями Honeywell (система TDC 2000) и Yokogawa (система CENTUM). Системы TDC-3000 были усовершенствованы и по настоящее время успешно эксплуатируются на предприятиях энергетической, металлургической, газовой промышленности по транспортировке и переработке газа, нефти и нефтепродуктов, целлюлозно-бумажной промышленности и др.

Основными современными на сегодняшний день распределенными системами управления являются следующие:

■ ABB System 800xA

■ CONTRONIC Hartmann-Braun

■ Damatic XDi Valmet Automation

■ Emerson DeltaV

■ Honeywell Experion PKS

■ Invensys Foxboro I/A Series

■ Siemens SIMATIC PCS7

■ Yokogawa CENTUM CS 3000

Современные распределенные системы управления эксплуатируются на базе:

■ промышленных рабочих станций;

■ многоканальных контроллеров;

■ станций распределенного ввода/вывода;

■ открытых промышленных сетей (Industrial Ethernet, Profibus, Modbus и др.);

■ интеллектуальных устройств ввода/вывода;

■ беспроводных устройств передачи информации;

■ WEB-технологии передачи данными.

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

В зависимости от количества поставленных решаемых задач информационная емкость системы включает в себя различное число каналов ввода/вывода, способных обрабатывать от сотен до десятков тысяч сигналов. Для осуществления приема, хранения и обработки больших объемов параметров (информации) применяются базы данных реального времени (БДРВ) - реляционные, иерархические, объектно-ориентированные. Сервер БДРВ является ядром интегрированной системы управления, обеспечивая тем самым форматирование массивов данных, поступающих от технологического процесса для последующего их анализа и применения на верхнем уровне управления производством. БДРВ должна обеспечивать

15

i Надоели баннеры? Вы всегда можете отключить рекламу.