最近写东西碰到多种分支如错误和判断逻辑时,总是一团乱麻,有些错误不一定会发生,但是不写总感觉不对。随后摸到一本书<O’Reilly The Art of Readable Code>,图文并茂,看了看确实写得不错。
结合StackOverflow的一个例子,来看看处理过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| if(FileExists(file)) { contents = OpenFile(file); // <-- prevents inclusion in if if(SomeTest(contents)) { DoSomething(contents); } else { DefaultAction(); } } else { DefaultAction(); }
|
这样的代码处理起来没什么问题,但是看着别扭(如果当外层的判断一多,if/else就对应增多,形成多个嵌套)。因为它把所有的步骤放在一个过程里处理了,如果要进行维护,阅读起来并不简单。我把它理解为流程图逻辑,流程图是产品需求用到的,还是尽量不要用到代码上吧。
改进后:
1 2 3 4 5 6 7 8 9 10 11
| if(FileExists(file)) { contents = OpenFile(file); // <-- prevents inclusion in if if(SomeTest(contents)) { DoSomething(contents); return; } }
DefaultAction();
|
这次改进后程序先处理DoSomething(),中断异常情况,最后处理默认情况。
再次改进:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| contents_t get_contents(name_t file) { if(!FileExists(file)) return null;
contents = OpenFile(file); if(!SomeTest(contents)) // like IsContentsValid return null;
return contents; }
...
contents = get_contents(file) contents ? DoSomething(contents) : DefaultAction();
|
用函数处理,把判断和逻辑分开,这样功能就分离出来了,清晰明了,利于维护。
总结:我偏向于处理异常后,再处理正常情况,因为如果为函数的话,你所做事情应该是匹配函数名的,剔除掉异常情况,最后得到的就是正常情况的结果,不是吗?
最后,回归到IF/ELSE,最初代码的IF/ELSE形式为:
1 2 3 4
| if(contents_t contents = get_contents(file)) DoSomething(contents); else DefaultAction();
|