ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД

ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ

 

А.Г.Иванов, А.А.Пятницкий, Ю.Е.Филинов

 

Аннотация

 

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

 

Статья написана в 1991 г., опубликована в 1993 г. в сборнике трудов ИПИ РАН.


 

ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ПОДХОД

К ТЕХНОЛОГИИ ПРОГРАММИРОВАНИЯ

 

А.Г.Иванов, А.А.Пятницкий, Ю.Е.Филинов

 

 

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

 

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

 

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

 

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

 

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

 

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

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

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

 

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

 

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

 

Возможность применения вышеуказанной схемы обеспечивают три единые для всех уровней средства: объектно-ориентированный язык, среда программирования, база данных (библиотека классов). Эти средства в явном виде составляют основу любой объектно-ориентированной технологии. Рассмотрим их основные характеристики (более полные сведения об объектно-ориентированных языках и системах можно

найти в [8, 9]).

 

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

 

Объектно-ориентированным языкам присущи следующие характеристики:

.        абстрактные типы данных;

.        скрытие реализации внешнего интерфейса (инкапсуляция);

.        наследование свойств и поведения объектов;

.        динамическое связывание имени со значением;

.        полиморфизм имен сообщений;

.        автоматическое управление памятью.


 

.... -------.......... Реальный объект (задача)
... |............................ V
... |..........---------------------------------------
... |.......... |.Анализ требований пользователя....|<-- |
... |..........---------------------------------------... |
.. Анализ........................ |....................... |
(что делать)..................... V....................... |
... |..........---------------------------------------... |
... |..........| Спецификация требований пользователя|<-- |
... |..........---------------------------------------... |
.... -------..................... V....................... |
.... -------................. Требования.................. |
... |............................ V.......................
... |.......... ---------------------------------------... |
... |.......... | Спецификации требований к программе |<-- |
... |.......... ---------------------------------------... |
Проектировние.................... |....................... |
.(как делать).................... V....................... |
... |.......... ---------------------------------------... |
... |.......... | Разработка общей схемы программы... |<-- |
... |.......... ---------------------------------------... |
... |............................ |....................... |
... |............................ V....................... |
... |.......... ---------------------------------------... |
... |.......... |. Детальная разработка программы.... |<-- |
... |.......... ---------------------------------------... |
.... ---------................... V....................... |
.... ---------.............. Спецификации................. |
... |............................ V....................... |
... |.......... ---------------------------------------... |
... |.......... |. Кодирование и отладка программы... |<-- |
... |.......... ---------------------------------------... |
Изготовление..................... |....................... |
(чем делать)..................... V....................... |
... |.......... ---------------------------------------... |
... |.......... |... Тестирование частей программы... |<-- |
... |.......... ---------------------------------------... |
... |............................ |....................... |
... |............................ V....................... |
... |.......... ---------------------------------------... |
... |.......... |... Тестирование всей программы..... |<-- |
... |.......... ---------------------------------------... |
.... ---------................... V....................... |
.... ---------............... Программа................... |
... |.................. ..........V....................... |
... |.......... ---------------------------------------... |
... |.......... |..... Использование программы....... |<-- |
... |.......... ---------------------------------------... |
Использование.................... | .......................|
(что сделано).................... V....................... |
... |.......... ---------------------------------------... |
... |.......... |.... Сопровождение программы........ |<-- |
... |.......... ---------------------------------------... |
... |............................ |....................... |
... |............................ V....................... |
... |.......... ---------------------------------------... |
... |.......... |.... Сопоставление результатов...... |... |
... |.......... |. программы с реальным объектом..... |--> |
.... -------... ---------------------------------------

Рис.1. Схема функционального процесса создания программы


Восходящее........................................... Нисходящее

направление.. ........................................направление

разработки... /...... _________________.......... \.. разработки

........... /....... /................ \........... \

......... /........ |. Реальный объект. |............ \

........ V......... |..... (задача).... |.............. V

................. /. \_________________/ \

....... ________/________............... __\___________

...... /................ \............. /............. \

..... |.. Сопоставление.. |.......... /.. Анализ тре-... \

..... |.. результатов с.. |......... |... бований........ |

..... |.. реальным объ-.. |......... |... пользователя... |

..... |.. ектом.......... |.......... \................. /

..... \____________..... /............ \...... _________/___

.... /. \__________\___/... ............\ ____/_______ /... \

.. /................ \...................... /.............. \

. |. Сопровождение... |.................... |. Спецификация.. |

. |. программы....... |.................... |. требований.... |

. |.................. |....... .............|. пользователя.. |

.. \____________..... /..................... \. _________ ___/___

./.. \__________\___/........................ /_____________/.... \

| Использование.. \......................... |..... Спецификация.. |

| программы...... | .........................|..... требований.... |

|................ |......................... |..... к программе... |

.\... __________ /......................... __\_________......... /

.. \_/_________/ \....................... /.... \________\______/

.. /.............. \................... /................. \

. |. Тестирование... \................ |..... Разработка... |

. |. всей программы. |................ |..... общей схемы.. |

. |................. |................ |..... программы.... |

.. \....... _________................. |... ___________... /

.... \_____/______/.. \................ \ _/____________\/

........ /............. \............... /............... \

...... /................. \........... /................... \

..... |.. Тестирование.... |......... |... Разработка....... |

..... |.. частей про-..... |......... |... детальной схемы.. |

..... |.. граммы.......... |......... |... программы....... /

...... \........... _______/.... ______\______........... /

........ \........ /.... /. \ ./........ \_____\________/

.......... \_____/____ /..... \................. \

............... |.. Отладка. | |. Кодирование... |

............... |........... | |................ |

................ \........... \................ /

.................. \________/.. \_____________/

 

Рис.2. Схема объектно-ориентированного процесса создания программы

 

 

Чисто объектно-ориентированные языки, такие как Smalltalk [4], Eiffel [5], обладают всеми перечисленными здесь свойствами. Широко распространены объектно-ориентированные расширения традиционных языков (Си++ [6],. Турбо-Паскаль [7]), в которых присуствуют не все объектно-ориентированные черты.

 

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

 

Классы представляют собой накопленные знания о ранее изготовленных продуктах, следовательно здесь вполне допустимо употребление термина "база знаний". База классов должна обеспечивать легкий поиск классов, их изучение, модификацию, включение новых классов. Язык и база классов объединяются в интегрированную объектно-ориентированную среду программирования (ООСП), в которой все средства поддержки процесса разработки программ написаны на данном языке и входят на равных правах в состав базы классов. Типичными примерами таких средств являются графический многооконный интерфейс с пользователем, иерархические меню, компилятор, интерпретатор, отладчик, текстовый редактор.

 

Разработка программ по объектно-ориентированной технологии сводится к созданию новых классов, их тестированию и включению в состав ООСП. Рассмотрим этот процесс подробнее, опираясь на схему 2.

 

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

 

Здесь пользователь. не связывается формальным синтаксисом объектно-ориентированного языка, но только простой семантикой: "каждому объекту соответствуют его свойства и поведение".

 

Такое описание требований пользователя не только не является процедурным по сути, но даже не функциональным, поскольку не отвечает на вопрос "что должно быть сделано?". В нем есть две части: "что дано" и "что должно быть получено". Каждая часть представлена группой объектов со своими свойствами и поведением.

 

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

 

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

 

имяОбъекта названиеДействия дополнительныеАргументы

 

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

 

ТаблицаИмен вывестиНаДиск: 'A'.

 

Здесь объекту с именем ТаблицаИмен посылается сообщение с именем вывестиНаДиск и аргументом 'A'. Приняв это сообщение, объект ТаблицаИмен записывает свое содержимое на диск 'A', причем делает это способом, скрытым от объекта, пославшего данное сообщение.

 

Еще один важный вопрос,. решаемый на этапе анализа программы - классификация объектов. Все объекты с одинаковыми свойствами и поведением объединяются в один класс, становясь при этом экземплярами последнего. Класс также является объектом с собственными свойствами и поведением. Важнейшим свойством класса является описание структуры его экземпляров, важнейшим элементом поведения - способность порождать новые экземпляры.

 

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

 

Класс может иметь как предков, так и потомков, поэтому всякой программе соответствует иерархическая древовидная или сетевая структура классов. Эта структура является неотъемлемой частью ООСП.

 

Классификация объектов необходима, во-первых, для лучшего понимания процесса решения задачи и, во-вторых, для более эффективного выполнения программы решения задачи.

 

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

 

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

 

Если при этом трудно собрать некоторый новый класс по причине го сложности или высокого уровня абстракции, вводятся дополнительные классы в качестве "моста" между проблемным классом и базовыми лассами среды (см.рис.3).

 

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

 

Свойства - это элементы внутренней структуры объекта, называемые в объектно-ориентированной терминологии "переменными экземпляра". Каждая переменная экземпляра - это в свою очередь объект некоторого другого класса, как правило расположенного в нижней части иерархии классов. В языках без строгой типизации (Smalltalk [4], SELF [10]) достаточно простого перечисления имен свойств. Классы им будут сопоставлены в программах,. реализующих поведение объекта. В языках же со строгой типизацией (Eiffel [5], Си++ [6]) при создании нового класса необходимо указать классы всех переменных экземпляра.

 

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

 

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

 


........ Классы прикладной задачи (уровни анализа)

......... -------..... -------..... -------

......... |.... |..... |.... |..... |.... |

......... |.... |..... |.... |..... |.... |.... Дополнительные

......... -------... ..-------..... -------.... классы уровней

......... /.... \..... /............ /. \........ разработки и

........ /...... \... /............ /... \....... кодирования

....... /........ \. /..... . .. . /.. .. \ .. .. .. .. .. .

... -------.... -------... .. -------..... \.............. .

... |.... |.... |.... |.. ... |.... |...... \............. .

... |.... |.... |.... |. .... |.... |....... \............ .

... -------.... ------- ..... -------........ \........... .

...... \........... \. ...... /. \..... .......\.......... .

....... \........... \...... /... \............ \......... .

........ \.......... .\.... /..... \............ \........ .

......... \........ .. \.. /....... \............ \....... .

.......... \...... .. -------..... -------... -------..... .

........... \.... ... |.... |..... |.... |... |.... |..... .

............ \.. .... |.... |..... |.... |... |.... |..... .

............. \ ..... -------..... -------... -------..... .

.............. . . . ./ . \. . . . . \ . . . . \ . . . . . .

.. .............\... /.... \......... \........ \

=================\==/=======\==========\=========\============

................. \/........ \......... \........ \

..... -------... -------... -------... -------.... \..... -------

..... |.... |... |.... |... |.... |... |.... |..... \.... |.... |

..... |.... |... |.... |... |.... |... |.... |...... \... |.... |

..... -------... -------... -------... -------....... \.. -------

......... \...... /......... /.. \........ /.......... \. ..../

.......... \.... /......... /.... \...... /............ \... /

.......... -------..... -------... -------............ -------

.......... |.... |..... |.... |... |.... |............ |.... |

.......... |.... |..... |.... |... |.... |............ |.... |

.......... -------..... -------... -------............ -------

................. \....... /........ |.... \.......... /

.................. \..... /...... ...|...... \....... /....

................ ...-------...... ...|....... -------

.............. .....|.... |......... |...... |.. ..|

............... ....|.... |......... |...... |. ...|

................ ...-------......... |...... -------

Базовые.................. \..... ....|....... /

классы ООСП ...............\........ |...... /

........................... -----------------................

........................... |.. ............|

........................... |. .............|

........................... -----------------

................ Рис.3. Иерархия классов ООСП


 

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

 

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

 

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

 

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

 

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

 

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

объектно-ориентированного языка.

 

Гибкость. Внесение изменений внутри объекта или класса совершенно не затрагивает его клиентов, т.е. тех объектов, которые его используют, разумеется, если внешний интерфейс объекта остается неизменным. Это фундаментальный принцип объектно-ориентированного программирования. Таким образом обеспечивается гибкость при программировании снизу-вверх.

 

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

 

Многие объектно-ориентированные среды (Smalltalk [4], CLOS [11]) дополнительно увеличивают гибкость программирования путем введения динамического связывания имени со значением и режима интерпретации вместо компиляции. Это замедляет скорость выполнения программ, но поддерживает так называемое экспериментальное программирование, часто используемое в системах искусственного интеллекта.

 

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


Заключение

 

В течение 1988 - 1991 гг. авторы применяли объектно-ориентированный подход при разработке программного обеспечения для персональных компьютеров: технологического модуля объектно-ориентированного программирования (ТМООП), графической объектно-ориентированной среды программирования (ГООСП) и объектно-ориентированной среды разработки специализированных словарей.

 

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

 

Объектно-ориентированные системы предъявляют повышенные требования к аппаратуре. Практика использования ТМООП на IBM PC/AT показала замедление скорости выполнения программ в 5-7 раз по сравнению с аналогичными программами на Си или Паскале. При этом время получения готовой программы сократилось в 2-3 раза, программы стали выглядеть яснее, лучше приспособлены для повторного использования.

 

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

 

ЛИТЕРАТУРА

 

1. Фокс Дж. Программное обеспечение и его разработка. М.:Мир, 1985. - 368 с.

2. Лисков Б., Гатэг Дж. Использование абстракций и спецификаций при разработке программ: Пер. с англ. - М.: Мир, 1989. - 424 с.

3. Jackson M.-A. A Program Design. Academic Press, 1985.

4. Goldberg A.,. Robson D.. Smalltalk-80: The Language and its Implementation. Addison-Wesley, 1983.

5. Meyer. D.. Genericity. versus. Inheritance.. In. OOPSLA'86, SIGPLAN Notices, v.21, n.11, 1986, pp. 391-405.

6. Stroustrup D. The C++ Programming Language. Addison-Wesley, 1986.

7. Borlang Turbo-Pascal v.6.0. Borland Inc, 1990.

8. Иванов А.Г., Карпова А.В., Семик В.П., Филинов Ю.Е. Объектно-ориентированная среда программирования. Системы и средства информатики. Вып.2. М.: Наука, 1991.

9. Программирование. Специальный выпуск по объектно-ориентированному программированию. N 6, 1990.

10. Chambers C., Ungar D., Lee E. An Efficient Implementation of SELF, a Dynamically-Typed Object-Oriented Language Based on Prototypes. In OOPSLA'89, SIGPLAN Notices, v. 24, n.10, 1989, pp. 49-70.

11. Bobrow D.G. et al. Common Lisp Object System Specification. SIGPLAN Notices, v.23, n.9, 1988.