IF/ELSE的处理方式

最近写东西碰到多种分支如错误和判断逻辑时,总是一团乱麻,有些错误不一定会发生,但是不写总感觉不对。随后摸到一本书<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();