Основы объектно-ориентированного программирования - [21]
Явные интерфейсы
Четвертое правило является еще одним шагом к укреплению тоталитарного режима в обществе модулей: требуется не только, чтобы любые переговоры ограничивались лишь несколькими участниками и были немногословными; необходимо, чтобы такие переговоры были публичными и гласными!
Всякое общение двух модулей A и B между собой должно быть очевидным и отражаться в тексте A и/или B.
За этим правилом стоят критерии:
[x]. Декомпозиции и композиции. Если нужно разложить модуль на несколько подмодулей или компоновать его с другими модулями, то любая внешняя связь должна быть ясно видна.
[x]. Непрерывности. Должно быть очевидно, какие элементы могут быть затронуты возможным изменением.
[x]. Понятности. Как можно истолковывать действие модуля A, если на его поведение может косвенным образом влиять модуль B?
Одной из проблем, возникающих при применении правила Явных Интерфейсов, является то, что межмодульная связь может осуществляться не только через вызов процедуры; источником косвенной связи может быть, например, совместное использование данных (data sharing):
Рис. 3.9. Совместное использование данных
Предположим, что модуль A изменяет данные, а модуль B использует тот же элемент данных x. Тогда A и B оказываются фактически связанными через x, хотя между ними может и не быть явной взаимосвязи, например, вызова процедуры.
Скрытие информации
Правило Скрытия Информации можно сформулировать следующим образом:
Разработчик каждого модуля должен выбрать некоторое подмножество свойств модуля в качестве официальной информации о модуле, доступной авторам клиентских модулей.
Применение этого правила означает, что каждый модуль известен всем остальным (то есть разработчикам других модулей) через некоторое официальное описание, или так называемые общедоступные (public) свойства.
Конечно, таким описанием может быть весь текст модуля (текст программы, текст проекта): он и обеспечивает правильное представление о модуле, поскольку это и есть модуль! Но правило Скрытия Информации устанавливает, что в общем случае это не обязательно: описание должно включать лишь некоторые из свойств модуля. Остальные свойства должны оставаться не общедоступными, или закрытыми (секретные) (secret). Вместо терминов - общедоступные и закрытые свойства - используются также термины: экспортируемые и частные (скрытые) (private) свойства. Общедоступные свойства модуля известны также как интерфейс (interface) модуля (не следует путать с пользовательским интерфейсом системы программирования).
В основе правила Скрытия Информации лежит критерий непрерывности. Предположим, что в некотором модуле происходят изменения, касающиеся лишь его скрытых элементов и не затрагивающие общедоступных свойств; тогда на другие обращающиеся к нему модули, называемые его клиентами, эти изменения не подействуют. Чем меньше общедоступная часть, тем больше шансов на то, что изменения в модуле будут содержаться в его скрытой части.
Можно изобразить модуль, поддерживающий правило Скрытия Информации, в виде айсберга; лишь его верхушка - интерфейс - видна клиентам.
Рис. 3.10. Модуль в условиях скрытия информации
В качестве характерного примера рассмотрим процедуру поиска по ключу атрибутов, хранящихся в таблице, такой как картотека личного состава или таблица идентификаторов компилятора. Эта процедура существенно зависит от способа представления таблицы - последовательный массив или файл, хэш-таблица, двоичное или индексное (B-Tree) дерево и т.д. Скрытие информации означает, что выбранный способ реализации таблицы не влияет на использование такой процедуры. Модули-клиенты не должны страдать от каких-либо изменений в реализации программы.
Правило скрытия информации придает особое значение отделению описания функции от ее реализации, - что делает функция и как она это делает - разные вещи. Помимо критерия непрерывности, это правило связано также с критериями декомпозиции, композиции и понятности. Нельзя независимо разрабатывать модули системы, комбинировать существующие модули или понимать действие отдельных модулей, если неизвестно в точности, что каждый из них может (или не может) ожидать от других модулей.
Какие же из свойств модуля должны быть общедоступными, а какие - скрытыми? Как правило, в общедоступную часть следует включать функциональность, заданную спецификацией модуля, а все, что связано с реализацией этих функциональных возможностей, должно быть скрыто, предохраняя другие модули от последующих изменений реализации программы.
Однако эта рекомендация является нечеткой, так как не дано определение спецификации (specification) и реализации (implementation). Действительно, можно поддаться искушению, изменив определение на прямо противоположное, и утверждать, что спецификация состоит из общедоступных свойств модуля, а реализация - из его скрытых свойств! ОО-подход обеспечит намного более точные рекомендации на основе теории абстрактных типов данных.(См. лекцию 6, в частности "Абстрактные типы данных и скрытие информации".)
Для понимания смысла скрытия информации и применения этого правила должным образом, важно избежать широко распространенного неверного толкования. Несмотря на свое название, скрытие информации не означает защиты информации в смысле обеспечения секретности - запрещения авторам модулей-клиентов доступа к тексту модуля-поставщика (supplier module). На самом деле авторы модулей-клиентов имеют доступ ко всем интересующим их подробностям. В некоторых случаях было бы разумно запретить им это, но такое решение, которое, конечно, может принять руководство проекта, не следует из правила скрытия информации. Скрытие информации, как техническое требование, означает лишь, что модули-клиенты (независимо от того, разрешен ли их авторам доступ к скрытым свойствам модулей-источников) должны рассчитывать только на общедоступные свойства модуля-поставщика. Точнее говоря, должно быть невозможным создание клиентских модулей, правильное функционирование которых зависело бы от скрытой информации.