有些时候,一个方法需要满足一些条件才能执行。所以,在真正产生实际作用的代码前,需要进行很多判断,判断初始条件是否满足。这样的方法可能长这个样子:
1 | def some_method |
对于第一次阅读这个方法的开发者,最有意义的应该是最后一行,但前面的判断条件却占据了这个方法的大部分空间。如果一个阅读者是顺序阅读,那么他的脑力在读到真正起关键作用的代码之前,可能已经快要枯竭了。毕竟,人的短期记忆只能记住(并可以应用) 3 或 4 条信息,多一点的话也就 7 条。前面那么一大长串树形结构的判断条件,反而可能阻碍其他开发者去阅读。
怎么办?
能不能把那些判断条件封装成另外一个方法?这好像是个不错的选择,但是那些判断条件都在控制some_method
的返回,如果抽象到另外一个方法中,比如judge
方法中,那么judge
方法中 return
是无法控制some_method
的返回的。
利用被调函数的返回值,控制调用函数的返回
如果我们把那些判断条件抽象出去的时候,在调用函数中增加一个条件来判断封装好的方法的返回值,就能决定调用函数是否需要返回了。
1 | def some_method |
这样的重构是不是让 some_method
看起来清爽多了。
如果你不关心judge
方法返回什么样的错误信息,你甚至可以将some_method
方法写成这样:
1 | def some_method |
在上面这个重构的方法中,如果 judge
方法的返回值不是 nil
,那么some_method
就会被返回。据说这种带有 a_judgement and return
的结构在写 ruby 和 rails 代码时很常用。
利用被调函数抛出的异常,控制调用函数的返回
根据调用栈的特点,如果被调函数抛出异常,他就会从调用栈中弹出,这个时候,如果在调用函数中增加异常的捕捉,程序的执行就有回到了调用函数上,而且还捕捉到了异常信息。所以,我们可以这么重构。
1 | def some_method |
这样的重构中,some_method
也是比较清爽的。