Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


Основы объектно-ориентированной технологии программирования

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

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

Принцип управления сложными системами известен еще со времен Древнего Рима - divide et impera (разделяй и властвуй). При проектировании сложных программных систем необходимо ее разделять на все меньшие и меньшие подсистемы, каждую из которых можно создать и совершенствовать независимо. Такой процесс называется декомпозиция.

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

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

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

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

Технология программирования - это набор правил, приемов и методов, которые помогут программисту представить себе реальные вещи абстрактными, чтобы затем "запечателеть" их в тексте на каком-либо языке программирования. Формализовать, описать и промоделировать процессы и явления реального мира. Парадигма - набор правил и принципов для анализа явления или задачи, проектирования программы и непосредственно ее реализации на языке. Парадигма - это "взгляд на мир".

Объектно-ориентированная парадигма

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

Объектно-ориентированный анализ выполняется на основе определенного набора принципов:

  1. Абстракция - формирование представления о свойствах и поведении предмета путем выделения существенных характеристик, отличающих его от других видов объектов, путем мысленного удаления несущественных частностей. Анализируется внешнее поведение объекта (интерфейс и интерфейсные функции). Абстракция - вещь полезная, но обычно число абстракций (объектов) намного превышает наши умственные возможности.
  2. Инкапсуляция - сокрытие внутреннего устройства, реализации объекта. В итоге объект как "черный ящик". Дополняет абстрагирование направленностью внутрь объекта. Инкапсуляция - главное средство для борьбы со сложностью системы. Для уменьшения количества абстракций и упрощения работы с ними убирает из поля зрения внутреннее содержание абстракции.
  3. Модульность - связанность набора объектов для решения задачи. Разбить моделируемое явление на объекты, но все-таки объекты взаимодействуют друг с другом, связанность. Модульность упрощает задачу объединяя логически связанные абстракции в группы.
  4. Сохраняемость - возможность объекта сохранять информацию о своем состоянии, а затем при необходимости восстанавливать его.
  5. Параллелизм - организация жизни и взаимодействия объектов.
  6. Наследование (иерархия) - такое отношение между классами, когда один объект заимствует структурную и функциональную часть другого. Таким образом создается иерархия объектов, где на более высоком уровне - более абстрактные объекты, а на более низких уровнях - более конкретные, с более частными свойствами. Наследование резко упрощает задачу позволяя использовать уже созданные и проверенные объекты для наделения их более конкретными свойствами.
  7. Полиморфизм (типизация) - позволяет проводить моделирование в терминах области моделирования. Объект и тип данных понятия взаимозаменяемые. Полиморфизм резко упрощает задачу позволяя использовать привычные термины, типы данных, операторы, одноименные функции.

Абстракция

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

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

  • все предметы в этом множестве имеют один и тот же набор характеристик;
  • все предметы подчинены и согласовываются с одним и тем же набором правил, нормами поведения, законами природы.

ОБЪЕКТ =
= набор характеристик (описывающих свойства предметов реального мира) +
+ набор правил поведения (реакция на воздействие)

Когда выявлена сущность (смысл, семантика) объекта в модели, он должен быть назван уникальным именем. В зависимости от моделируемой области реального мира по своей сущности могут быть выявлены следующие виды объектов:

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

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

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

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

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

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

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

ЛИНЗА
R1
R2
d
D
ID
ID_OS

Типы атрибутов:

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

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

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

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

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

Таким образом, динамическая абстракция объекта - это его поведение. И только вместе атрибуты и правила поведения определяют объект. Каков бы ни был объект, его поведение определяется его состоянием. А состояние в свою очередь "историей", то есть последовательностью совершенных над объектом действий.

По аналогии с естественным языком:

ОБЪЕКТ (существительное) =
АТРИБУТЫ
(прилагательные) +
+ ПОВЕДЕНИЕ
(глаголы только в поаелительном наклонении: сделай это! сделай то!)

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

  • КОНСТРУКТОР - операция создания объекта и инициализации его атрибутов
  • ДЕСТРУКТОР - операция, освобождающая используемые объектом ресурсы и разрушающая его.
  • МОДИФИКАТОР - операция, которая изменяет состояние объекта (clear, pop, push, remove, set т.п.).
  • СЕЛЕКТОР - операция, считывающая состояние объекта, но не меняющая (length, height, width, isEmpty, getX, getY и т.п.)
  • ИТЕРАТОР - операция, позволяющая организовать доступ ко всем частям объекта в строго определенной последовательности (first, last, next, previous и т.п.)
  • УТИЛИТА - операция высокого уровня выполняющая те или иные действия в зависимости от сущности объекта (raytrace)

Таким образом,

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

Инкапсуляция - дополняет принципы абстракции. Инкапсуляция используется на первых же шагах при проектировании и программировании. Все что описывает объект и его поведение заключается как бы в капсулу (“черный ящик”). На диаграмме класса "капсулу" символизирует прямоугольник, в который заключаются атрибуты и методы. В языке С++ "капсулу" символизируют скобки

class ИМЯ
{
private:
    ...
protected:
    ...
public:
    ...
}

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

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

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

В языках программирования модульность поддерживатеся по-разному. В языке С++ модулями являются раздельно компилируемые файлы. Описание классов принято размещать в отдельных заголовочных файлах (с расширением .h), а реализацию - отдельно в файлах с расширением .cpp. Связь между файлами осуществляется с использованием директивы препроцессору #include.

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

Т.о. модульность способствует сокращению времени компиляции и повторному использованию кода, работе в команде. Модульность дополняет абстракцию и инкапсуляцию в процессе практической реализации.

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

void Lens::write(ostream& out) const
{
    cout<<m_R1<<m_R2<<m_d<<m_D<<m_n;
}
void Lens::read(istream& in)
{
    cin>>m_R1>>m_R2>>m_d>>m_D>>m_n;
}

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