百度工程效率部技术教练经验分享
2019-12-26
来源:百度敏捷教练
学对于领域知识的深入理解,产品线同学所做的详细设计多是关于业务流程的优化,业务算法的重构,而涉及类的设计,代码职责的划分问题,则由技术教练把握。
经过一段时间的合作,产品线同学意识到前期做的代码详细设计,在不断的重构中变得面目全非,重构最后得出漂亮的软件设计与之前的想法相差很远,所以才能彻底接收技术教练的方案。
重构的一些技术
封装实现细节,降低复杂度
把数据和它的行为放在一起
光有数据而没有行为是没有意义的。把本身行为留给用户,不仅在语义上不合理,且提高了用户处理的复杂度,实现细节的变更会引起用户的变化,甚至带来重复等另外的问题。封装往往是解决这类问题的有效手段。
ac::DARequest darequest;
darequest.set_query_list(query_list);
darequest.set_query_control(queryControl);
... many other similar initial methods
重构成:
ac::DARequest darequest;
bool is_init_success = darequest.init(...)
用及早返回的技巧来降低复杂度
卫语句(出错及早返回)的技巧,可以用来减少嵌套
遵循单一职责
单一职责是软件设计的一个基本原则,但在实践中却不容易做到。
让一个函数做一件事,从语义上分开
AC向BC召回的策略集合 “deque<StrategyRecallQueue*> _query_types;”实际上包含normal_queue和inserted_queue,他们都是通过get_next_queue来查找。但使用者却在某些地方明确的希望得到normal_queue,且get_next_queue的实现里也在区分如果是normal_queue该怎么办,如果是其他的类型该怎么办。因此将两种语义分理,重构出两个接口:
QC_ERR_CODE get_normal_query_type()
QC_ERR_CODE get_next_query_type()
文件也单一职责
acqueryanalyze.h这个文件,完成了query变换工作。它包含结构体query_list_t,然而query_list_t却是召回阶段和其他阶段也会用到的结构体。因此,将query_list_t与acqueryanalyze.h分离开。
query_list_t与DaData.h又存在循环依赖,导致了各种晦涩难以发觉的编译问题,降低了开发效率。头文件应该自完备(头文件自己解决需要的所有依赖),且避免循环依赖,以避免这类编译问题。
使用前置声明减少头文件依赖
头文件的依赖调用是影响编译速度最主要的问题之一,而前置声明则是解决这类问题的手段。应该尽量使用前置声明而非直接包含头文件。如acqueryanalyze.h:
#include"acpub.h"
...
#include"memset_manager.h"
重构成对应的前置声明:
classUsData;
....
namespaceda_interface {
classanalyzed_query;
}
使用策略模式增加灵活性
消除开关且增加可测性
开关代码在主干开发的情况下很常见。开关的另外一种实现是使用策略模式。
if(conf_set.ac2da_use_basa == 1) {
ac2da_s
免责声明:
1、IT项目管理界发布的所有资讯与文章是出于为业界传递更多信息之目的,并不意味着赞同其观点或证实其描述。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请浏览者仅作参考,并请自行核实相关内容。
2、本站部分内容转载于其他网站和媒体,版权归原作者或原发布媒体所有。如文章涉及版权等问题,请联系本站,我们将在两个工作日内进行删除或修改处理。敬请谅解!