В настоящее время объектно-ориентированный подход к программированию является стандартом де-факто. Мы попытаемся проанализировать те свойства объектной модели, которые позволили ей занять лидирующую позицию в разработке ПО, и способы ее применения на практике. В данной статье приведены основные понятия объектной модели и кратко рассмотрены ее применение на разных этапах разработки ПО. В дальнейшем мы более подробно расскажем о специфике объектно-ориентированных методов спецификации, анализа и дизайна программных систем.
Что такое объектно- ориентированный подход к программированию
В сознании значительной части людей объектно-ориентированный подход к программированию ассоциируется прежде всего с языком программирования. Если проект написан на Си++, Java или Smalltalk - значит, используется объектный подход. Я бы сказал иначе: если проект пишется на Си++ или Smalltalk - значит, возможно использование объектного подхода.
Что же такое объектно-ориентированный подход к программированию? Это последовательное использование объектной модели предметной области на всех этапах разработки программного обеспечения. Ниже мы опишем основные понятия объектной модели. Эти понятия не зависят ни от языка программирования, ни от технологии разработки программных систем.
В центре объектной модели, естественно, стоит понятие объекта. Объект - это настолько общее понятие, что довольно сложно дать ему четкое и приемлемое для всех определение. Ивар Якобсон дает следующее определение: объект - это сущность, способная сохранять свое состояние (информацию) и обеспечивающая набор операций (поведение) для проверки и изменения этого состояния. Объект характеризуется набором операций и состоянием, которое сохраняет результат этих операций.
Предположим, мы разрабатываем библиотечную систему. Одним из объектов в этой системе будет читатель. Читатель характеризуется своим именем и списком книг, взятых в библиотеке. Читатель может сдать книгу или взять новую. В такой модели объект "читатель" имеет состояние описываемое, двумя атрибутами - имя (неизменяемое) и список книг (изменяемый), и совершает две операции - "сдать" и "взять". Операции соответственно изменяют список книг у данного читателя.
Целиком система будет состоять из множества объектов: читатели, книги, хранилище, библиотекарь и т. д. Эти объекты взаимодействуют между собой, посылая друг другу сообщения. Например, читатель может получить сообщение о необходимости сдать книгу (поскольку подходит к концу срок, на который она выдана) и в ответ выполнить операцию "сдать". Другим примером сообщения может быть вопрос библиотекаря к читателю: "Как Вас зовут?". Чтобы правильно отреагировать на такое сообщение, объекту "читатель" необходимо иметь операцию "назвать свое имя".
В системе обычно функционирует множество объектов одного класса. Читатели Иванов, Петров и Сидоров - экземпляры класса "читатель". Все экземпляры одного и того же класса имеют один и тот же набор операций и могут реагировать на одни и те же сообщения. Класс иногда называют типом объектов. Класс в определенном смысле соответствует понятию абстрактного типа данных, введенному в программирование довольно давно, еще в языке Модула-2.
Классы могут наследовать свойства других классов. В нашем примере два класса - "библиотекарь" и "читатель" - имеют общее. Они являются людьми, т. е. они принадлежат к классу "человек". Атрибут "имя" и операция "сказать свое имя" - свойства человека. Эти свойства унаследованы классами "библиотекарь" и "читатель" от класса "человек".
Предположим, что нашей библиотекой пользуются студенты и преподаватели университета, при этом у них немного разные права. Например, преподаватели могут одновременно брать больше книг, чем студенты. В рамках объектной модели этот факт можно отобразить следующим образом: введем два класса - "читатель-преподаватель" и "читатель-студент". Они наследуют (являются подклассами, или выведены из) класса "читатель". У них общий интерфейс - набор операций, однако действия при выполнении этих операций могут быть различны. Кроме того, при дальнейшей разработке системы нам понадобятся различные операции или атрибуты для студентов и преподавателей.
Таким образом, классы образуют иерархию, показанную на рисунке.
Различие операций "взять" и "сдать" в классах "преподаватель" и "студент" иллюстрирует еще одно важное свойство объектной модели - полиморфизм. Полиморфизм позволяет работать с неким объектом, не зная конкретного класса, к которому этот объект относится. При посылке сообщения "сдать" нам неважно, кем является данный читатель - студентом или преподавателем. Однако сама операция сдачи книг будет происходить по-разному в зависимости от того, кто этот читатель.
Объективные и субъективные проблемы большого проекта. Объектно-ориентированная модель как адекватное отображение решаемой задачи
Рассмотрим ряд типичных проблем больших проектов, которые объектно-ориентированный подход существенно упрощает.
Большая и сложная задача. Это естественно, иначе проект не был бы большим. Когда мы разрабатываем программную систему, мы разрабатываем программную модель предметной области - части реального мира. Самая большая сложность состоит в семантическом разрыве между реальностью и программой. Объектная модель уменьшает этот разрыв. Реальный мир естественно описывать как набор взаимодействующих объектов. Такое описание, с одной стороны, понятно конечному потребителю и эксперту, с другой - легко ложится на объектную модель, а следовательно, его легко реализовать.
Постоянные изменения задания. Чаще всего изменяются не сами объекты, участвующие в системе, а протоколы их взаимодействия. В этом случае основа системы остается без изменения и реализация изменений оказывается существенно проще. Если же изменения касаются какого-либо объекта, они будут локальны для данного класса.
Слишком большая длительность разработки. Объектно-ориентированный подход стимулирует многократное использование программного обеспечения. Количество существенно различных объектов не так уж и велико. Иногда можно применить имеющиеся классы в готовом виде или объекты в качестве компонентов других объектов. Механизм наследования классов позволяет использовать имеющиеся классы в качестве базовых, из которых выводятся новые, специализированные на конкретное применение. Кроме того, широкое распространение объектно-ориентированного подхода привело к огромному числу предлагаемых готовых библиотек классов, как универсального характера, так и ориентированных на различные сферы бизнеса.
Сложность сопровождения. Использование готовых, многократно проверенных классов уменьшает количество ошибок. Структура программ, основанная на объектах, отображающих объекты реального мира, уменьшает вероятность появления побочных неожиданных эффектов от изменений. Также здесь можно повторить аргументы о сравнительной простоте изменения системы.
Разумеется, все это не дается даром. При разработке системы необходимо приложить определенные усилия, особенно направленные на многократное использование кода.
И здесь опять объектная ориентация показывает свое преимущество тем, что существуют объектно-ориентированные методы для всех этапов разработки, начиная от анализа требований заказчика и кончая тестированием и поддержкой исходных текстов.
Этапы разработки и их реализация в рамках объектной модели
До появления объектной модели все шаги разработки программной системы были резко отделены друг от друга. Переход от анализа к дизайну, от дизайна к кодированию - это переход от одной модели к другой, своего рода прыжок. Такой переход требует дополнительных сил и, естественно, сопряжен с дополнительной опасностью искажения информации, внесения ошибок.
Как мы уже говорили, одним из важнейших преимуществ объектной ориентации является возможность использования одной и той же модели на всех этапах разработки. Наличие хорошо стыкующихся, а тем более одних и тех же методов анализа, дизайна и программирования упрощает весь процесс, уменьшает риск непонимания между разработчиками и тем самым ускоряет разработку и повышает качество продукта.
Анализ. Объектно-ориентированный анализ (ООА) начинается с документирования (записи) требований заказчика к системе. Важно, чтобы это описание однозначно понималось как заказчиками, так и разработчиками. Одним из наиболее широко распространенных является метод use case - метод сценариев. В нем записываются все сценарии использования будущей системы с точки зрения пользователя. Затем, на этапе анализа, эти сценарии переводят в сценарии взаимодействия объектов. Благодаря тому, что основные объекты реального мира и программной системы одни и те же, перевод будет простым и однозначным.
Существует множество методов объектно-ориентированного анализа. Пожалуй, самой интересной разработкой последнего времени является попытка создания так называемого Объединенного метода (Unitied Method). Три законодателя мод в объектно-ориентированном анализе - Grady Booch, James Rumbaugh и Ivar Jacobson - объединились под крышей компании Rational Software для того, чтобы соединить лучшее из трех ранее самостоятельных методов в один. Следует отметить, что большинство методов ООА не зависят от конкретного языка программирования. Результирующая модель одна и та же для Си++ и Smalltalk.
Дизайн. Разница между анализом и дизайном заключается в том, что в результате анализа мы описываем внешнее поведение системы, тогда как результат дизайна - спецификация того, как это поведение будет реализовано.
В объединенном методе анализ и дизайн - просто две стадии одной и той же модели с одним и тем же языком описания и одними и теми же CASE-средствами.
Уже на этапе дизайна возможно многократное использование имеющихся решений. Настоящую революцию в программировании произвело проектирование "по образцам" (Design Patterns). Образцы - это хорошо документированные, аргументированные проектные решения. Например, если в системе может существовать не более одного объекта определенного класса, можно воспользоваться образцом Singleton; если нужен объект, контролирующий доступ к другому объекту, - образцом Proxy, и т. п. Фактически образцы - это развитие понятия алгоритма, но с упором на структуру для решения определенной задачи, а не на последовательность действий.
Программирование. Наличие объектно-ориентированного дизайна существенно упрощает этап написания кода. Как мы уже отмечали, важнейшую роль играет возможность использования готовых библиотек классов. Относительная изолированность классов существенно повышает надежность тестирования.
Объектно-ориентированное программирование - не панацея
Использование самой передовой методики не гарантирует от неудач. Один из самых больших провалов в истории разработки программных комплексов - система обработки багажа в новом аэропорту города Денвера, которая задумывалась как полностью объектно-ориентированная система.
Основные проблемы объектно-ориентированной разработки - трудоемкость и сложность, особенно на начальном этапе перехода от, например, структурного программирования.
Объектно-ориентированные языки программирования сложнее процедурных. Для освоения языка Си++ требуется по крайней мере в два-три раза больше времени, чем для освоения языка Си. Библиотеки классов экономят время разработки, но опять-таки требуют времени на изучение.
Большая часть времени разработки уходит на анализ и дизайн. По многочисленным оценкам, эти стадии отнимают не менее 60% общего времени. Это часто усложняет взаимодействие с заказчиком, который хочет быть уверен, что разрабатывается именно то, что ему требуется. (На помощь приходят средства прототипирования - за недостатком места мы не можем остановиться на них подробнее.) Использование образцов дизайна требует квалификации, изучения и, следовательно, времени. То же самое относится и к методам ООА/ООД и CASE-средствам.
Тем не менее опыт показывает, что преодоление всех этих трудностей себя полностью оправдывает. Компании, переходящие на объектно-ориентированную разработку, вначале вкладывают дополнительные средства в обучение. По мере освоения новых и накопления собственного багажа проектных решений и программного обеспечения процесс разработки ускоряется и удешевляется и выгоды намного перекрывают начальные затраты.
Александр Фридман
Литература
Booch G. Object-Oriented Analisys and Design with Applications. 2nd ed. 1994.
Jacobson I. e. a. Object-Oriented Software Engineering. Addison-Wesley, 1992.
Gamma E. e. a. Design Patterns. Addison-Wesley, 1995.
FAQ.comp.objects - ftp://ftp.rtfm.mit.edu:/pub/usenet/comp.object. http://www.rational.com.