Сложность программных систем 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Сложность программных систем



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

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

2. Системы поддержания целостности информации объемом в сотни тысяч записей при параллельном доступе к ним.

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

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

Существенная черта промышленной программы - уровень сложности: один разработчик практически не в состоянии охватить все аспекты такой программной системы. Грубо говоря, сложность промышленных программ превышает возможности человеческого интеллекта. Увы, но сложность, о которой мы говорим, по-видимому, присуща всем большим программным системам. Говоря "присуща", мы имеем в виду, что эта сложность здесь неизбежна: с ней можно справиться, но избавиться от нее нельзя. Как говорит Брукс, "сложность программного обеспечения - отнюдь не случайное его свойство".

Сложность вызывается четырьмя основными причинами:

1. Сложностью реальной предметной области, из которой исходит заказ на разработку.

2. Трудностью управления процессом разработки.

3. Необходимостью обеспечить достаточную гибкость программы.

4. Неудовлетворительными способами описания поведения больших дискретных систем.

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

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

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

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

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

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

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

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

Известно высказывание: "Чем сложнее система, тем легче ее полностью развалить". Строитель едва ли согласится расширить фундамент уже построенного 100-этажного здания. Это не просто дорого, делать такие вещи - значит напрашиваться на неприятности. Но что удивительно, пользователи программных систем, не задумываясь, ставят подобные задачи перед разработчиками. Это, утверждают они, всего лишь технический вопрос для программистов.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 

Рис. 1.1. Алгоритмическая декомпозиция

 

 

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

Рис. 1.2. Объектно-ориентированная декомпозиция

 

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

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

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

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

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

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

В 60-70-е гг. было разработано много методов, помогающих справиться с растущей сложностью программ. Наибольшее распространение получило структурное проектирование по методу сверху вниз. Метод был непосредственно основан на топологии традиционных языков высокого уровня типа FORTRAN или COBOL. В этих языках основной базовой единицей является подпрограмма, и программа в целом принимает форму дерева, в котором одни подпрограммы в процессе работы вызывают другие подпрограммы. Структурное проектирование использует именно такой подход: алгоритмическая декомпозиция применяется для разбивки большой задачи на более мелкие задачи.

Тогда же стали появляться компьютеры еще больших, поистине гигантских возможностей. Значение структурного подхода осталось прежним, но оказалось, что структурный подход не работает, если объем программы превышает приблизительно 100 000 строк.

В последнее время появились десятки методов, в большинстве которых устранены очевидные недостатки структурного проектирования. Наиболее удачные методы были разработаны Петерсом, Йеном и Цаи, а также фирмой Teledyne-Brown Engineering. Большинство этих методов представляют собой вариации на одни и те же темы. Саммервилль предлагает разделить их на три основные группы:

– метод структурного проектирования сверху вниз;

– метод потоков данных;

– объектно-ориентированное проектирование.

Примеры структурного проектирования приведены в работах Йордана и Константайна, Майерса и Пейдж-Джонса. Основы его изложены в работах Вирта, Даля, Дейкстры и Хоара. Интересный вариант структурного подхода можно найти в работе Милса, Лингера и Хевнера. В каждом из этих подходов присутствует алгоритмическая декомпозиция. Следует отметить, что большинство существующих программ написано, по-видимому, в соответствии с одним из этих методов. Тем не менее, структурный подход не позволяет выделить абстракции и обеспечить ограничение доступа к данным; он также не предоставляет достаточных средств для организации параллелизма. Структурный метод не может обеспечить создание предельно сложных систем, и он, как правило, неэффективен в объектных и объектно-ориентированных языках программирования.

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

В основе объектно-ориентированного проектирования (object-oriented design, OOD) лежит представление о том, что программную систему необходимо проектировать как совокупность взаимодействующих друг с другом объектов, рассматривая каждый объект как экземпляр определенного класса, причем классы образуют иерархию. Объектно-ориентированный подход отражает типологию новейших языков высокого уровня, таких как SmallTalk, ObjectPascal, C++, CLOS и Ada.

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

1) условные обозначения - язык для описания каждой модели;

2) процесс - правила проектирования модели;

3) инструменты - средства, которые ускоряют процесс создания моделей, и в которых уже воплощены законы их функционирования.

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

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

1) программам присуща сложность, которая нередко превосходит возможности человеческого разума;

2) задача разработчиков программных систем - создать у пользователя разрабатываемой системы иллюзию простоты;

3) сложные структуры часто принимают форму иерархий. Полезны обе иерархии: и классов, и объектов;

4) сложные системы обычно создаются на основе устойчивых промежуточных форм;

5) познавательные способности человека ограничены; можно раздвинуть их рамки, используя декомпозицию, выделение абстракций и создание иерархий;

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

7) объектно-ориентированный анализ и проектирование - метод, использующий объектную декомпозицию.

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

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

Методы структурного проектирования помогают упростить процесс разработки сложных систем за счет использования алгоритмов как готовых строительных блоков. Аналогично методы объектно-ориентированного проектирования созданы, чтобы помочь разработчикам применять мощные выразительные средства объектного и объектно-ориентированного программирования, использующего в качестве блоков классы и объекты. Но в объектной модели отражается и множество других факторов. Как показано ранее, объектный подход зарекомендовал себя как унифицирующая идея всей компьютерной науки, применимая не только в программировании, но также в проектировании интерфейса пользователя, баз данных и даже архитектуры компьютеров. Причина такой широты в тoм, что ориентация на объекты позволяет нам справляться со сложностью систем самой разной природы. Объектно-ориентированный анализ и проектирование отражают эволюционное, а не революционное развитие проектирования. Новая методология не порывает с прежними методами, а строится с учетом предшествующего опыта. Однако алгоритмическая декомпозиция помогает только до определенного предела, и обращение к объектно-ориентированной декомпозиции необходимо. Более того, при попытках использовать такие языки как C++ или Ada в качестве традиционных, алгоритмически ориентированных, мы не только теряем их внутренний потенциал - скорее всего результат будет даже хуже, чем при использовании обычных языков С и Pascal.

Унаследовав многое от предшественников, объектный подход, к сожалению, перенял и запутанную терминологию. Программист в языке Smalltalk пользуется термином метод, в C++ - термином виртуальная функция, в CLOS - обобщенная функция. В ObjectPascal используется термин приведение типов, а в языке Ada то же самое называется преобразованием типов. Чтобы уменьшить путаницу, следует определить, что является объектно-ориентированным, а что - нет.

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

С объектно-ориентированной архитектурой тесно связаны объектно-ориентированные операционные системы (ОС). Наиболее значительный вклад в объектный подход внесен объектными и объектно-ориентированными языками программирования. В 70-х гг. создан ряд языков, реализующих идею абстракции данных: Alphard, CLU, Euclid, Gypsy, Mesa и Modula. Затем методы, используемые в языках Simula и Smalltalk, были использованы в традиционных языках высокого уровня. Внесение объектно-ориентированного подхода в язык С привело к возникновению языков C++ и Objective С. На основе языка Pascal возникли ObjectPascal, Eiffel и Ada. Появились диалекты LISP, такие как Flavors, LOOPS и CLOS(Common LISP Object System), с возможностями языков Simula и Smalltalk.

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

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

□ Абстрагирование.

□ Ограничение доступа.

□ Модульность.

□ Иерархия.

Эти элементы являются главными в том смысле, что без любого из них подход не



Поделиться:


Последнее изменение этой страницы: 2017-02-08; просмотров: 2206; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.135.183.89 (0.052 с.)