лучше ли возвращать сложный объект или использовать параметры ссылки / выхода? - PullRequest
17 голосов
/ 28 июля 2010

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

Проекты, с которыми я сталкивался, включают возвращение bool и использование параметра out (или ref) для сообщения, возвращение экземпляра (специально разработанного) класса со свойствами bool и string или даже возвращение перечисления, указывающего проход или конкретная ошибка. Каков наилучший способ получить всю информацию из метода? Есть ли что-нибудь из этого "хорошего"? У кого-нибудь есть другие рекомендации?

Ответы [ 14 ]

0 голосов
/ 29 июля 2010

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

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

"Проекты, с которыми я сталкивался, включают в себя возврат bool и использование параметра out (или ref) для сообщения, возвращающего экземпляр (специально разработанный) класса со свойствами bool и string, или даже возвращающего перечисление, указывающее проход или конкретную ошибку. "

  1. Сложные объекты, конечно, наиболее очевидный вариант.(класс или структура)

  2. Выходной параметр : «Один из способов представить параметры - это то, что они похожи на дополнительные возвращаемые значения метода. Они очень удобныкогда метод возвращает более одного значения, в этом примере параметры firstName и lastName могут использоваться некорректно. Однако для хорошего стиля программирования, если вы пишете метод со многими параметрами out, вам следует подумать о рефакторинге кода.Одним из возможных решений является упаковка всех возвращаемых значений в одну структуру. "Слишком много параметров out или ref указывает на недостаток дизайна.

  3. Tuple : "сгруппировать кучу несвязанных с другими данными в некоторой структуре, более легкой, чем класс"

Необходимо прочитать: Подробнее о кортежах :

0 голосов
/ 29 июля 2010

Я думаю, что это зависит от уровня сложности и от того, может ли операция завершиться неудачей, что приведет к ... что?

В случае TryParse примеров вы, как правило, не можете вернуть недопустимое значение(например, нет такой вещи как «недопустимый» int) и определенно не может возвратить тип нулевого значения (соответствующие Parse методы не возвращают Nullable<T>).Кроме того, для возврата Nullable<T> потребуется ввести на сайте вызова переменную Nullable<T>, условную проверку, чтобы определить, является ли значение null, с последующим приведением к типу T, что должно дублировать среду выполнения.проверьте, является ли значение нулевым, прежде чем возвращать это фактическое ненулевое значение.Это менее эффективно, чем передача результата в качестве параметра out и указание через возвращаемое значение успеха или неудачи (очевидно, в этом случае вас не беспокоит , почему это не удалось, только то, что оно сделал ).В предыдущих версиях .Net единственным выбором были Parse методы, которые вызывали любые сбои.Перехват исключений .Net стоит дорого, особенно в связи с возвратом флага true / false, указывающего состояние.

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

out и ref не являются no-nos, но ваш интерфейс должен быть тщательно продуман какнасколько они необходимы или нет, прежде чем использовать их.Стандартный возврат по ссылке должен быть достаточным в более чем 99% случаев, но я бы посмотрел на использование параметров out или ref, прежде чем излишне определять новый тип, просто чтобы удовлетворить возвращение «одного» объекта вместо нескольких значений.

0 голосов
/ 29 июля 2010

Мы делаем что-то очень похожее с нашими службами WCF, используя объекты Request и Response, и исключения полностью всплывают (не обрабатываются в самом методе) и обрабатываются пользовательским атрибутом (написанным в PostSharp), который перехватывает исключение ивозвращает ответ «ошибка», например:

[HandleException]
public Response DoSomething(Request request)
{
   ...

   return new Response { Success = true };
}

public class Response
{
   ...
   public bool Success { get; set; }
   public string StatusMessage { get; set; }
   public int? ErrorCode { get; set; }
}

public class Request
{
   ...
}

Логика обработки исключений в атрибуте может использовать сообщение «Исключение» для установки StatusMessage, и если у вас есть набор пользовательских исключений в вашем приложении, вы даже можете установитьErrorCode, где это возможно.

0 голосов
/ 29 июля 2010

Метод TryParse (...) - не лучший пример в этом случае.TryParse только сигнализирует, был ли проанализирован номер или нет, но не указывает, почему анализ не удался.Это не нужно, потому что единственная причина, по которой он может потерпеть неудачу, связана с «плохим форматом».

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

Какие тесты вы проводите?Они связаны вообще?Существуют ли тесты в этом же методе, которые не пройдут из-за совершенно разных несвязанных причин, которые вы должны отслеживать, чтобы дать содержательный отзыв пользователю / потребителю?

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

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

Существует много возможностей, но нам нужно больше информации о том, что вы пытаетесь сделать, чтобы дать вам более точный совет.

...