Мне был назначен проект по разработке набора классов, которые действуют как интерфейс к системе хранения. Требование состоит в том, что класс поддерживает метод get со следующей сигнатурой:
public CustomObject get(String key, Date ifModifiedSince)
В принципе, предполагается, что метод возвращает CustomObject
, связанный с key
, если и только если объект был изменен после ifModifiedSince
. Если система хранения не содержит key
, тогда метод должен вернуть значение null.
Моя проблема такова:
Как обрабатывать сценарий, в котором существует ключ, но объект имеет not?
Это важно, потому что некоторые приложения, которые используют этот класс, будут веб-службами и веб-приложениями. Этим приложениям необходимо будет знать, нужно ли возвращать 404 (не найдено), 304 (не изменено) или 200 (ОК, здесь данные).
Решения, которые я взвешиваю:
- Выбросить пользовательское исключение, если
система хранения не содержит
key
- Выбросить пользовательское исключение, если
ifModifiedSince
не работает. - Добавить свойство status в CustomObject. Требовать вызова для проверки свойства.
Я не доволен ни одним из этих трех вариантов. Мне не нравятся варианты 1 и 2, потому что я не люблю использовать исключения для управления потоком. Мне также не нравится возвращать значение, когда я намерен указать, что было no value.
Тем не менее, я склоняюсь к варианту 3.
Есть ли вариант, который я не рассматриваю? Кто-нибудь имеет сильные чувства по поводу любого из этих трех вариантов?
Ответы на этот вопрос, парафраз:
- Предоставьте
contains
метод и требует вызова вызывающего абонента перед вызовомget(key, ifModifiedSince)
, бросьте исключение, если ключ не существует, return null, если объект не был модифицировано. - Оберните ответ и данные (если есть) в составном объекте.
- Используйте предопределенную константу для обозначения некоторого состояния (
UNMODIFIED, KEY_DOES_NOT_EXIST
). - Caller реализует интерфейс, который будет используется как обратные вызовы.
- Дизайн отстой.
Почему я не могу выбрать ответ № 1
Я согласен, что это идеальное решение, но это был тот, который я (неохотно) отклонил. Проблема с этим подходом заключается в том, что в большинстве случаев, когда эти классы будут использоваться, бэкэнд-система хранения будет сторонней удаленной системой, такой как Amazon S3. Это означает, что для метода contains
требуется обратная поездка в систему хранения, которая в большинстве случаев будет сопровождаться другой поездкой туда и обратно. Поскольку это будет стоить как времени, так и денег, это не вариант.
Если бы не это ограничение, это был бы лучший подход.
(Я понимаю, что я не упомянул об этом важном элементе в вопросе, но я старался держать его в курсе. Очевидно, это было актуально.)
Вывод:
После прочтения всех ответов я пришел к выводу, что обертка - лучший подход в этом случае. По сути, я буду подражать HTTP, с метаданными (заголовками), включая код ответа, и тело контента (сообщение).