Платформа Eclipse
Правила применения API
Версия 0.15 - Последнее исправление: 30 мая 2001 года, 12:00
В этом разделе рассмотрены правила применения клиентов API платформы Eclipse (и другие
компоненты).
Что такое API
Платформа Eclipse определяет элементы API, применяемые клиентами (независимыми производителями
программного обеспечения, разрабатывающими модули). В свою очередь модули
могут определять элементы API для собственных клиентов и т.д. Элементы API представляют
собой внешний интерфейс: они содержат спецификацию их предназначения и способа
применения. Для элементов API предоставляется поддержка: группа разработки платформы
Eclipse устранит ошибки реализации в случае отклонений от указанного алгоритма работы. Поскольку
обработка изменений API может быть связана с затруднениями, группа разработки платформы
Eclipse попытается эффективно расширить элементы API в последующих выпусках.
Каким образом определить API
По своей природе элементы API предусматривают наличие документации и спецификации.
Это отличает их от прочих элементов, описывающих внутреннюю
реализацию без опубликованной документации или спецификации. Таким образом, если вам не
удалось найти документацию по какому-либо элементу, с большой вероятностью можно
утверждать, что он не связан с API.
Для более четкого разграничения исходный код платформы разделен на пакеты API и
прочие пакеты. Все элементы API объявлены в соответствующих пакетах API.
-
Пакет API - это пакет Java, в состав которого входит по крайней мере один класс
или интерфейс API. Имена пакетов API приведены в документации по соответствующему
компоненту; как правило, в именах прочих пакетов, описывающих подробности
реализации, указано слово "internal". Имена пакетов API разрешено указывать к исходном
коде клиентов. Ниже перечислены пакеты, предусмотренные для платформы Eclipse:
-
org.eclipse.foo.* - например, org.eclipse.swt.widgets,
org.eclipse.ui или org.eclipse.core.runtime
-
org.eclipse.foo.internal.* - не API; пакеты с описанием внутренней реализации
-
org.eclipse.foo.examples.* - не API; примеры
-
org.eclipse.foo.tests.* - не API; комплекты тестирования
-
Класс или интерфейс API - класс или интерфейс типа public, входящий в
состав пакета API, либо класс или интерфейс public или protected,
объявленный в другом классе или интерфейсе API, либо наследованный из них.
Имена классов API разрешено указывать в исходном коде клиентов.
-
Метод или конструктор API - метод или конструктор типа public или
protected, объявленный в классе или интерфейсе API, либо наследованный из
них.
Имена методов API разрешено указывать к исходном коде клиентов.
-
Поле API - поле типа public или protected, объявленное в классе или
интерфейсе API, либо наследованное из них. Имена полей API разрешено указывать в
исходном коде клиентов.
Остальные элементы рассматриваются в качестве описания внутренней
реализации, характерной для отдельных клиентов. Допустимый код клиента не должен
содержать ссылок на имена элементов, не связанных с API (даже с помощью интеллектуальных
API Java). В некоторых случаях недопустимые ссылки запрещаются правилами обработки имен
языка Java. Учитывая следующее простое правило, вы можете
полностью избежать подобных неполадок:
-
Используйте только API, для которых предусмотрена официальная документация. Указывайте
ссылки только на пакеты, описанные в соответствующей опубликованной документации по
API Java. Никогда не упоминайте пакеты, относящиеся к компонентам, в именах
которых указано слово "internal". Такие компоненты не связаны с API. Никогда
не упоминайте пакеты, для которых отсутствует документация по API Java. Они также не
связаны с API.
Общие правила
Спецификация элементов API создается на основе комментариев документации по Java,
указанных в исходном коде Java этих элементов. В некоторых случаях документация
предоставляется в виде контракта. Например, для метода это
может быть контракт, заключенный двумя сторонами - стороной вызывающей метод и стороной
реализующей его. Ниже приведено основное правило:
-
Выполняйте условия всех контрактов. Описание контрактов приведено в
документации по Java, опубликованной для используемых элементов API.
Термин "должен", употребляемый в контрактах на использование API, означает, что ответственность за
выполнение условий контракта возлагается на другую сторону. Невыполнение условий
может привести к ошибкам программирования, последствия которых не указываются, либо их
невозможно предсказать.
-
Выполняйте все требования, связанные с термином "должен". Обращайте особое
внимание на условия, в которых применяется термин "должен".
Прочие очевидные правила:
-
Не следует полагаться на случайное поведение. Случайное поведение - это
закономерность, определенная в результате эксперимента, но не гарантированная спецификацией API.
-
Не следует обрабатывать нулевые значения в качестве объектов. Нулевое значение
указывает на отсутствие объекта. Если в спецификации API не указано обратное, все объекты
следует рассматривать как не нулевые.
-
Не рекомендуется использовать интеллектуальные функции Java не по назначению. Применение
интеллектуальных функций Java для обхода проверки, выполняемой компилятором Java, не
создает никаких преимуществ. Дополнительные контракты по API для применения
интеллектуальных функций отсутствуют. Интеллектуальные функции увеличивают
зависимость от неуказанных алгоритмов работы и подробностей внутренней
реализации.
-
Используйте собственные пакеты. Не рекомендуется объявлять код в пакетах,
принадлежащих другим компонентам. Собственный исходный код следует всегда объявлять в
собственных пакетах.
Вызов общедоступных методов API
С точки зрения большинства клиентов API Eclipse представляет собой набор общедоступных методов,
входящих в состав классов и интерфейсов API, которые клиент может вызывать по мере
необходимости.
-
Проверяйте выполнение входных условий. Перед тем, как вызвать метод API,
убедитесь, что выполнены связанные входные условия. С другой стороны
вызывающая сторона может быть уверена, что выходные условия будут выполнены
непосредственно после возврата из вызова.
-
Нулевые параметры. Нулевые параметры можно передавать методам API только в том
случае, если это явным образом разрешено в документации. Это одна из самых
распространенных ошибок, допускаемых при программировании.
-
Ограниченные инициаторы. Методы API, доступные только для конкретных
инициаторов, разрешено вызывать только в том случае, если вы входите в их число. В
некоторых случаях методы должны входить в состав общедоступного API для работы с
конкретным классом инициаторов (как правило, внутренним). Вызов одного из таких методов
в неподходящее время может привести к неизвестным (непредвиденным) последствиям.
-
Методы отладки. Не вызывайте методы API, предназначенные "только для целей
отладки". Например, в состав этой категории входят практически все методы
toString().
-
Захват параметров. Не следует передавать массивы, наборы и другие объекты,
допускающие изменение, в качестве параметра методу API и изменять их впоследствии. Это с
большой вероятностью может привести к ошибкам.
Создание экземпляров классов API платформы
Обратите внимание, что не все настроенные классы API доступны для создания экземпляров.
Условия создания экземпляров классов API описаны в соответствующих контрактах. Кроме
того, контракт может устанавливать ответственность за остаточную инициализацию
(например, настройку конкретного свойства перед активизацией экземпляра), а также за
связанный жизненный цикл (например, вызов метода dispose() для освобождения
ресурсов операционной системы, занятых экземпляром). Классы, экземпляры которых
должны создавать клиенты, в документации по Java указываются явным образом (например,
с помощью фразы, аналогичной "Допускает создание экземпляра клиентом").
-
Ограниченное создание экземпляров. Экземпляры классов API, доступные только для
конкретных сторон, разрешено создавать только в том случае, если вы входите в их
число. В некоторых случаях классы должны входить в состав общедоступного API для работы с
конкретной стороной (как правило, внутренней). Создание экземпляра одного из таких
классов неподходящим образом может привести к неизвестным (непредвиденным)
последствиям.
Производные классы API платформы
В качестве производных классов можно использовать только подмножества классов API. Условия
объявления производных классов API описаны в соответствующих контрактах исходных классов API. Кроме
того, эти контракты устанавливают ответственность, связанную с инициализацией и жизненным
циклом производных классов. Классы, производные классы которых должны создавать клиенты, в документации по
Java выделяются явным образом (например, с помощью фразы, аналогичной "Допускает создание
производных классов клиентом").
-
Ограничение производных классов. Создание производных классов API, если это запрещено исходными
классами, недопустимо. Такие классы следует рассматривать, как объявленные конечными. (В
некоторых случаях для их описания применим термин "гибкие конечные" классы).
Вызов защищенных методов API
Вызов наследованных защищенных и общедоступных методов из производных классов в общем случае
разрешен. Однако, в отличие вызова общедоступных методов за пределами иерархии в данном
случае особое внимание следует обратить на правильность вызова.
Переопределение методов API
Переопределение предусмотрено только для части общедоступных и защищенных методов
API. Для каждого метода API предусмотрен контракт производных классов, в котором
описаны условия его переопределения в производном классе. По умолчанию переопределение запрещено.
Обратите особое внимание на контракт производных классов конкретного переопределяемого метода.
Условия контракта не передаются автоматически в ходе переопределения метода.
-
Переопределение общедоступных и защищенных методов API допустимо только в том
случае, если это разрешено явным образом. В противном случае, методы следует
рассматривать как конечные. (В некоторых случаях для их описания применим термин "гибкие
конечные" методы). Предусмотрены следующие типы переопределения:
- "реализация" - абстрактный метод, объявленный в производном классе,
должен быть реализован настроенным производным классом
- "расширение" - метод, объявленный в производном классе, должен вызывать метод из
базового класса (в точности один раз)
- "повторная реализация" - метод, объявленный в производном классе, не должен
вызывать метод из базового класса
- "переопределение" - метод, объявленный в производном классе, может вызвать метод
базового класса, если такая необходимость возникнет
-
Проверяйте выполнение выходных условий. Убедитесь, что после возврата реализация
удовлетворяет всем выходным условиям, указанным для метода API.
-
Упреждающая проверка входных условий. Не следует предполагать, что входные
условия, указанные для метода API, обязательно выполняются при вызове. Хотя
проверка входных условий необязательна, рекомендуется все-таки выполнять ее (если
это целесообразно и экономно). Такой подход позволяет своевременно отслеживать
ошибки в работе инициаторов.
-
Нулевые результаты. Не следует возвращать с помощью методов API нулевые
результаты, если в документации это не разрешено явным образом (при указании
интерфейса или базового класса).
-
Возврат копий. Не следует возвращать в качестве результата метода API незаменяемые
массивы, наборы и другие объекты, допускающие внесение изменений. Всегда возвращайте их копии во
избежание ошибок, связанных с инициаторами, которые могут изменить объект.
Реализация интерфейсов API платформы
Клиентам разрешено предоставлять реализацию только части интерфейсов API. Условия
реализации интерфейсов API описаны в соответствующих контрактах. Интерфейсы,
допускающие реализацию клиентами, в документации по Java выделяются явным образом
(например, с помощью фразы, аналогичной "Допускает реализацию клиентом"). Клиент может
объявить производный интерфейс API только в том случае, если он обладает соответствующими
правами.
-
Ограниченная реализация. Интерфейсы API, доступные только для конкретных
сторон, разрешено реализовывать только в том случае, если вы входите в их число. Зачастую
интерфейсы скрывают подробности внутренней реализации.
Реализация общедоступных методов API
См. "Переопределение методов API".
Обращение к полям классов и интерфейсов API
Клиенты могут считывать содержимое полей API, которые как правило объявляются в
качестве конечных. В состав некоторых объектов со структурой могут входить общедоступные
не конечные поля, к которым клиентам могут быть предоставлены права на чтение и запись.
-
Нулевые поля. Не следует указывать в полях API нулевые значения, если обратное
не задано явным образом.
Преобразование объектов в известный тип API
Преобразование объекта из одного известного типа API в другой тип API (либо условное преобразование
с помощью instanceof) допустимо только в том случае, если оно разрешено явным образом в
спецификации API.
-
Преобразование и instanceof. Не рекомендуется извлекать дополнительную информацию
об объекте с помощью выражений преобразования и instanceof.
Сведения о реализации, получаемые таким образом, не гарантированы API.
Кроме того, преобразование объекта в класс или интерфейс, не связанный с API, в
большинстве случаев недопустимо.
Нарушение правил
Нарушение правил, сознательное или неосознанное, влечет за собой определенные
последствия. К сожалению наказание за нарушение правил никем не установлено.
В значительной мере соблюдение правил API основано на ответственности за знание и выполнение правил, возлагаемой на каждого клиента.
Контракты, предусмотренные для элементов API, описывают поддерживаемые и
сохраненные условия применения. В условиях постоянного развития платформы Eclipse
контракты API задают нужное направление изменения. Без учета контрактов все
компоненты платформы можно считать неподдерживаемыми, допускающими
изменение без дополнительного уведомления в любое время (даже между выпусками и разными
операционными системами). Исходный
код клиента, не соответствующий правилам, может быть недопустим в других версиях и
уровнях исправления платформы, либо при переходе к другой операционной системе, либо при
под управлением другого набора модулей, либо при выполнении в другой проекции
рабочей среды и т.д. Тем не менее, последствия конкретных нарушений мало кого
интересуют. Если вы все же решили нарушить правила, не говорите, что вас не
предупреждали. Не следует ожидать чего-либо большего, чем сожаление со стороны окружающих.
С другой стороны, исходный код клиента, соответствующий рассмотренным правилам, должен
поддерживать различные версии и уровни исправления платформы, разные базовые
операционные системы, а также мирно сосуществовать с другими модулями. Только игра по
правилам позволит платформе Eclipse стать стабильной и поддерживаемой основой для
создания новых интересных продуктов.