- •Введение
- •Введение
- •1. Сложность программного обеспечения
- •2. Объектная модель
- •2.1. Абстрагирование
- •2.2. Инкапсуляция
- •2.3. Модульность
- •2.4. Иерархичность
- •2.5. Типизация
- •2.6. Параллелизм
- •2.7. Сохраняемость
- •3. Объекты
- •3.1. Состояние
- •3.2. Поведение
- •3.3. Идентичность
- •3.4. Отношения между объектами
- •4. Классы
- •4.1. Ассоциация
- •4.2. Агрегация
- •4.3. Обобщение
- •4.3.1. Наследственная иерархия
- •4.3.2. Обобщение и типизация
- •4.3.3. Множественное наследование
- •4.4. Зависимость
- •4.5. Инстанцирование
- •4.6. Переменные и операции класса
- •4.7. Интерфейсы
- •4.8. Группирование классов
- •5. Объектно-ориентированный анализ
- •6. Основные конструкции языка uml
- •6.1. Диаграмма классов
- •6.2. Диаграмма объектов
- •6.3. Диаграммы взаимодействий
- •6.4. Диаграмма состояний
- •6.5. Диаграмма деятельности
- •Литература
- •Дополнение
- •1. Многократное использование программных систем. Основы визуального и компонентного программирования
- •2. Организация тестирования в объектно-ориентированных системах
- •Литература
1. Сложность программного обеспечения
Объектно-ориентированный подход возник в первую очередь в ответ на растущую сложность программного обеспечения. На заре компьютерной эры возможности компьютеров были ограничены и было очень трудно написать большую программу. В 60–70-е гг. эффективность применения компьютеров резко возросла, и стало все больше создаваться прикладных программ повышенной сложности. Наибольшее распространение в это время получило структурное проектирование по методу сверху вниз. Однако через некоторое время оказалось, что структурный подход не работает, если объем программы превышает приблизительно 100 тыс. строк. Как результат – выход проектов за рамки установленных сроков и бюджетов и, более того, их несоответствие начальным требованиям. Для решения этих проблем и стали применять объектно-ориентированный подход.
Справедливости ради отметим, что объектно-ориентированный подход является достаточно универсальным инструментом. Он может применяться и для разработки программ малой и средней сложности. Однако, именно для сложных систем использование объектно-ориентированного подхода является критичным. Таким образом, основной областью использования объектно-ориентированного подхода и основным объектом нашего интереса являются сложные промышленные программные продукты.
Подобные системы могут применяться для решения самых разных задач. В качестве примеров можно привести:
– системы с обратной связью (интеллектуальные, самообучающиеся системы), которые активно взаимодействуют или управляются событиями физического мира и для которых ресурсы времени и памяти ограничены;
– задачи поддержания целостности информации объемом в сотни тысяч записей при параллельном доступе к ней с обновлениями и запросами;
– системы управления и контроля над реальными процессами (например, диспетчеризация воздушного и железнодорожного транспорта).
Системы подобного типа обычно имеют большое время жизни, и большое количество пользователей оказывается в зависимости от их нормального функционирования. Глобальные системы национального или даже мирового масштаба являются яркими примерами таких систем (системы управления ядерными объектами, Интернет).
Сложность является существенной чертой промышленной программы: один разработчик практически не в состоянии охватить все аспекты такой системы. Фактически сложность промышленных программ превышает возможности интеллекта одного человека.
Сложность, присущая программному обеспечению, определяется следующими основными причинами:
– сложностью реального мира;
– сложностью управления процессом разработки;
– гибкостью программного обеспечения;
– сложностью описания поведения систем.
Сложность реального мира
Проблемы, которые мы пытаемся решить с помощью разрабатываемого программного обеспечения, часто неизбежно содержат сложные элементы, к которым предъявляется множество различных и нередко противоположных требований.
Но даже в простых проблемах сложность может возникнуть из-за языковой и понятийной "нестыковки" между заказчиком системы и ее разработчиком: пользователи обычно с трудом могут внятно объяснить разработчикам, что на самом деле нужно сделать. Часто пользователь лишь смутно представляет, что ему нужно от будущей программной системы. С другой стороны, разработчик, являясь экспертом лишь в своей области знаний, недостаточно квалифицирован в предметной области.
Дополнительные сложности возникают в результате изменения требований к программной системе уже в процессе разработки. В основном требования корректируются из-за того, что само осуществление программного проекта часто изменяет проблему. Использование системы, после того как она разработана и установлена, заставляет пользователей лучше понять и отчетливей сформулировать то, что им действительно нужно. В то же время этот процесс повышает квалификацию разработчиков в предметной области и позволяет им задавать более осмысленные вопросы, которые проясняют темные места в проектируемой системе.
Сложность управления процессом разработки
Большое число требований к системе неизбежно приводит либо к созданию нового программного продукта значительных размеров, либо к модификации существующего, что также не делает его проще. Сегодня обычными стали системы размером в десятки тысяч и даже миллионы строк на языках высокого уровня. Ни один человек не в состоянии понять и разработать полностью такую систему. Поэтому возникает необходимость разбиения системы на подсистемы и модули и коллективная разработка систем.
В идеале для успеха разработки команда разработчиков должна быть как можно меньше. Но какой бы она ни была, всегда возникнут трудности, связанные с координацией работ над проектом, и проблема взаимопонимания требований и спецификаций системы.
Гибкость программного обеспечения
Программирование обладает максимальной гибкостью среди технических наук. Программист, как и писатель, работает со словом, и всеми базовыми элементами, необходимыми для создания программ, он может обеспечить себя сам, зачастую пренебрегая уже существующими разработками. Такая гибкость – чрезвычайно привлекательное, но опасное качество: пользователь, осознав эту возможность, постоянно изменяет свои требования; разработчик увлекается украшательством своей системы во вред основному ее назначению. Поэтому программные разработки остаются очень кропотливым и "бесконечным" делом, а программные системы потенциально незавершенными.
Сложность описания поведения системы
Сложные программные системы содержат сотни и тысячи переменных, текущие значения которых в каждый момент времени описывают состояние программы. Кроме того, они имеют большое количество точек ветвления, которые определяют множество зависящих от ситуации путей решения задачи. Все это разработчик должен продумать, зафиксировать в программах, протестировать и отладить.
Любая сложная система, в том числе и сложная программная система, обладает следующими общими признаками:
1. Сложные системы часто являются иерархическими и состоят из взаимозависимых подсистем, которые, в свою очередь, также могут быть разделены на подсистемы и т.д.
Сложная система состоит не просто из отдельных компонент, между ними имеются определенные иерархические отношения.
Например, большинство персональных компьютеров состоит из одних и тех же основных элементов: системного блока, монитора, клавиатуры и манипулятора "мышь". Мы можем взять любую из этих частей и разложить ее, в свою очередь, на составляющие. Системный блок, например, содержит материнскую плату, платы оперативной памяти, центральный процессор, жесткий диск и т.д.
Продолжая, мы можем разложить на составляющие центральный процессор. Он состоит из регистров и схем управления, которые сами состоят из еще более простых деталей: диодов, транзисторов и т.д. Возникает вопрос, что же считать простейшим элементом системы? Ответ дает второй признак.
2. Выбор того, какие компоненты в данной системе считаются элементарными, относительно произволен и в большой степени оставляется на усмотрение исследователя.
Низший уровень для одного наблюдателя может оказаться достаточно высоким для другого. Если пользователю достаточно выделить системный блок, монитор и клавиатуру, то для разработчика компьютера этого явно недостаточно.
3. Внутрикомпонентная связь обычно сильнее, чем связь между компонентами.
Это обстоятельство позволяет отделять высокочастотные взаимодействия внутри компонентов от низкочастотных взаимодействий между компонентами и дает возможность относительно изолированно изучать каждую компоненту.
4. Иерархические системы обычно состоят из немногих типов подсистем, по-разному скомбинированных и организованных.
Иными словами, разные сложные системы содержат одинаковые структурные части. Эти части, в свою очередь, могут использовать общие более мелкие компоненты. Например, и у растений, и у животных имеются крупные подсистемы типа сосудистых систем, и клетки как более мелкие компоненты.
5. Любая работающая сложная система является результатом развития работавшей более простой системы.
В качестве примера назовем теорию эволюции живой природы.
Сложная система, спроектированная с нуля, вряд ли заработает. Следует начать с работающей простой системы.
В процессе развития системы объекты, первоначально рассматривавшиеся как сложные, становятся элементарными, и из них строятся более сложные системы.
