编写返回 void 的方法是一种好习惯吗?
Posted
技术标签:
【中文标题】编写返回 void 的方法是一种好习惯吗?【英文标题】:Is it a good practice to write methods that return void? 【发布时间】:2012-05-07 02:21:37 【问题描述】:我正在开发一个由复杂对象组合驱动的用 java 编码的复杂企业应用程序。例如:在特定场景中,要执行一个操作,流程如下:
login() ->
Followed by defined sequence of 10 to 20 method calls in different classes ->
Followed by a logout()
在框架内,包括登录、注销在内的几乎所有操作以及 10 到 20 个方法调用中的许多都没有返回类型。任何错误行为都由框架处理。说,在登录中
public void login()
try
//login actions
//chained sequence of calls
catch()
// framework handling exceptions and other rollback options
中间的 10 到 20 个动作是在框架的不同层次结构中对不同对象的方法调用。
一个随机的类应该是这样的:
class someobject
def variable
void action1() do something on variable
void action2() do something on variable
...
变量经常改变状态,这些动作有一个仅由框架定义的序列,我觉得这很烦人。
我想说,如果有适当的返回类型,或者至少有一些方法,比如login()
的布尔值,生活会容易得多。由于对一系列 void 返回函数的严格遵守,我发现很难通过调试来理解流程,而且单元测试对我来说成了一场噩梦。
所以现在,我的印象是编写返回某些内容的函数总是更好,尤其是当涉及到一系列操作时。那么,这是一个安全的假设吗?我想听听你对此的看法。如果我错了,请纠正我。
【问题讨论】:
您在这里解释的内容听起来像是您缺少正确的组件驱动设计。该方法将导致无法维护的“spagetti 代码”。你可能需要引入一些中间层... 【参考方案1】:一个方法最基本的可测试性是通过它的返回码。在login
的情况下,您需要(如您所述)能够测试您现在是否已登录,并且boolean
返回是显而易见的方法。否则,您必须检查一些属性,这似乎是不必要的非原子和复杂的(尽管可能由于其他原因需要)。
对我来说,这个论点可以扩展到任何有意义的方法。使用void
返回码很常见,但更多是由于旧习惯而不是良好的设计原因。简单的属性设置器是一个反例,我相信还有其他的。
【讨论】:
如果你是函数式编程的粉丝(我是),我会更进一步说 void 方法是可变状态的标志 - 这很糟糕。【参考方案2】:在我看来,没有必要总是在操作链上返回某些东西这完全取决于您的要求。即在登录身份验证方法中,最好返回布尔结果以进行简化。如果一系列动作独立于一个和另一个,那么在我看来,没有必要返回任何不会被任何动作使用的东西。因此,如果一个动作的结果影响下一个动作,那么它应该返回一些内容以进行简化和测试,以便您可以直接从导致问题的方法的输出中提取。确定方法后,您可以检查已确定的特定方法。所以基本上每件事都取决于你的要求。如果您的要求在不返回任何东西的情况下得到更好的处理,那么您应该接受它。此外,您应该遵循最佳实践或设计模式以提高效率,这对于所有情况都会更好,并且您最终可以摆脱混乱。这只是我的意见。
【讨论】:
【参考方案3】:当方法对类中的本地数据进行操作时,void 方法是完全合理的,只要它对类上下文中有意义的某些“行为”进行建模。例如,如果您有一个对其内容进行排序的 SpecialSortedList,即 myList.sort(),则 sort() 方法将无效,因为它对与 SpecialSortedList 相关的某些行为进行建模。
如果方法不对类内的本地数据进行操作,即通过参数接受其数据并返回一些数据(即不依赖本地数据),最好将其声明为静态甚至移动它到一个实用程序或帮助类。
【讨论】:
您是说,Data Repository 或任何其他数据提供者中的“添加”、“删除”或“更新”等方法应该返回一些东西吗?布尔?还是刚刚创建的记录的id? 依我看,你说的排序方法应该返回排序后的列表,不要做有副作用的吓人的事情,然后返回void。【参考方案4】:越来越多,我更喜欢返回状态码而不是 void。这做了几件事:
-
我允许调用您的函数的代码知道接下来要做什么(例如,如果操作失败,那么调用代码可能需要执行与操作成功时不同的操作)。
测试和调试更容易(正如您所提到的)。我已经开始相信为可测试性编写代码是确保代码质量的最佳方法之一(当然假设您确实对其进行了测试)。 void 函数很难测试。
我的偏好是尽可能让大多数函数接受参数,返回答案并且不更改任何类变量。正如 Jaco 所提到的,这些可以声明为静态的,甚至可以移动到实用程序类中。然后你可以让一些控制器函数使用返回值的函数。
【讨论】:
【参考方案5】:我会将答案分成两部分:
什么时候返回“void”有用 -
如果方法返回一个值只是为了指示不正确的状态/异常,那么它应该返回“void”。异常应该负责处理所有错误场景,而不是说“布尔”返回值。现在,调用代码需要再次验证布尔值和异常。如果它只抛出异常,那么调用代码会更容易和更清晰。
什么时候返回 void 没那么有用 -
如果方法执行任何操作并返回值作为结果,则不应返回“void”,需要返回相关的结果类型(布尔/整数/对象等)。
一般来说,返回值应该实际对应于方法是否返回。它不应该对应于方法执行是否正确(嗯,应该是)。所有输入验证/异常场景都应该通过抛出相应的异常来处理。例如,当输入无效时抛出 IllegalArgumentException,而不是返回“布尔”表示方法未执行。
【讨论】:
我完全不同意应该将异常用作传达常规故障场景的焦点。以上是关于编写返回 void 的方法是一种好习惯吗?的主要内容,如果未能解决你的问题,请参考以下文章