Контекст (Изменить)
Некоторые разъяснения были по требованию, поэтому я постараюсь подвести итог тому, что влияет на вопрос.
-
Цель проекта - предоставить определенную функциональность программистам, скорее всего, в виде библиотеки (JAR с файлами классов, я думаю).
-
Чтобы использовать указанную функциональность, программисты должны были бы соответствовать ограничениям, которые должны (должны) быть удовлетворены. В противном случае он не будет функционировать должным образом (как блокировки от
java.util.concurrent
, которые должны быть получены/освобождены в соответствующее время и место). -
Этот код не будет точкой входа в приложения, использующие его (т.е. не имеет
main
). -
В API существует ограниченное (и небольшое) количество операций.
<сильные > Примеры:
-
Подумайте о небольшой игре, где почти все реализовано и управляется уже реализованными классами. Единственное, что осталось для программиста - написать метод или пару из них, которые описывают, что будет делать персонаж (ходить, менять направление, останавливать, проверять объект). Я хотел бы убедиться, что их методы (возможно, отмеченные аннотацией?) Просто
walk
илиchangeDirection
, или вычисляютdiff = desiredValue - x
, а не, скажем, пишут в какой-либо файл или открывают соединение сокета. -
Подумайте о менеджере транзакций. Менеджер будет предоставлен этой библиотекой, а также некоторые постоянные атрибуты транзакций (их уровень изоляции, тайм-ауты,...). Теперь программисты хотели бы иметь транзакции и использовать этого менеджера. Я хотел бы убедиться, что они только
read
,write
,commit
илиrollback
на некоторых ресурсах, известных менеджеру. Я бы не хотел, чтобы они былиlaunchRocket
в середине транзакции, если менеджер не контролирует запуск каких-либо ракет.
Проблема
Я хочу наложить некоторые инварианты/ограничения/ограничения на тело метода (или группы методов), которые позднее будут реализованы каким-либо другим программистом, в некоторых других пакетах/местоположениях. Скажем, я даю им что-то вроде:
public abstract class ToBeExtended {
// some private stuff they should not modify
// ...
public abstract SomeReturnType safeMethod();
}
Для целей этого проекта важно (возможно, обязательное), чтобы тело метода удовлетворяло некоторым инвариантам. Вернее, крайне важно, чтобы набор команд, используемых в этом методе, ограничен. Примеры этих ограничений:
- Этот метод не должен выполнять никаких операций ввода-вывода.
- Этот метод не должен создавать какие-либо неизвестные (потенциально опасные) объекты.
- ...
Поставьте другой способ:
- Этот метод может вызывать методы известного (определенного) класса.
- Этот метод может выполнять некоторые основные инструкции (математика, назначение локальных переменных,
if
s, циклы...).
Я просматривал аннотации, и, похоже, ничего близкого этому не было.
До сих пор мои варианты:
-
Определите некоторую аннотацию
@SafeAnnotation
и примените ее к методу, определяя контракт с разработчиком, что он будет следовать установленным правилам, иначе система будет работать неправильно. -
Определите
Enum
с разрешенными операциями. Вместо раскрытия разрешенных методов раскрывается только метод, который принимает список этих объектов перечисления (или что-то похожее на Control Flow Graph?) и выполняет его, давая мне контроль над тем, что можно сделать.
Пример:
public enum AllowedOperations { OP1, OP2 }
public class TheOneKnown {
public void executeMyStuff (List<AllowedOperations> ops) {
// ...
}
}
Мой вопрос
Есть ли какая-либо функция на языке, например аннотации, отражение или что-то еще, что позволяет мне проверять (во время компиляции или времени выполнения), если метод действителен (т.е. удовлетворяет моим ограничениям)?
Вернее, есть ли способ принудить его к вызову только ограниченного набора других методов?
Если нет (и я думаю, что нет), будет ли этот второй подход подходящей альтернативой?
Подходит, как в интуитивно понятной, хорошо продуманной и/или эффективной практике.
Обновление (прогресс)
Изучив некоторые связанные вопросы, я также рассматриваю (как третий вариант, возможно) следующие шаги, приведенные в принятом ответе этого вопроса, Хотя это может потребовать некоторого пересмотра архитектуры.
Вся идея использования аннотаций для введения ограничений, похоже, требует внедрения моего собственного обработчика аннотаций. Если это так, я мог бы также рассмотреть небольшой язык, специфичный для домена, чтобы программист использовал эти ограниченные операции, а затем перевел код на Java. Таким образом, я бы также имел контроль над тем, что указано.