我的代码库已经包含重复代码,只有很小的差异,可序列化的ID,索引,变量数组。
代码库非常庞大,并且基于简单的预处理程序指令和常量(例如:#define CFG_PROJECT cfgAutobot
,#define CFG_PROJECT cfgUltron
,..等)激活/停用了一些组件。
功能实际上是相同的,但具有不同的组件和条件。例如:
int somedata;
int somecounter;
void main_loop(){
#if(CFG_PROJECT == cfgAutobot)
if(someInterface() == 1){
somedata = some_other_interface();
}
#endif
#if(CFG_PROJECT == cfgUltron)
if(third_if() > 0){
someCounter++;
}
else
{
someCounter = 0;
}
#endif
}
void query_data(int selector){
if(False){
/* Dummy block */
}
#if(CFG_PROJECT == cfgUltron)
else if(selector == 1){
return somedata;
}
#endif
#if(CFG_PROJECT == cfgAutobot)
else if(selector == 2){
return someCounter;
}
#endif
else{
return Err_code;
}
}
因为这个代码使用的数据比简单的计数器和整数复杂得多,涉及不同大小的多个组件,所以这些代码部分要复杂得多。然而,它们可以追溯到一个共同的结构。
我能够按如下方式应用X-list技术:
#define Ultron_implementation X(var_ultron, (someInterface() == 1), update_function_1, selector_id_1)
#define Autobot_implementation X(var_autobot, (third_if() > 0), update_function_2, selector_id_2)
/* (Please note, that this is a simplified example, in the actual
code there are much more components, but the `main_loop`
implementation can be traced back to a few update functions) */
void update_function_1(int var, int selector) {
if(selector == 1){
var++;
}else{
var = 0;
}
}
void update_function_2(int var, int selector) {
if(selector == 1){
var = some_other_interface();
}else{
/* Nothing to do */
}
}
#define X(var_name,condition,func_name,sel_id) int var_name;
Ultron_implementation
Autobot_implementation
#undef X
void main_loop(){
#define X(var_name,condition,func_name,sel_id) \
if(condition){ \
func_name(var_name, true);\
}else{ \
func_name(var_name, false);\
}
Ultron_implementation
Autobot_implementation
#undef X
}
void query_data(int selector){
if(False){
/* Dummy block */
}
#define X(var_name,condition,func_name,sel_id) \
else if(selector == sel_id){ \
return var_name;\
}
Ultron_implementation
Autobot_implementation
#undef X
else{
return Err_code;
}
}
这个的问题在于,尽管它现在是一个统一的实现,但新组件的引入仍然需要复制粘贴,并通过先前定义的常量进行过滤(即:{{1} })现在被排除在逻辑之外。
有没有办法最大限度地减少复制粘贴到代码中各个位置的需要,并根据定义的常量进行过滤(即CFG_PROJECT
)?
答案 0 :(得分:0)
在编译时过滤到预定义的常量需要预处理器指令CFG_PROJECT
,#if
等。但是没有办法在#ifdef
语句AFAIK中使用它们。
但是,在#define
语句之外写这些内容是完全合法的。
#define
前者可以编译成一个列表(各种各样)
#if(CFG_PROJECT == cfgAutobot)
#define Autobot_implementation X(var_autobot, (third_if() > 0), update_function_2, selector_id_1)
#else
#define Autobot_implementation
#endif
#if(CFG_PROJECT == cfgUltron)
#define Ultron_implementation X(var_autobot, (third_if() > 0), update_function_2, selector_id_2)
#else
#define Ultron_implementation
#endif
根据定义的常量,#define MACRO_LIST \
Autobot_implementation \
Ultron_implementation
的元素将包含MACRO_LIST
函数定义(即:implementation)或空常量。
在实施中,现在可以使用以下内容:
X()
为了总结激活的组件,看看有多少组件被激活并在实现中引用它们,连接(void main_loop(){
#define X(var_name,condition,func_name,sel_id) \
if(condition){ \
func_name(var_name, true);\
}else{ \
func_name(var_name, false);\
}
MACRO_LIST
#undef X
}
)标记可以用于例如枚举定义。示例:
##
基本上任何相关变量,ID或实现都可以通过这种方式“序列化”。
此解决方案使代码难以理解,维护并且非常难以调试,但一旦经过测试和验证,它就消除了来自copypasting的错误可能性。结果将是一个更清晰,更优雅,更小的代码库,而不是替代品。
实际上,生产代码中的开发时间从3个月减少到几个小时。