SoftCraft
разноликое программирование

Top.Mail.Ru

Объектно-ориентированный подход действительно лучше структурного


Гари Уорен Кинг (Gary Warren King)

http://www-eksl.cs.umass.edu/~gwking/whyoop.htm
Последнее обновление 22.01.1997

Перевод А. И. Легалова


Примечание: Предлагаемая Вашему вниманию статья уже успела обзавестись бородой. Однако, предпринятые в ней попытки обоснования достоинств объектного подхода представляют определенный интерес. Благодарю за ответ на призыв о потерянной ссылке. Теперь можно легко уличить меня в посредственном переводе и насладиться авторским текстом! А.Л.


Все говорят о нем, но никто его не определяет

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

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

Чем является программное обеспечение?

Что такое программирование? Н. Вирт красноречиво определяет это понятие в заголовке своей книги: Алгоритмы + Данные = Программы [Вирт85, Вирт89]. Перефразируем это по-другому: программная система - это набор механизмов для выполнения некоторых действий над некоторыми данными.

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

Что такое "качество программного обеспечения"?

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

Таблица 1.

Характеристики качества программного обеспечения

Фактор

Означает

Корректность (правильность)

Обеспечивает правильную обработку на правильных данных

Устойчивость

"Элегантно" завершает обработку ошибок

Расширяемость

Может легко адаптироваться к изменяющимся требованиям

Многократность использования

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

Совместимость

Может легко использоваться с другим программным обеспечением

Эффективность

Эффективное использование времени, компьютерной памяти, дискового пространства и т.д.

Переносимость

Можно легко перенести на другие аппаратные и программные средства

Верификация

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

Поддержка целостности

Защищает себя от неправильного обращения и неправильного употребления

Легкость использования

Для пользователя и для будущих программистов

Корректность и устойчивость

Легко спутать термины "Корректная программа" и "Устойчивая программа". Корректная программа работает, когда поданы на вход правильные данные. Она отвечает всем требованиям к спецификации данных и не терпит неудачу внутри заданного диапазона. Устойчивость подразумевает не только правильность. Устойчивая программа способна обработать ситуации, не запланированные проектом. Эти ситуации включают некорректный ввод пользователя, аппаратный отказ и ошибки во время выполнения программы. Устойчивые системы терпят неудачу элегантно, без потери критических данных. Легко увидеть, что обе характеристики необходимы для любой системы, которая будет оценена как высококачественное программное обеспечение. Если система некорректна, то она бесполезна. Если система неустойчива, то она окажется неспособной справиться с задачей в реальной ситуации.

Расширяемость

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

  • Простота проекта. Более простые проект и архитектура позволяют произвести изменения намного быстрее и легче, чем при сложном проекте.
  • Децентрализация. Разбиение сложных проблем на малые. Управляемость и независимость фрагментов, означающая, что они могут быть поделены внутри себя. Это значит, что изменения, могут быть выполнены без перекраивания других частей системы.

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

Многократность (повторность) использования и совместимость

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

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

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

Совместимость и многократное использование идут "взявшись за руки", потому что повторно используемое программное обеспечение (например, plug&play компоненты) должно быть совместимо с его новым окружением. Совместимое программное обеспечение поддерживает качество посредством использования прошлых усилий и подпорок при формировании новых систем. Программное обеспечение с низким коэффициентом совместимости требует огромных усилий, чтобы настроить систему на необходимое использование. Это усилие могло быть потрачено на проектирование лучшей системы или на улучшение эффективности кода.

Другие характеристики

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

Где структурное проектирование дает сбои

Теперь, когда мы знаем то, что ищем, когда создаем программное обеспечение, можно оценить качество работы существующих методов.

Краткий обзор нисходящего структурного проектирования

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

Нисходящая функциональная декомпозиция

Рис. 1. Пример нисходящей функциональной декомпозиции

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

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

Проблемы метода

Функциональную точку зрения трудно развивать

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

Реальные системы трудно охарактеризовать функционально

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

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

Фокусирование на функциональности теряет из виду данные

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

Функциональная ориентация производит код, менее пригодный для многократного использования

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

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

Но что сказать о библиотеках подпрограмм?

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

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

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

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

Итог по структурному проектированию

Для подведения итогов я процитирую Мейера Бертрана (Bertrand Meyer), так как вряд ли скажу лучше его:

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

Как и почему преуспевают объектно-ориентированные методы

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

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

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

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

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

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

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

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

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

Объектно-ориентированное проектирование. Резюме

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

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

Почему объектная ориентация работает

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

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

Объектная ориентация работает на более высоком уровне абстракции

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

Жизненный цикл объектно-ориентированный программы не требует никаких "прыжков"

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

Рис. 2. Каскадный ("прыжковый") подход к разработке программного обеспечения.

Данные стабильнее функций

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

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

В ходе всех этих изменений основа системы остается сравнительно постоянной. Эта основа - данные. Например, отчеты и формы для сбора данных могут изменяться со временем, но тот факт, что программное обеспечение для сбора и подготовки данных должно иметь дело с доходом, расходами, выводами, таблицами и т.д., остается незыблемым. Реляционная система управления базами данных (РСУБД) может использовать более эффективные схемы индексации или новые языки управления для доступа к данным, но тот факт, что РСУБД должна иметь дело с таблицами, индексами, схемами и соотношениями, остается неизменным. Это означает что система, сформированная на основе "структурных совокупностей, реализуемых абстрактными типами данных" (см. выше) будет способна продолжить использовать тех же самых типов данных (классов) в ходе всего жизненного цикла программы. Функциональные реализации классов изменятся, но "Инкапсуляция и сокрытие информации работают вместе, чтобы изолировать одну часть системы от других, позволяя коду быть модифицируемым и расширяемым, а ошибки можно зафиксировать без риска ввести ненужные и непреднамеренные побочные эффекты."

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

Усиление роли хороших методов программирования

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

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

Проектирование, опирающееся на данные, поддерживает многократное использование кода

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

Резюме

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

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

Литература

  1. [Буч98] Буч Г. Объектно-ориентированный анализ и проектирование с примерами приложений на C++, 2-е изд./Пер. с англ. - М.: "Издательства Бином", СПб: "Невский диалект", 1998 г. - 560 с., ил.
  2. [Вирт85] Вирт Н. Алгоритмы + структуры данных = программы. - М.: Мир, 1985.
  3. [Вирт89] Вирт Н. Алгоритмы и структуры данных. - М.: Мир, 1989.