【问题标题】:Should a connect method return a value?连接方法应该返回一个值吗?
【发布时间】:2010-06-08 20:54:40
【问题描述】:

我正在查看一些我继承的代码,但我无法决定是否喜欢其中的一些代码。

基本上,有一种方法如下所示:

bool Connect(connection parameters){...}

连接成功返回true,否则返回false

我过去写过这样的代码,但现在,当我看到这种方法时,出于多种原因我不喜欢它。

  1. 很容易编写忽略返回值的代码,或者没有意识到它返回了一个值。

  2. 没有办法返回错误信息。

  3. 检查方法的返回看起来不太好:

    if (!Connect(...)){....}

我可以重写代码以在连接不成功时引发异常,但我不认为这是一种异常情况。相反,我正在考虑将代码重构如下:

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

我喜欢其他开发人员必须提供成功和错误字符串,以便他们知道方法有错误条件并且我可以知道返回消息

有人对这件事有什么想法吗?

谢谢 -马特

【问题讨论】:

    标签: c# coding-style


    【解决方案1】:

    我会选择例外而不是out 参数。如果您希望您班级的消费者关心,请让他们关心异常,或者让他们独自一人。通过使用 out 参数,如果他们没有关心,你只是让他们的生活更加不方便,因为他们让他们使用一次性变量。还要考虑如果您的函数已经在野外,如果您更改签名(而不是提供额外的重载),那么您将引入重大更改。

    程序员希望在错误情况下出现异常,尤其是在 C# 等语言中。我们受过训练。

    【讨论】:

    • 我同意这个答案。通常,无法连接到某物被视为一种例外情况,并且在整个 .NET 框架(ADO.NET、WCF)中往往被视为这种情况。返回成功/错误消息对是老式的 Windows API 风格编程 - 使用 try/catch 处理强类型异常要好得多(这是惯例)。如果您有可用的工具,您应该使用它们。
    【解决方案2】:

    我只有一个意见,所以就看它的价值吧。

    这样命名的方法“Connect”是一个命令。这就像把它给一个士兵,“跳跃”或“射击”。除非他无法完成命令,否则您不会期望士兵回来报告,这将是一种罕见的情况。

    因此,我倾向于没有此类方法的返回值,但如果有机会在该方法的常规使用下会出现故障,那么我构建了第二个方法,命名为 TryXYZ,返回一个布尔值,如有必要,向我提供任何 XYZ 的结果作为输出参数。

    这遵循 .NET BCL 中各种数字类型的 Parse 方法制定的标准。

    所以在你的情况下,我可能会:

    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();
                ...
            }
    }
    

    我不希望我的订单不会完成,但从某种意义上说,我想明确一点。

    【讨论】:

    • 我喜欢这种方法。它确实使事情变得清晰。我认为将 TryConnect(...) 方法与 Foovanadil 的自定义返回类型建议相结合是我将要采用的方法。
    • 如果您的连接是短暂的,您还可以考虑返回 IDisposable 以便像这样轻松清理连接: using( var connection = connect( ... ) ) { // 使用连接 }
    【解决方案3】:

    我看到你的观点,但要添加我的 2c。

    我一般不喜欢输出参数。如果您需要从函数返回多个值,请重新评估函数正在执行的操作,在大多数情况下,多个返回值表明方法执行过多。在您的情况下,从您的连接方法返回复杂类型是合法的(除了简单的布尔值)。

    我赞成从存储所有相关信息的连接方法返回一个自定义类型,而不是多个输出参数。考虑未来的可扩展性,如果您需要在未来包含更多信息怎么办。添加额外的输出参数是一项重大更改

    另外,我倾向于不同意强制用户为所有状态数据提供内存分配。有时我不关心成功消息(也许我只关心它是否出错),在这种情况下,必须传递两个输出参数是一件很痛苦的事情。

    我同意,尽管检查发布的初始方法的返回值并不理想。

    【讨论】:

      【解决方案4】:

      我不介意 Connect 函数返回布尔值,而且我不喜欢输出参数。如果该函数没有返回连接状态,您可能不得不编写一个 IsConnected 函数/属性(取决于您的风格)以允许有人检查它,因此它节省了一步。

      就预期而言,让调用代码捕获异常,这将迫使调用者关心。 :)

      【讨论】:

        【解决方案5】:

        我同意无法建立连接(在大多数情况下)不应被视为异常情况。然而,强迫用户为错误字符串等提供参数也不是很好。其他可能的解决方案:

        1. 使用日志记录。缺点是消息会写入日志,但调用方无法(无需付出太多努力)。
        2. 使用布尔返回并提供查询最后一个错误的方法(如 C 中的 errno)。恕我直言,也不好。
        3. 重构您的代码,返回一个连接类的对象。提供查询连接状态的方法。
        4. 返回一个收集所有相关信息的类的实例,即 isSuccessfull()、getErrorString 等。

        【讨论】:

          【解决方案6】:

          不确定这是否比您的重构代码更好,但希望这可以给您另一个想法。

          对于我的项目,我创建了一个返回最后一条错误消息的方法。

          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.
          }
          

          这可能不是最好的方法,但应该可以帮助你:)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-05-18
            • 1970-01-01
            • 1970-01-01
            • 2019-09-03
            • 1970-01-01
            • 2021-09-21
            • 1970-01-01
            相关资源
            最近更新 更多