2008-09-16 2 views
19

Позвольте мне начать с того, что я не защищаю этот подход, но я видел его недавно, и мне было интересно, есть ли имя для него, которое я мог бы использовать, чтобы указать на виновную сторону. Так вот.Есть ли название для этого запаха анти-шаблона/кода?

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

class FunctionResult<T> 
{ 
    public T payload; 
    public int result; 
} 

А затем объявить свои функции, как это:

FunctionResult<string> MyFunction() 
{ 
    FunctionResult<string> result; 
    //... 

    return result; 
} 

Один из вариантов на этой модели является использование перечисления для кода ошибки вместо строки , Теперь вернемся к моему вопросу: есть ли имя для этого, и если да, то что это?

+1

«Кто-то, кто не идиот, сломает мои пальцы молотком, когда увидит этот« узор ». Но это в значительной степени относится ко всем антипаттернам. – Will 2008-09-16 14:15:08

+1

Если это анти-шаблон, то какова рекомендация для языков, которые не поддерживают прямую поддержку исключений (я думаю о VB/VBA). – 2008-09-16 14:41:42

+1

Если они не поддерживают исключения, они, вероятно, также не поддерживают шаблоны/дженерики. – 2008-09-16 15:17:59

ответ

17

Я согласен, что это конкретно не антипаттерн. Это может быть запах в зависимости от использования. Существуют причины, по которым на самом деле не хотелось бы использовать исключения (например, возвращаемые ошибки не являются «исключительными» для стартеров).

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

Этот код может и не быть ошибкой: рассмотрите ответ HTTP, который состоит из множества разных данных, включая код состояния, вместе с телом ответа.

1

Как насчет шаблона «Невозможно решить, является ли это ошибкой или нет». Похоже, если вы действительно имели исключение, но хотели вернуть частичный результат, вы бы обернули результат в исключение.

4

Я не уверен, что это анти-шаблон. Обычно я рассматривал это вместо исключений из соображений производительности или, возможно, для того, чтобы тот факт, что метод может оказаться более явным. Для меня это скорее личное предпочтение, чем анти-шаблон.

10

Ну, это не антипаттерн. Стандартная библиотека C++ использует эту функцию, и .NET даже предлагает специальный класс FunctionResult в платформе .NET. Это называется Nullable. Да, это не ограничивается результатами функции, но может быть использовано для таких случаев и на самом деле очень полезно здесь. Если в .NET 1.0 уже был класс Nullable, он, безусловно, использовался бы для методов NumberType.TryParse вместо параметра out.

2

Этот подход на самом деле намного лучше, чем некоторые другие, которые я видел. Некоторые функции в C, например, когда они сталкиваются с ошибкой, они возвращаются и, кажется, преуспевают. Единственный способ сказать, что они потерпели неудачу, - вызвать функцию, которая получит самую последнюю ошибку.

Я потратил часы, пытаясь отладить код семафора на моем MacBook, прежде чем я узнал, что sem_init не работает на OSX! Он скомпилирован без ошибок и запускался без каких-либо ошибок, но семафор не работал, и я не мог понять, почему. Мне жаль людей, которые переносят приложение, которое использует POSIX semaphores в OSX, и должны иметь дело с проблемами конфликтов ресурсов, которые уже были отлажены.

6

Обычно я передаю полезную нагрузку как ссылку (не const) и код ошибки в качестве возвращаемого значения.

Я разработчик компьютерных игр, мы прогонять исключения

1

Если вы не хотите использовать исключения, самый чистый способ сделать это - вернуть функцию код ошибки/успеха и принять либо аргумент ссылки или указателя, который заполняется результатом.

Я бы не назвал это анти-шаблоном. Это очень хорошо зарекомендовавший себя работоспособный метод, который часто предпочтительнее использовать исключения.

1

Если вы ожидаете, что ваш метод не в состоянии время от времени, но не считают, что исключительное, я предпочитаю эту модель, как используется в .NET Framework:

bool TryMyFunction(out FunctionResult result){  

    //...  
    result = new FunctionResult(); 
} 
5

Konrad является правильным, C# использует двойные возвращаемые значения все время. Но я вроде как методы TryParse, Dictionary.TryGetValue и т. Д. В C#.

int value; 
if (int.TryParse("123", out value)) { 
    // use value 
} 

вместо

int? value = int.TryParse("123"); 
if (value != null) { 
    // use value 
} 

... в основном потому, что Nullable модель не масштабируется для возвращаемых типов без значения (т.е. экземпляров класса). Это не будет работать с Dictionary.TryGetValue(). И TryGetValue лучше, чем KeyNotFoundException (нет «исключений из первого шанса» постоянно в отладчике, возможно более эффективный), лучше, чем практика Java get() возвращает null (что, если ожидаются нулевые значения), и более эффективно, чем сначала вызовите ContainsKey().

Но этот is все еще немного вялый - так как это выглядит как C#, тогда он должен использовать параметр out. Вероятно, все выгоды от повышения производительности теряются, создавая экземпляр класса.

(Может быть Java для типа «строки», находящегося в нижнем регистре, за исключением. В Java, конечно, вы должны использовать класс для эмуляции двойных возвращаемых значений.)

3

Я согласен с теми, которые говорят, что это не является анти-модель. Его совершенно правильный шаблон в определенных контекстах. Исключения составляют исключения ситуации, возвращаемые значения (как в вашем примере) должны использоваться в ожидаемых ситуациях. Некоторые домены ожидают действительные и недопустимые результаты из классов, и ни один из них не должен быть смоделирован как исключения.

Например, если у вас есть количество газов, может ли автомобиль добраться от А до В, и если да, то сколько газа осталось? Такой вопрос идеально подходит для структуры данных, которую вы предоставили. Невозможно сделать поездку от А до Б, поэтому исключение не должно использоваться.

0

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

  1. объектов х = MyFunction() полезная нагрузка; (игнорирование результата возврата - очень плохо)
  2. int code = MyFunction(). Result; (выброс полезной нагрузки - может быть, все в порядке, если это предполагаемое использование.)
  3. FunctionResult x = MyFunction(); // ... (куча дополнительных объектов FunctionResult и дополнительного кода, чтобы проверить их все за место)

Если вам необходимо использовать коды возврата, это нормально. Но тогда используйте коды возврата. Не пытайтесь упаковать в него дополнительную полезную нагрузку. Вот что такое ref и out Параметры (C#) предназначены для. Необязательные типы могут быть исключением, но только потому, что для поддержки этого языка используется дополнительный сахар, испеченный на языке.

Если вы все еще не согласны с этой оценкой, DOWNVOTE этот ответ (не весь вопрос). Если вы думаете, что это анти-шаблон, то UPVOTE это. Мы будем использовать этот ответ, чтобы узнать, что думает сообщество.

1

Дискуссии о запахах и анти-узорах напоминают мне телешоу «Survivor», где у вас есть различные программные конструкции, пытающиеся проголосовать друг у друга на острове. Я бы предпочел видеть, что «у конструкции X есть такие-то плюсы и минусы», а не на постоянно меняющийся список указаний о том, что следует и чего не следует делать.