当前位置:C++技术网 > 资讯 > 项目开发经验之谈:返回值和返回数据方式的总结

项目开发经验之谈:返回值和返回数据方式的总结

更新时间:2017-05-27 23:09:05浏览次数:1+次

    说起返回值和返回数据方式,大家都很熟悉了。然而,这次在开发服务器系统的时候,却因为返回值和返回数据方式产生了一些麻烦,所以来总结一下。
    一个函数执行完,需要做到几点:
1.完成功能
2.返回数据
3.返回执行状态
    完成功能属于最基本的点了,这点不必说。然而在处理返回数据和返回执行状态上,有时候不注意,有可能产生混乱。下面来说说是如何产生混乱的。

一、返回数据方式

    一个函数执行完后,我们经常需要知道执行状态,也要知道返回的数据。当然,状态比数据更重要。如果执行失败,返回的数据将是没有意义的。那么如何返回这两者呢?
    一般有以下三种:
    第一种:返回值返回状态,然后用参数返回数据。我们先判断返回值的状态,来确定执行是否成功,或者来确定出错的类型,进而来决定是否使用返回的数据。如果失败或者出错类型导致数据无效,那么一定不要使用数据。这也就是要先判断状态的原因。参数返回数据的方式有引用和指针形式。
    第二种:用返回值共享返回状态和返回数据。如果返回的数据和状态同属于一种类型,比如都是int类型,很多时候为了让参数简单,就直接用返回值来共享返回状态和返回数据。比如,返回值为0,出错;返回值小于0,表示出错的原因;返回值大于0,就是数据。举一个例子,一个函数测量身高。因为身高不可能为0和0以下的值,所以可以这样用。
    第三种:使用结构体来返回状态和数据。如果要大量的数据需要返回,同时还要返回状态,使用参数也很麻烦,我们要传递一大堆参数,函数使用起来也就麻烦了,参数太长了。返回后的数据也不好管理。为了简化,就用一个结构体来将所有需要返回的数据和状态打包返回。但是,这样你需要事先定义一个结构体,这就是麻烦的地方。当参数和数据真的太多的时候,这种方式倒是挺合适。
    以上只是列举了三种,可能还有更多的方式,毕竟人类的智慧是很强大的。第三种不再我们今天讨论的范围。最常见的还是前两种。
    上面的三种都是讨论的返回数据的方式,含状态。第二种有其使用条件,如果乱用,就混乱了。比如测量温度,不管返回什么数值,都是可能的,所以,就不能用返回值共享返回状态和返回数据。
    所以,第二种使用需要注意一下,除非真合适,否则不要用。一般情况,第一种和第三种都是可以的。在返回数据的方式上,我们要做到,数据和状态的分离。当然,在一个函数执行可能出错的情况下,一定要设计执行状态,而不要忽略状态。一个好的代码,这一点是非常重要的。如果一个函数执行了之后,连成功与否都不知道,能说是好代码吗?出了问题也让人感觉莫名其妙的,调试找问题就更麻烦了。
    还有一种常见的方式就是,函数只给出执行是否成功,然后使用专门的函数获取错误码,再获取判断错误信息。这种方式在api函数中很常见,但是作为我们个人的函数设计,尽量不要这样。最好让一个函数可以单独运作,解除其他地方的依赖,让函数可以更好的移植。

二、返回值的使用

    对于返回值的使用,可能很少有人去认真想过。但是这个却是我在项目中感触非常多的地方。一个不起眼的地方,却也体现了高质量代码的细节。返回值我们这里讨论作为状态的返回值,讨论的是这个返回值如何定义。
    一般有这些定义方法:
    1.布尔类型
        对于布尔类型,就只有true和false了。但是,这个值到底是执行的结果(数据)还是执行的状态(是否执行成功),这个在返回数据方式中就应该定义好。事实上,后面的类型,都是如此。我们这里假设都确定的是执行的状态。对于布尔类型的状态,定义返回值也有一些技巧。
        一个函数检测水是否满了,返回true表示满了,返回false表示没有满。另一个函数检测水是否不满,返回true表示不满,返回false表示满。虽然返回的值都是一样,但是意义却有所变化。很多时候我们在定义这个值的时候,发现定义一个状态值,在进一步判断是,需要取反来进行错误处理,那么此时我们可以考虑检测状态的反面,比如将检测水满变成水不满,这样后续的判断就可以不必反转状态来判断。毕竟直接的判断更省事,可以减少错误。如果你在觉得一个状态判断感觉绕口的时候,请记得优化状态判断。而且一旦定义了一个方式,比如都判断正向的状态值,true表示OK,false表示不OK,那么后续的判断也都尽量保持一致。这一点看似没有什么关系,但是当逻辑复杂了之后,很容易混乱。
    2.int型
        对于int返回状态的返回值,我们也有几种定义方式。1.返回0表示成功,非零表示失败,非零值表示具体的错误码。2.返回0表示失败,大于0表示成功,小于0表示错误码。同时,后一种有时候还和布尔类型的返回值进行混用。int可以兼容bool类型的返回值,但是除非必要,尽量不要混用。要么就是int转成bool后,状态消失,后续无法跟踪错误信息。bool转为int之后,状态不够,和没有转一样。然而在混用的时候,慢慢让两种类型的返回值混在一起,最后也搞不清楚谁是谁了。
    3.其他类型
        其他类型主要有字符串或者指针。一般是将空字符串或者空指针或者空,对于指针来说,一般都是空指针表示失败,非空指针表示成功。而字符串则不确定。可以将空字符串作为失败状态,而非空表示数据。这是将数据和状态混在一起的情况。具体情况具体分析了。

    我在项目中,因为涉及到多层次的接口调用问题,而且多层次的接口都是我自己定义的,所以在设计接口返回值时,有时候是多层次的接口返回值都是在一起,一时返回0表示成功,一时返回1表示成功,一时返回true表示成功。这个问题,确实导致了一部分状态判断错误,所以后来就从头到尾将返回值的定义梳理了一遍,最后状态都保持一致,没有问题了。
    在我们平时在设计函数时,尽量保持一种风格,这样在做复杂项目的时候,我们也就可以因为平时的习惯而受益。