诸位看官,上代码:
if (0 == retCode) { SendMsg("000", "Process Success", outResult); } else { SendMsg("000", "Process Failure", outResult); }
乍一看,这段代码还算比较简短。那下面这段呢?
if(!strcmp(pRec->GetType(), RECTYPE::INSTALL)) { CommDM.ChangGroupInfo(const_cast(CommDM.GetAttr("IPAddress", &(pGroup->m_Attr))), true); } else { CommDM.ChangGroupInfo(const_cast(CommDM.GetAttr("IPAddress", &(pGroup->m_Attr))), false); }
看出来问题了吗?经过仔细的对比,我们发现,如此华丽的代码,if/else 的执行语句真正的差异只在于一个参数。第一段代码,二者的差异只是发送的消息,第二段代码,差异在于最后那个参数。
看破这个差异之后,新的写法就呼之欲出了,以第一段代码为例:
const char* msg = (0 == retCode ? "Process Success" : "Process Failure"); SendMsg("000", msg, outResult);
为了节省篇幅,我选择了条件表达式。我知道,很多人不是那么喜欢它。如果 if/else 依旧是你的大爱,勇敢追求去吧!
由这段代码调整过程,我们得出一个简单的规则:
- 让判断条件做真正的选择。
对于前面调整的代码,判断条件真正判断的内容是消息的内容,而不是消息发送的过程。经过我们的调整,获取消息内容和发送消息的过程严格分离开来。
消除了代码中的冗余,代码也更容易理解,同时,给未来留出了可扩展性。如果将来 retCode 还有更多的情形,我们只要调整消息获取的部分进行调整就好了。当然,封装成函数是一个更好的选择,这样代码就变成了:
SendMsg("000", msgFromRetCode(retCode),outResult);
至于第二段代码的调整,留给你练手了。
这样丑陋的代码是如何从众多代码中脱颖而出的呢?很简单,只要看到,if/else 执行块里面的内容相差无几,需要我们人工比字符寻找差异,恭喜你,你找到它了。
作者简介:
郑晔,ThoughtWorks 公司咨询师,拥有多年企业级软件开发经验,热衷于探索各种程序设计语言在真实软件开发中所能发挥的威力,致力于探寻合理的软件开发方式,加入 ThoughtWorks 公司后,投入到敏捷开发方法的实践之中,为其他公司提供敏捷开发方法方面的咨询服务。他的 blog 是梦想风暴。
查看原文:代码之丑(一)
【编者按】:这是 InfoQ 中文站新推出的专栏栏目。专栏旨在邀请国内一线的技术领域专家,定期撰写发表连载专栏,从深度和质量上为国内的技术从业者提供专业性、持续性的知识分享。这个《代码之丑》专栏计划推出系列共十篇,敬请期待后续精彩内容。也欢迎向 InfoQ 中文站推荐专栏作者及内容。
评论