ubmit_with_basa()
...
}else if {
g_Scheduler.get()->submitWithCallback()
...
}
重构出AsyncSubmitter接口类,AsyncSubmitterGs和AsyncSubmitterBasa是两个实现的子类,在初始化的时候将具体的子类注入(工厂),这样,在使用的地方则不用再关心是通过哪种方式请求这样的细节,同时提供了再次扩展成其他通讯方式的可能。然而,这样做最主要的好处是增加了可测性,使用gmock屏蔽发送消息这样的细节。
抽象出可复用的组件
在重构此模块过程中,不断抽象处这样有测试保障,可大量的使用,无论大小的组件。这样组件的使用,可消除重复与浪费,降低程序复杂度,提高健壮性。
这些组件,在任何C++代码需要地方都可以使用。
NULL_CHECKER
此模块采取防御式编程,期望在每个函数入口处检查NULL指针,确保程序的健壮性。然而无数的地方在进行这样的指针判断,编写这样重复的代码显得十分繁琐。
if(NULL == query_list || NULL == pfd_sets
|| NULL== pthread_data || NULL == pdyn) {
ul_writelog(UL_LOG_WARNING,"%s() param error", __FUNCTION__);
return -1;
}
因此重构出简洁的NULL_CHECK 这样的工具。
NULL_CHECK(RETURN_FAULT,query_list,pfd_sets, pthread_data, pdyn);
自动记录命令执行的时间
在此模块中,经常需要记录方法命令执行的时间,像这样:
timevalsend_start, send_end;
gettimeofday(&send_start,NULL);
ret= submit_with_callback(bcservice,bcrequest);
gettimeofday(&send_end,NULL);
intsend_time = (send_end.tv_sec -send_start.tv_sec) * USECS_PER_SEC
+ (send_end.tv_usec -send_start.tv_usec);
_m_time_data->submit_bc_time +=send_time
voidf() {
timeval send_start, send_end;
gettimeofday(&send_start, NULL);
...
gettimeofday(&send_end, NULL);
int send_time = (send_end.tv_sec -send_start.tv_sec) * USECS_PER_SEC
+(send_end.tv_usec - send_start.tv_usec);
_m_time_data->submit_bc_time += send_time
}
大量这样重复计算执行时间的代码,干扰了正常的逻辑代码,增加了代码阅读量,并且还容易出错。因此提炼出TimeDataRecord 和CmdInvokeTimer 这样的工具类。
structTimeDataRecord {
TimeDataRecord(int& time_data) :_time_data(time_data){
gettimeofday(&_ts,NULL);
}
~TimeDataRecord() {
gettimeofday(&_te,NULL);
_time_data +=(_te.tv_sec - _ts.tv_sec) * USECS_PER_SEC +(_te.tv_usec - _ts.tv_usec);
}
private:
int& _time_data;
timeval _ts, _te;
};
CmdInvokeTimer::invoke(this,METHOD(ResultFetcher2,submit_with_callback), PARAMS(bcservice,bcrequest),GetTimeData().send_da_time);
演化出更清晰的框架
对于召回逻辑,重构前存在极其复杂的调用关系如下,且前两个的逻辑处理依赖第三个逻辑处理的输出,这三个逻辑处理的圈复杂度在70左右。
运用不限于上面的重构技术,合理分配职责,降低复杂度,消除重复等