Не совсем уверен, что формальный термин для такой модели / проблемы, но вот с чем я сталкиваюсь:
У меня есть операция, которая несколько велика. Это может или пройти или потерпеть неудачу. Каждый проход или сбой несет с собой либо результат успешной операции, либо информацию о том, почему операция не удалась. Я изо всех сил пытаюсь построить эту функцию "правильно".
class Pass{
int someGoodStuff;
double someOtherGoodStuff;
}
class Fail{
String failureMsg;
float howMuchOperationWasOffBy;
}
class Operator{
public ??? operation(){
}
}
Подход 1 : Состояния отказа похожи на исключения. Давайте бросим их. Это позволяет мне включить информацию об ошибке и сделать тип возврата просто Pass. Однако эти состояния отказа не являются ошибками языка программирования, они являются ошибками бизнес-логики. Таким образом, в этом подходе меня не устраивают две вещи: во-первых, он путает сбой бизнес-логики с фактическими ошибками Java (что кажется неправильным), и во-вторых, он поддерживает нормальный поток выполнения без каких-либо веских причин для этого.
Подход 2 : Функции в java любят возвращать один тип объекта, поэтому Pass и Fail реализуют интерфейсный Result и имеют возвращаемый тип функции.
interface Result{...}
class Pass implements Result{...}
class Fail implements Result{...}
class Operator{
public Result operation(){...}
}
Однако, pass и fail указывают, что функция полностью отличается. У них мало или нет перекрывающихся переменных или функций. Это кажется неправильным и сводит меня к необходимости instanceof
всей важной информации из пропусков и неудач.
Подход 3 : Какой-то объект объединения, который может быть как пройденным, так и неудачным (но не оба)
class Result{
public Pass pass=null;
public Fail fail=null;
}
class Operator{
public Result operation(){...}
}
Это имеет то преимущество, что я могу сказать что-то вроде
Result result=op.operation();
if (result.succeed()){
doStuffWithPass(result.getPass());
}else{
doStuffWithFail(result.getFail());
}
Что в основном я и делал с instanceof, но выглядела лучше; Теперь код выглядит так, как вы этого ожидаете. Понятно следовать.
Однако в Java нет настоящих типов Union. Я должен убедиться, что кто-то случайно не попытается связываться с переменными прохода Результата сбоя или наоборот. Кроме того, каждый метод, который я вызываю для типа объединения, должен быть основан на выяснении, является ли это проходом или неудачей (ветвь That If внезапно должна быть везде)
Наконец, хотя это и не является реальной проблемой, я полагаю, что такая схема распределяет пространство как для прохода, так и для неудачи для каждого результата, когда я знаю, что он может быть только одним из них (т.е. он должен занимать пространство равно Max(space(Pass),space(Fail))
)
Ни один из этих подходов не кажется идеальным. Я чувствую, что должен быть образец, чтобы решить такую проблему. Есть ли?