Есть ли название для этого запаха / шаблона? - PullRequest
19 голосов
/ 16 сентября 2008

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

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

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

А затем объявите ваши функции следующим образом:

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

    return result;
}

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

Ответы [ 13 ]

17 голосов
/ 16 сентября 2008

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

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

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

11 голосов
/ 16 сентября 2008
10 голосов
/ 16 сентября 2008

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

6 голосов
/ 16 сентября 2008

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

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

5 голосов
/ 16 сентября 2008

Конрад прав, 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 (нет «исключений первого шанса» постоянно в отладчике, возможно, более эффективен), приятнее, чем практика get () Java, возвращающая ноль (что, если ожидаются нулевые значения), и более эффективен, чем необходимость сначала вызовите ContainsKey ().

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

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

4 голосов
/ 16 сентября 2008

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

3 голосов
/ 16 сентября 2008

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

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

2 голосов
/ 16 сентября 2008

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

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

1 голос
/ 19 ноября 2008

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

1 голос
/ 16 сентября 2008

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

bool TryMyFunction(out FunctionResult result){    

     //...    
     result = new FunctionResult();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...