大家在工作中也许会碰到这样的情况,一个C语言程序,可能有十几万行代码,读取上百张的数据表,还要处理N多的业务逻辑
当你和你的小组实现了这样一个系统之后,它工作的很好,这时,大家都长舒了一口气.可是,哪知道恶梦才刚刚开始.
突然有一天,客户会提出新的需求,通知要你新加一个功能,你不得不在程序里的初始化函数里,处理业务逻辑的函数里,还有扫尾的函数里都加上你要新添加的功能代码,当然添加这三处地方也许只是最少的情况,更多的情况下,需要你做更多的工作.
所以,这就需要我们把这些工作的共性抽象出来,形成一个类似框架的东西.提高程序的可维护性和可扩展性.现在我就想完成这样一个东西.虽然可能会很难,自己水平也不是很高,可能会失败,但就当是投石问路吧…
设计的思想是把每项的一个功能都看成是一个component,每一个component都有自己独立的初始化函数,业务处理函数,和扫尾的函数等.还可以根据配置文件来配置管理组件和一些基础设施,可能会提供一种机制来管理这些组件和基础设施.然后会有一些函数来实现IOC,把复杂性委托给"框架".让"框架"来管理这些组件的具体实现.这有点像C语言版的Spring,呵呵…
下面的函数是我实现这个框架的第一步:
方法很简单
/*---------------定义一个要实现的功能的头文件imp.h-------------*/
#ifndef _IMP_H
#define _IMP_H
/*参数是传入自身的”引用”*/
void do_before(struct TestStruct* t);
void prcess (struct TestStruct* t,int i);
void do_after(struct TestStruct* t)
#endif
/*-------------组件的声明struct.c------------*/
#ifndef _STRUCT_H
#define _STRUCT_H
/*这个就代表了一个组件,注意函数指针名字和刚才定义的名字一致*/
struct TestStruct
{
int i; //业务逻辑需要的一些变量
int j;
void ( * do_before)(struct TestStruct *);
void ( * prcess)(struct TestStruct *,int);
void do_after(struct TestStruct* t)
};
#endif
/*-----------------main函数调用:--------------*/
#include "struct.h"
#include "imp.h"
struct TestStruct ts1={
. do_before = do_before, //把imp.h里函数传入
.process = process,
. do_after = do_after,
};
void main_init(struct TestStruct *); //一个测试函数
int main(void)
{
/* 声明*/
struct TestStruct * test;
void (*_main_ before)(struct TestStruct *);
void (*_main_ process)(struct TestStruct *);
void (*_main_ after)(struct TestStruct *);
/*初始化*/
ts1.i = 10;
ts1.j = 20;
test = &ts1;
_main_before = main_init
_main_process = main_process
_main_after = main_after
/*使用*/
_main_ before (test…..);
_main_ process(test…..);
_main_ after (test….);
}
void mian_init (struct TestStruct * test)
{
printf("before add\n");
test->do_before(&ts1);
}
总结:这是程序的第一个版本, 它并没有给程序带来什么实质性的改变,函数指针的使用使程序变的难以理解,甚至还没有直接实现来的直观,方便.而且, 像_main_ before (test…..);这个函数,到模块多了以后,参数列表会很长.这个版本仅仅是规定了一个函数调用的契约,而且是要程序员自己必须要自己去注意这个契约,契约要求每实现一个功能都需要定义一个结构体,结构体里面会有它要使用的变量和操作.所以,这个实现和刚开始提出的目标还有很大的差距.
PS:关于框架这种东西,我觉得框架内部结构复杂是可以接受的…关键的是要向使用者隐藏这种复杂性.
C语言没有提供面向对象语言那种数据的封装,但是我们可以自己实现一种方式来达到同样的效果.也许有人会觉得用结构化语言去模仿面向对象语言的特性完全没有必要,但是事实是:现在仍然有很多关键的应用需要用到C语言.所以,我们可以通过解决问题一次,就重复运用解决这类问题办法来解决再次出现的类似的问题.
在下一个版本中,我想做如下的改进:
1) 想办法让C语言也能在运行时动态确定调用函数.这样话.就不用我们手动去指定调用哪个函数了…而是通过一个配置文件…但是好像C语言要这样搞会很难,唉…可惜不是java
2) 而参数列表会很长的问题应该能很好解决…