logo
Языки программирования

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

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

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

1. Принять от кассира место назначения заказчика и дату отправления.

2. Отобразить на терминале кассира список доступных рейсов.

3. Принять от кассира предварительный заказ на конкретный рейс.

4. Подтвердить предварительный заказ и напечатать билет.

Эти требования, естественно, находят отражение в проекте, показанном на рис. 14.1, с модулем для каждой функции и «главным» модулем, который вызывает другие.

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

Но все мы знаем, что изменение программного обеспечения чревато внесением ошибок; не устойчивый к ошибкам проект приведет к тому, что поставленная программная система будет ненадежной и неустойчивой. Вы могли бы возразить, что персонал должен воздержаться от изменения про­граммного обеспечения, но весь смысл программного обеспечения состоит в том, что это именно программное обеспечение, а значит, его можно перепро­граммировать, изменить; иначе все прикладные программы было бы эффек­тивнее «зашить» подобно программе карманного калькулятора.

Программное обеспечение можно сделать намного устойчивее к ошибкам и надежнее, если изменить основные критерии, которыми мы руководствуем­ся при проектировании. Правильнее задать вопрос: над чем работает програм­мное обеспечение? Акцент делается не на функциональных возможностях, а на внешних устройствах, внутренних структурах данных и моделях реального мира, т. е. на том, что принято называть объектами (objects). Модуль должен быть создан для каждого «объекта» и содержать все данные и операции, необ­ходимые для реализации объекта. В нашем примере мы можем выделить не­сколько объектов, как показано на рис. 14.2.

Такие внешние устройства, как дисплейный терминал и принтер, иденти­фицированы как объекты, так же как и базы данных с информацией о рейсах и предварительных заказах. Кроме того, мы выделили объект Заказчик, на­значение которого — моделировать воображаемую форму, в которую кассир вводит данные до того, как подтвержден рейс и выдан билет. Этот проект ус­тойчив к ошибкам при внесении изменений:

• Изменения, которые вносят для того, чтобы использовать разные терми­налы, могут быть ограничены объектом Терминал. Программы этого объекта отображают данные заказчика на реальный дисплей и команды клавиатуры, так что объект Заказчик не должен изменяться, а только ото­бражаться на новые аппаратные средства.

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

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

Фактически, основное различие между объектно-ориентированным и «обычным» программированием состоит в том, что в обычном программиро­вании мы ограничены встроенными абстракциями, в то время как в объектно-ориентированном мы можем определять свои собственные абстракции. На­пример, числа с плавающей точкой (см. гл. 9) — это ничто иное, как удобная абстракция сложной обработки данных на компьютере. Хорошо было бы, ес­ли бы все языки программирования содержали встроенные абстракции для каждого объекта, который нам когда-нибудь понадобится (комплексные чис­ла, рациональные числа, векторы, матрицы и т. д. и т. п.), но полезным абст­ракциям нет предела. В конечном счете, язык программирования нужно чем-то ограничить и оставить работу для программиста.

Как программист может создавать новые абстракции? Один из способов со­стоит в том, чтобы использовать соглашения кодирования и документирование («первый элемент массива — вещественная часть, а второй — мнимая часть»). С другой стороны, язык может обеспечивать такую конструкцию, как приват­ные типы в языке Ada, которая дает возможность программисту явно опреде­лить новые абстракции; эти абстракции будут компилироваться и проверять­ся точно так же, как и встроенные абстракции. ООП можно (и полезно) применять и в рамках обычных языков, но, аналогично другим идеям в про- граммировании, оно работает лучше всего, когда используются языки, кото­рые непосредственно поддерживают это понятие. Основная конструкция для поддержки ООП — абстрактный тип данных, который обсуждался в предыду­щей главе, но важно понять, что объектно-ориентированное проектирование является более общим и простирается до абстрагирования внешних уст­ройств, моделей реального мира и т. д.

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