这种反模式/代码气味有名字吗?

这种反模式/代码气味有名字吗?

Is there a name for this anti-pattern/code smell?

首先,我说我不主张采用这种方法,但是最近我看到了这种方法,我想知道是否有一个名字可以用来指认有罪的政党。 所以去。

现在您有了一个方法,并且想要返回一个值。 您还想返回一个错误代码。 当然,异常是更好的选择,但是无论出于何种原因,您都希望使用错误代码。 记住,我在这里扮演恶魔的拥护者。 因此,您将创建一个通用类,如下所示:

1
2
3
4
5
class FunctionResult< T >
{
    public T payload;
    public int result;
}

然后像这样声明你的函数:

1
2
3
4
5
6
7
FunctionResult<string> MyFunction()
{
    FunctionResult<string> result;
    //...

    return result;
}

此模式的一种变体是对错误代码使用枚举而不是字符串。 现在,回到我的问题:对此有一个名称吗?


我同意这不是专门的反模式。根据使用情况,可能会有异味。有一些原因导致人们实际上不希望使用异常(例如,对于初学者来说,返回的错误不是" exception")。

在某些情况下,您希望服务为其结果返回一个通用模型,包括错误和良好值。这可能被低级服务交互所包装,该服务交互将结果转换为异常或其他错误结构,但是在服务级别,它使服务可以返回结果和状态代码,而不必定义可能会导致异常的异常结构。必须跨远程边界进行翻译。

该代码也不一定是错误:考虑一个HTTP响应,该响应由许多不同的数据(包括状态码)以及响应主体组成。


它被称为"用异常替换错误代码"


好吧,这不是反模式。 C ++标准库利用了此功能,.NET甚至在.NET框架中提供了一个特殊的FunctionResult类。它称为Nullable。是的,这不仅限于函数结果,它还可以用于此类情况,在这里实际上非常有用。如果.NET 1.0已经具有Nullable类,则肯定会将它用于NumberType.TryParse方法,而不是out参数。


我通常将有效负载作为(非const)引用传递,并将错误代码作为返回值传递。

我是游戏开发人员,我们排除了例外情况


Konrad是正确的,C#始终使用双返回值。但是我有点像C#中的TryParse,Dictionary.TryGetValue等方法。

1
2
3
4
int value;
if (int.TryParse("123", out value)) {
    // use value
}

代替

1
2
3
4
int? value = int.TryParse("123");
if (value != null) {
    // use value
}

...主要是因为Nullable模式无法缩放为非Value返回类型(即类实例)。这不适用于Dictionary.TryGetValue()。而且TryGetValue不仅比KeyNotFoundException(在调试器中始终没有"第一次机会异常",可以说效率更高)要好,比Java的get()返回null(如果期望null值会怎样)的做法还好,并且比必须这样做要更有效。首先调用ContainsKey()。

但这仍然有些棘手-因为它看起来像C#,所以应该使用out参数。实例化类可能会损失所有效率提高。

(除了" string"类型为小写字母外,它可以是Java。在Java中,您当然必须使用一个类来模拟双返回值。)


我不确定这是否是反模式。出于性能原因,我经常看到使用此方法而不是使用异常,或者可能是为了使该方法失败的事实更加明确。在我看来,这似乎是个人喜好而不是反模式。


我同意那些说这不是反模式的人的观点。在某些情况下,这是一种完全有效的模式。在特殊情况下例外,应在预期情况下使用返回值(如您的示例中所示)。一些域期望类产生有效和无效的结果,并且都不应该将它们建模为异常。

例如,给定X倍的汽油量,一辆汽车可以从A到B行驶吗?如果有,还剩下多少汽油?对于您提供的数据结构,这种问题是理想的。预计无法进行从A到B的旅行,因此不应使用异常。


实际上,这种方法比我所见过的其他方法要好得多。例如,C语言中的某些函数在遇到错误时会返回并似乎成功。告诉他们失败的唯一方法是调用将获得最新错误的函数。

我花了数小时尝试在MacBook上调试信号灯代码,然后才终于发现sem_init在OSX上不起作用!它编译时没有错误,并且在运行时没有引起任何错误-但是该信号灯不起作用,我不知道为什么。我很感激那些将使用POSIX信号的应用程序移植到OSX并必须处理已经调试的资源争用问题的人们。


关于气味和反模式的辩论让我想起了"幸存者"电视节目,那里有各种各样的编程结构试图在岛上互相投票。我宁愿看到" construct X具有某种优缺点",而不是不断发展的关于应该做什么和不应该做什么的法令列表。


如果您希望您的方法偶尔会失败,但又不认为这种例外,我更喜欢在.NET Framework中使用的这种模式:

1
2
3
4
5
bool TryMyFunction(out FunctionResult result){    

     //...    
     result = new FunctionResult();
}

如果您不想使用异常,则最干净的方法是让函数返回错误/成功代码,并采用填充了结果的引用或指针参数。

我不会称其为反模式。这是一种行之有效的可行方法,通常比使用异常更好。


"无法确定这是否是错误"模式如何呢?好像您确实有异常,但想返回部分结果,则将结果包装在异常中。


为了反模式的指定,该代码可以通过以下几种方式使用:

  • 对象x = MyFunction()。payload; (忽略返回结果-非常糟糕)
  • int代码= MyFunction()。result; (扔掉有效载荷-如果这是预期用途,可能会没事的。)
  • FunctionResult x = MyFunction(); // ...(一堆额外的FunctionResult对象和额外的代码来检查它们)
  • 如果您需要使用返回码,那很好。但是,然后使用返回码。不要尝试在其中打包额外的负载。这就是ref和out参数(C#)的目的。可空类型可能是一个例外,但这仅是因为在语言中还增加了额外的糖来支持它。

    如果您仍然不同意此评估,请对这个答案(不是整个问题)进行投票。如果您确实认为这是一种反模式,请对其进行投票。我们将使用此答案来查看社区的想法。


    推荐阅读

      linux命令行模式使用?

      linux命令行模式使用?,工作,地址,目录,信息,名称,系统,管理,命令,文件,标准,l

      linux切换成命令模式?

      linux切换成命令模式?,密码,系统,工具,模式,命令,首页,状态,图形界面,终端,

      linux命令行模式清页?

      linux命令行模式清页?,工作,系统,命令,信息,地址,目录,内容,文件,操作,功能,l

      linux进入命令行模式?

      linux进入命令行模式?,系统,地址,情况,工作,命令,终端,首页,信息,目录,界面,l

      linux底线模式命令?

      linux底线模式命令?,系统,档案,密码,状态,工作,命令,模式,文件,明文,界面,lin

      linux启用命令模式?

      linux启用命令模式?,系统,密码,数字,首页,电脑,情况,终端,界面,模式,命令,安

      linux命令错误代码?

      linux命令错误代码?,系统,密码,电脑,网络,手机,网址,软件,代码,设备,老板,Lin

      linux命令行模式联网?

      linux命令行模式联网?,系统,网络,地址,密码,软件,检测,信息,工具,终端,界面,l

      linux使用命令的方法?

      linux使用命令的方法?,系统,信息,工具,标准,数据,命令,左下角,目录,文件夹,

      linux回到命令行模式?

      linux回到命令行模式?,系统,密码,状态,工具,电脑,终端,界面,环境,地方,命令,

      linux命令模式联网?

      linux命令模式联网?,网络,系统,工具,软件,密码,地址,最新,信息,工作,数据,lin

      linux进去命令模式?

      linux进去命令模式?,系统,密码,首页,终端,命令,界面,窗口,选项,桌面,用户,lin

      linux命令模式全屏?

      linux命令模式全屏?,系统,工具,电脑,数据,位置,命令,虚拟机,分辨率,字符串,

      linux中回到命令模式?

      linux中回到命令模式?,系统,密码,情况,状态,终端,环境,信息,首页,界面,命令,

      linux命令行模式6?

      linux命令行模式6?,系统,设计,信息,工作,终端,首页,庞大,服务,地方,环境,linu

      linux怎么用命令模式?

      linux怎么用命令模式?,工作,地址,系统,信息,管理,命令,目录,情况,图形界面,

      linux插入命令模式?

      linux插入命令模式?,工作,系统,地址,管理,信息,时间,命令,目录,平均,项目,Lin

      命令行模式登陆linux?

      命令行模式登陆linux?,密码,系统,工作,信息,终端,环境,状态,地址,工具,服务,l

      linux打开命令模式?

      linux打开命令模式?,系统,密码,管理,情况,终端,命令,工具,信息,地方,电脑,LIN

      linux改命令行名字?

      linux改命令行名字?,时间,名字,名称,软件,文件,图片,位置,状态,网上,系统,lin