2015-11-23 2 views
2

У меня есть следующий метод:Не бросать бизнес исключений, но возвращение значения

public void Foo addFoo(String name); 

Этот метод добавляет Foo к некоторой структуре. В то же время он проверяет, существуют ли Foo по дате name. Я могу бросить FooNameConflictException, но я бы этого не сделал, так как я не рассматриваю это как исключение - это то, что может произойти, и оно является частью бизнес-потока приложения.

Вместо этого, я бы вернул информацию, если Foo по названию уже существует. Каков прагматичный способ сделать это? Что я должен вернуть, если имя уже существует?

  1. Возвращение null - и это чистая уродлив, как null не означает ничего, и это не является расширяемым и ... некрасиво.

  2. Foo с некоторым внутренним статусом, что указывает на то, что Foo является НОВЫМ или СУЩЕСТВУЮЩИМ. Тем не менее, мы должны тщательно сконструировать изменение состояния из NEW -> СУЩЕСТВУЮЩЕГО, т.е. я не уверен, когда это произойдет, и может не работать в многопоточных средах.

  3. сделать новый класс FooOperation или FooAdding, которые составляют из Foo экземпляра и дополнительного флага (ов), который приносит больше информации о процессе добавления.

  4. Я могу пойти с общим вариантом №3 и иметь класс Either, но тогда вы привязаны к двум значениям (слева или справа).

Я вижу решение № 3 как единственное прагматическое в этом случае. Я что-то упускаю?

+1

На первый взгляд это звучит как этот метод беря на себя более чем одну ответственность и должны быть развязаны на различные обязанности. – Makoto

+0

Зачем вам нужно знать, что значение 'Foo' для' name' было добавлено вместо повторного использования вне метода 'addFoo'? Вы также говорите, что конфликт - это то, что может произойти в нормальном бизнес-процессе, как вы справляетесь с этим делом? – Jean

+0

Вы глотаете свои исключения? –

ответ

0

По опыту, в случае, если name является ключом объекта Foo, я бы вернул объект Foo, связанный с именем, если оно было найдено.

Следовательно, пользователь метода будет использовать возвращаемый объект Foo, не заботясь о том, является ли это новым объектом или уже существующим объектом. Если вы должны знать состояние объекта Foo, возможно добавить в него атрибут state.

+0

Это похоже на # 2, но это дает дополнительная работа по правильному праву. Например, состояние может быть NEW, а затем дополнительный поток выдает экземпляр и изменяет состояние до того, как он фактически будет потреблен первым потоком. – igr

0

Лично я по-прежнему отправляюсь за исключением, но включаю чек, если он существует в вашем кодовом коде.

Таким образом, ваш обычный бизнес-поток включает проверку конфликта имен и соответствующей реакции. Вызов addFoo, несмотря на конфликт, приведет к возникновению исключения.

Если вы захотите, вы можете комбинировать check + обработку + вызов addFoo в своем собственном методе и, возможно, даже позволить этому влиять на видимость addFoo (сделайте его закрытым или лучше всего работает в вашем случае).

Типичная альтернатива для меня было бы с-стиль: Всегда возвращает код результата и пусть вызывающий код ветви на его основе (успех, nameConflict, ...)

Смежные вопросы