Есть ли название для этого «шаблона»? - PullRequest
11 голосов
/ 31 марта 2011

Мне интересно, есть ли имя для этого "шаблона", где сигнатура метода называется TrySomething, например int.TryParse, decimal.TryParse и т. Д.

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

Редактировать: я понимаю, что приведенный пример не относится к методам TryParse. Это был смысл опубликовать это ... Я не был уверен, как это назвать. Я согласен, что это больше похоже на соглашение об именах, а не шаблон. Спасибо за все комментарии.

Редактировать: Интересно ...

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

Для реализации шаблона TryParse вы предоставляете два разных метода для выполнения операции, которая может генерировать исключения в общих сценариях. Первый метод, X, выполняет операцию и выдает исключение при необходимости. Второй метод, TryX, не выдает исключение, а вместо этого возвращает логическое значение, указывающее успех или неудачу. Любые данные, возвращаемые при успешном вызове TryX, возвращаются с использованием параметра out (ByRef в Visual Basic). Методы Parse и TryParse являются примерами этого шаблона.

Ответы [ 8 ]

13 голосов
/ 31 марта 2011

Я бы назвал это Шаблон сокрытия ошибок . Вы получаете выгоду от создания TryX, когда у вас есть код, который обычно выдает исключение, которое вместо этого рано выключается с логическим значением. Если вы посмотрите на методы, предоставляемые фреймворком, то заметите, что варианты TryX существуют всякий раз, когда нетривиально или подвержено ошибкам (или это часто делается в фреймворке), чтобы написать свой собственный IsValidX способ.

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

В принципе, если a priori вы знаете, что операция завершится с исключением, логично и правильно предоставить сопутствующую операцию TryX. Это так называемый паттерн Tester-Doer . Post hoc анализ операции - это не Тестер-Doer , а просто Обработка исключений .

7 голосов
/ 31 марта 2011

В этом посте о TryParse они называют паттерном Тестер-Doer.

6 голосов
/ 31 марта 2011

Прежде всего, если ваше описание точное, это не совсем так, как работает int.TryParse и его братья и сестры.

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

На самом деле, лучший способ, опять же на мой взгляд, это то, что я видел в сторонней библиотеке, которую я не помню, но в основном у них были различные пользовательские типы, у которых была такая пара методов Parse / TryParse, и они делали следующее:

  1. Определите универсальную структуру, которая содержала бы и значение, полученное при разборе строкив качестве значения типа enum, передающего результат синтаксического анализа
  2. Все методы TryParse возвращали эту структуру и не имели out параметра
  3. Методы Parse просто вызывали методы TryParse, а затемперевел различные неуспешные результаты этого перечисления в соответствующие исключения

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

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

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

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

Я бы серьезно посмотрел на ваш паттерн и попытался бы его изменить.

Конечно, все это зависит от предположения, что ваше описание еготочный.

4 голосов
/ 31 марта 2011

Я называю это паттерном «Жаль, что у меня не было Option<T>» (который аналогичен паттерну «Жаль, что у меня было Either<T,E>» - представьте, где E: исключение).

TryXYZ (вприведенные выше примеры) имитирует Option с использованием логического результата и параметра out.(Для типов значений это может быть Nullable<T> в этом случае - я подозреваю, что это не так для int.TryParse и друзей частично, потому что Nullable пришли намного позже .NET).Возвращение исключения через out более похоже на Either.

В C # я бы не рекомендовал отлавливать исключения, просто передав их в out параметрам в общем, хотя (это «правило» может отличаться в зависимости от языкакоторый поддерживает различимые союзы и сопоставление с образцом) - я пытаюсь 1) справиться с этим «правильно», однако это определено, что очень хорошо может быть out в особых обстоятельствах ;или 2) отпустить, чтобы вызывающий мог попробовать то же самое.

(Как уже отмечали другие, это скорее соглашение).

Счастливое кодирование.

3 голосов
/ 31 марта 2011

Вы можете назвать это ExceptionSafeBridge. Он ведет вас из мира исключений в мир кодов ошибок. Но я не думаю, что это официально.

Этот шаблон является обычным, когда вам нужно соединить, например, между Код C и управляемый код.

1 голос
/ 31 марта 2011

Да. Он называется Тестер-Doer .

1 голос
/ 31 марта 2011

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

0 голосов
/ 31 марта 2011

если проблема возникает во время tryparse, то есть

 int val;
        if(int.TryParse("2", out val))
        {
            //do work with val
        }

Тогда вы не получите исключение через параметр out, значение 0 для out, false будет возвращено как логическое значение.

Best betвместо этого использовать "is" или "as".

Я бы не стал называть подход, который вы описываете шаблон, хотя ... Просто практика кодирования (не самая лучшая).

Пример as:

private void SetObj(object obj)
{
    int thisInt = obj as int;
    if(thisInt != null)
    {
       //do work
    }
    else
    {
       //handle issue
    }

}

Вышеприведенное намного более эффективно во время выполнения, чем try / catch.

Если вы используете «is», когда as недоступно для вас («as»)не для всех типов), убедитесь, что не добавляете избыточность путем реализации, поскольку WITH is ... использует только один или другой.

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