Как вернуть подробные сведения об ошибке из метода без использования исключений и при необходимости включить значение? - PullRequest
6 голосов
/ 14 января 2012

Сначала немного фона:

У меня уже есть класс Result, который я реализовал для переноса информации о результатах. Они были реализованы специально для сбоев, результат успеха, как правило, не несет никакой дополнительной информации. Я использую их в общедоступных методах вне основного API в одном из моих проектов или в методах глубиной в один или два уровня, где мне нужно перенести подробную информацию обратно в общедоступный API. Этот API используется в контейнере и клиенте командной строки и ранее был очень хорошо проверен. Альтернативой было добавление этой информации контекста сбоя к исключениям и добавление нескольких более отдельных классов исключений, где они просто не принадлежали. Я думаю, это отражает мой общий подход:

http://blogs.atlassian.com/2011/05/exceptions_are_bad

Результат имеет вспомогательное перечисление и интерфейс:

  1. ResultStatus: SUCCESS, FAILURE, CONDITIONAL_SUCCESS и т. Д. Содержит коды возврата int и общие сообщения (например, «Операция прошла успешно»)
  2. ResultCode: пустой интерфейс для маркировки кодов результатов перечисления, FILE_NOT_FOUND, FILE_INVALID, FILE_INCOMPATIBLE. В основном они предназначены для модульного и функционального тестирования, но также используются для интерактивной справки (справка Maven по сбою функционально аналогична тому, что я делаю)

Result предоставляет статические фабричные методы для статуса и методы компоновщика для установки других ключевых полей и является неизменным. Вот как выглядит результат построения:

Result.success().withCode( ResultCode ).withMessage( "" );

И оценивая полученный результат:

result.isSuccessful();
result.hasCode( ResultCode );
result.getMessage();

Моя проблема:

Подход оказался очень успешным, в частности, благодаря функциональным тестам стало легче, однако у меня есть один существенный пробел: хотя в большинстве случаев я забочусь только о результате, в некоторых критических областях мне нужно возвращать значение с результатом ,

Я не доволен своей первой попыткой: ResultPair<T>, которая содержит результат и значение, где T - тип значения. Если я не продублирую все методы Result, использование класса является многословным и неуклюжим: получите Result, добавьте его в ResultPair и выловите результат и значение перед оценкой. На первый взгляд, наследование не будет работать из-за паттерна компоновщика, и я не могу придумать, как получить чистый, чистый код, который Result позволяет без полного дублирования класса Result.

В идеале, подход позволил бы Result возвращать значение опционально, но я не могу придумать способ сделать это безопасным для типов способом, который гарантирует, что сигнатуры метода четко указывают тип значения, но избегают бессмысленного универсальный параметр везде, где я не возвращаю значение.

Я действительно не против иметь два класса, и это не конец света, чтобы дублировать Result Builder и оценочный код, он просто чувствует неправильно , и я чувствую, что отсутствие опыта приобретает лучше меня, и я пропускаю (очевидное или не очень очевидное) решение. Я использую Guava, и я хочу запретить нулевые значения дружественным способом, поэтому может дополнительно обернуть все значения в необязательные, но мне все еще нужны общие параметры (и объединить их в класс, чтобы избежать result.value ( ) .get () ... Хорошо, теперь я думаю вслух. Я должен задать вопрос ...).

Есть ли способ удовлетворить эти, по-видимому, взаимоисключающие требования?

1 Ответ

2 голосов
/ 14 января 2012

Вы можете создать ResultPair<T> в качестве базового класса для класса результатов void :

public class Result extends ResultPair<Void> { ... }

Все соответствующие методы будут объявлены в ResultPair<T>.

ОБНОВЛЕНИЕ :

Еще лучше, используйте только один тип Result<T> и используйте Result<Void> всякий раз, когда вы не хотите иметь возвращаемое значение.Или, скорее, если использование Void в качестве аргумента типа кажется вам странным, создайте новый необъяснимый (или одноэлементный) тип, который означает «результата нет», и используйте его вместо этого: Result<Unit>, например.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...