Метод подключения должен возвратить значение?

Я смотрел на некоторый код, который я наследовал, и я не мог решенный, если мне нравится немного кода.

В основном существует метод, который похож на следующее:

bool Connect(connection parameters){...}

Это возвращает true, если это соединяется успешно, ложь иначе.

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

  1. Его легкое для написания кода, который просто игнорирует возвращенное значение или не понимает это, возвращает значение.

  2. Нет никакого способа возвратить сообщение об ошибке.

  3. Проверка возврата метода действительно не выглядит хорошей:

    если (! Подключение (...)) {....}

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

void Connect(Connection Parameters, out bool successful, out string errorMessage){...}

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

У кого-либо есть какие-либо мысли о вопросе?

Спасибо - Матовый

8
задан Matt S 8 June 2010 в 20:54
поделиться

6 ответов

У меня есть только мнение, так что воспринимайте его так, как оно того стоит.

Метод, названный так, "Подключиться", - это приказ. Это все равно, что отдать приказ солдату: "Прыгай" или "Стреляй". Вы не ожидаете, что солдат отчитается, если только он не сможет выполнить приказ, а это случается крайне редко.

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

Это соответствует стандарту, установленному методами Parse различных числовых типов в .NET BCL.

Так что в вашем случае я, вероятно, имел бы:

void Connect(connection parameters);
bool TryConnect(connection parameters, out status);

Самое приятное, что если вы правильно построите метод TryConnect, то Connect станет действительно простым.

Пример:

public bool TryConnect(string connectionString, out ConnectionStatus status)
{
    ... try to connect
    ... set status, and return true/false
}

public void Connect(string connectionString)
{
    ConnectionStatus status;
    if (!TryConnect(connectionString, out status))
        switch (status)
        {
            case ConnectionStatus.HostNotFound:
                throw new HostNameNotFoundException();
            ...
        }
}

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

3
ответ дан 5 December 2019 в 09:24
поделиться

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

Программисты ожидают исключений в случаях ошибок, особенно в таких языках, как C#. Мы были обучены.

12
ответ дан 5 December 2019 в 09:24
поделиться

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

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

1
ответ дан 5 December 2019 в 09:24
поделиться

Я согласен, что неспособность установить соединение (в большинстве случаев) не должна рассматриваться как исключительная ситуация. Однако заставлять пользователя предоставлять аргументы для строки ошибки и т.д. тоже не очень хорошо. Другие возможные решения:

  1. Используйте протоколирование. Недостатком является то, что сообщения записываются в журнал, но не доступны (без особых усилий) вызывающей стороне.
  2. Использовать возврат булевых значений и предоставлять методы для запроса последней ошибки (как errno в C). IMHO тоже не очень хорошо.
  3. Рефакторить код, возвращать объект класса соединения. Предоставьте методы для запроса состояния соединения.
  4. возвращайте экземпляр класса, который собирает всю необходимую информацию, aka isSuccessfull(), getErrorString и т.д.
1
ответ дан 5 December 2019 в 09:24
поделиться

Я вижу ваши замечания, но хочу добавить свои 2c.

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

Я был бы за то, чтобы возвращать пользовательский тип из метода connect, который хранит всю необходимую информацию, а не несколько выходных параметров. Подумайте о будущей расширяемости, что если вам понадобится включить больше информации в будущем. Добавление дополнительных выходных параметров - это разрушающее изменение

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

Хотя я согласен, что проверка возвращаемого значения исходного метода не идеальна.

1
ответ дан 5 December 2019 в 09:24
поделиться

Не уверен, что это лучше, чем ваш код рефакторинга, но, надеюсь, это может дать вам другое представление.

Для своих проектов я создаю метод, который возвращает последнее сообщение об ошибке.

string Error = '';
bool Connect(connection parameters)
{
// do my connection here
// if there's an error set string variable Error
// This way you can set different error message depending on what you're doing
}

string lastErrorMessage(){
// return Error string
}

Вы можете сделать это таким образом:

if(!connect(...))
{
string message = lastErrorMessage();
// Then do what you need here.
}

Возможно, это не лучший способ, но он должен вам помочь :)

0
ответ дан 5 December 2019 в 09:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: