Основы объектно-ориентированного программирования - [26]

Шрифт
Интервал

. Под "хакерством" здесь понимается небрежный (slipshod) подход к компоновке и модификации программы (а вовсе не несанкционированное и, конечно, недопустимое проникновение в компьютерные сети). Хакера можно считать плохим человеком, но часто намерения его чисты. Он может разглядеть полезный фрагмент программы, который почти пригоден для реализации текущих потребностей, намного превосходящих потребности, предусмотренные при первоначальной разработке программы. Вдохновленный похвальным желанием не создавать повторно то, что можно повторно использовать, наш хакер начинает модифицировать исходный текст программы, дополняя его средствами для выполнения новых задач. Конечно, такой порыв неплох, но результатом часто оказывается "засорение" программы многочисленными выражениями вида: if(этот_частный_случай) then. После нескольких повторений, возможно, осуществляемыми разными хакерами, программа начинает походить на ломоть швейцарского сыра, оставленного слишком долго на августовской жаре (безвкусность этой метафоры оправдывается тем, что она хорошо воспроизводит появление в такой программе как "дырок", так и "наростов").

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

Небольшое предупреждение: здесь не предлагается неорганизованное хакерство. В частности:

[x]. Если имеется возможность переписать исходную программу так, чтобы она, без излишнего усложнения, смогла удовлетворять потребности нескольких разновидностей клиентов, то следует это сделать.

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

Единственный Выбор

Последний из пяти принципов модульности можно считать следствием как принципа Открыт-Закрыт, так и правила Скрытия Информации.

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


>type PUBLICATION =

>record

>author, title: STRING;

>publication_year: INTEGER

>case pubtype:(book, journal, conference_proceedings) of

>book:(publisher: STRING);

>journal:(volume, issue: STRING);

>proceedings:(editor, place: STRING) -- Conference proceedings

>end


Здесь использован "тип записи с вариантами" (record type with variants) для описания наборов структур данных с полями, одни из которых (в этом примере author, title, publication_year) являются общими во всех случаях, а другие - характерны для частных вариантов данных.

Использование конкретной синтаксической конструкции здесь не является существенным. Языки программирования Algol 68 и C обеспечивают такую же возможность с помощью типа "объединение" (union). Тип union это тип T, определен как объединение ранее существовавших типов A, B,:: значение типа T это либо значение типа A, либо значение типа B,: . Достоинством типов записей с вариантами является то, что в них с каждым вариантом явно связан некоторый ярлык (tag), например book, journal, conference_proceedings.

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


>p: PUBLICATION


Чтобы с помощью p осуществлять какие-либо полезные действия, необходимо явно выделить различные случаи:


>case p of

>book:... Instructions which may access the field p.publisher...

>journal:... Instructions which may access fields p.volume, p.issue...

>proceedings:... Instructions which may access fields p.editor, p.place...

>end


Здесь оказалась удобной команда выбора case из языков Pascal и Ada; ее синтаксис воспроизводит определение типа записи с вариантами. В Fortran'е и C это может имитироваться многократным использованием команды безусловного перехода goto (switch в языке C). В этих и других языках такой же результат можно получить, используя вложенные команды условного перехода (if ... then ... elseif ... elseif ... else ... end