读书人

怎么重构多重判断if-else

发布时间: 2014-01-14 23:14:00 作者: rapoo

如何重构多重判断if-else
最近改别人的代码,看到以前他写得太烂了,有很多if-else判断,于是想重构。大家看有没有什么好的方法?
以前的代码是这么写的(例子):

UserProp m_Prop;
//////////////////////////////////////
if ( m_Prop.A == 1 )
{
if ( m_Prop.B == 1 )
{
return "Good";
}
else if ( m_Prop.B == 2 )
{
return "Not too bad";
}
else return "Just so so";
}
else if ( m_Prop.A == 2 )
{
if ( m_Prop.B == 1 )
{
if ( m_Prop.C == 1 )
{
return "Need improvement";
}
else return "Need more improvement";
}
else if ( m_Prop.B == 2 )
{
return "Have a chance to improve";
}
else return "Too bad";
}

[解决办法]
这不一定能重构。你的那些state有多少个态?
[解决办法]
这样的if-else还好啦,而且及时return,效率并不低。

引用:
最近改别人的代码,看到以前他写得太烂了,有很多if-else判断,于是想重构。大家看有没有什么好的方法?
以前的代码是这么写的(例子):
UserProp m_Prop;
//////////////////////////////////////
if ( m_Prop.A == 1 )
{
if ( m_Prop.B == 1 )
{
return "Good";
}
else if ( m_Prop.B == 2 )
{
return "Not too bad";
}
else return "Just so so";
}
else if ( m_Prop.A == 2 )
{
if ( m_Prop.B == 1 )
{
if ( m_Prop.C == 1 )
{
return "Need improvement";
}
else return "Need more improvement";
}
else if ( m_Prop.B == 2 )
{
return "Have a chance to improve";
}
else return "Too bad";
}

[解决办法]
整体来说,没有太好的办法。其实这个代码还是比较容易读懂的。具体到这个例子,我以为可以这样写,当然未见得更易懂:
UserProp m_Prop;
//////////////////////////////////////
ASSERT( (unsigned)(m_Prop.A-1) < 2 );

const char * prompts[]={"Good","Not too bad", "Just so so",
”Need more improvement", "Have a chance to improve", "Too bad"};
int tmp=unsigned(m_Prop.B-1);
int i=(m_Prop.A-1)*3+ tmp>1?2:tmp;
return i==3&&m_Prop.C==1 ? "Need improvement" : prompts[i];


两者(应该)功能上等效。但从易读懂,易维护的角度来看,原版应该更好。比如,如果m_Prop.B要细分为4类时,上面的代码就要大修。想使用这种"聪明"的办法,又要避免未预期的变化以难以追踪的方式break这些code,可以多放一些ASSERT,比如上面可以ASSERT( (unsigned)(m_Prop.B-1) <3 ); // 根据当前设计,只允许1,2,3三种值,那么上面的实现代码还可以进一步简化为:
UserProp m_Prop;
//////////////////////////////////////
ASSERT( (unsigned)(m_Prop.A-1) < 2 );
ASSERT( (unsigned)(m_Prop.B-1) < 3 );
const char * prompts[]={"Good","Not too bad", "Just so so",
”Need more improvement", "Have a chance to improve", "Too bad"};



int i=(m_Prop.A-1)*3+ m_Prop.B-1;
return i==3&&m_Prop.C==1 ? "Need improvement" : prompts[i];



Not necessarily better/smarter, just different.
[解决办法]
这种应该可以满足你的需求吧
引用:

//这样呢?
int state = (m_Prop.A << 8)
[解决办法]
(m_Prop.B << 4)
[解决办法]
m_Prop.C;
switch(state){

}
//或者搞几个mask?

[解决办法]
我觉得原版写的很清楚
在执行效率相同的情况下,逻辑清楚功能分明的100行要比代码复杂技巧高明的10行更好
[解决办法]
引用:
最近改别人的代码,看到以前他写得太烂了,有很多if-else判断,于是想重构。大家看有没有什么好的方法?
以前的代码是这么写的(例子):
UserProp m_Prop;
//////////////////////////////////////
if ( m_Prop.A == 1 )
{
if ( m_Prop.B == 1 )
{
return "Good";
}
else if ( m_Prop.B == 2 )
{
return "Not too bad";
}
else return "Just so so";
}
else if ( m_Prop.A == 2 )
{
if ( m_Prop.B == 1 )
{
if ( m_Prop.C == 1 )
{
return "Need improvement";
}
else return "Need more improvement";
}
else if ( m_Prop.B == 2 )
{
return "Have a chance to improve";
}
else return "Too bad";
}


重构不是盲目进行的,也就是说,代码本身不能狗说明长成什么样子就对了,即,代码要实现的功能是什么。只有从本质上清楚我们要解决的问题域,才能使我们设计出更好的代码结构。

一般来说,去掉if可以用switch替换,去掉switch可以用数组或者面向对象的多态来替换。
如果你能从问题域角度出发,能够抽象出多个分类,可以使用多态来解决。如果是同一事物在不同状态下有不同的行为,你可以使用状态模式来解决。


[解决办法]
其实我们做项目时首先注意的是软件的整体架构,然后是某个模块的架构,再就是到类的设计等等。当然怎样设计好的架构,有很多书籍都有说到,基本上不外乎易于理解,维护,扩展之类的。需要说明的是不要为了达到所谓的这些要求,然后进行无限制的设计。 不管当初这些架构设计的怎样,随着项目的进行,总是有这有那前面没想到问题,其中有些问题需要我们对于现在的架构/类/函数进行改进,否则没办法进行,这个时候需要重构,当然重构可大可小,大到软件整体架构,小到类/函数的重新设计/实现。

在C++中,理论上我们应减少像if/else的使用,但是单从你给定的代码来说,没办法给你一个很好的重构方案,如果仅是想换成像switch的代码,我觉得大可没有必要,除非它影响到外面(或者客户)的使用,或者你需要加入新的功能,这样的代码使你很难理解或者扩展,那你可以尝试重构一下,如果是关乎模块的设计,可以了解些design pattern。但是不管怎样,把UserProp.A/B/C改成enum类型是一个比较好的习惯,至少让人好理解。


[解决办法]
UserProp m_Prop;
//////////////////////////////////////
//如果m_Prop.B的取值范围在1~9之间
int AB=m_Prop.A*10+m_Prop.B;
switch (AB) {
case 11: return "Good";
case 12: return "Not too bad";
case 21:
if (m_Prop.C==1) return "Need improvement";
else return "Need more improvement";
case 22: return "Have a chance to improve";
default:
if (AB<=19) return "Just so so";
else return "Too bad";
}

http://bbs.csdn.net/topics/380157851

读书人网 >C++

热点推荐