分类:
2007-10-15 16:23:17
在插件系统中,每一个插件都有自己的一些配置信息,比如说图标信息、界面显示信息等。如果以前做了一个插件,发现另外一个插件和它的功能差不多的时候该怎么办呢?可以用配置文件将不同的地方描述出来,也可以在以前的基础上做一个派生类。到底是用配置还是用派生,这个问题就有趣了。
中国特色的软件产品就是地区版本多,同样一件事情每个地方规则都不一样。比如说做了一个功能,在北京用没有问题,拿到上海去就不符合要求了。地区特性要求我们的软件必须要响应变化。
出现变化后的第一个反应就是OO了。有着各式各样的设计模式来教我们怎样利用OO的特性来应对变化。
比如说现在需要一个计算个人所得税的模块。
计算的思路都是一样的,但由于地区经济的差异,所以在有些数据上各个地方会略有不同。
按照OO的思想来考虑,我们可以做一个计算的基类,利用模板方法将各地不同的地方做成虚函数。基类中处理具体计算的算法,派生类中处理地区差异,比如说各地的税收起征额不同。在到具体地区实施时只需要选择不同的派生类就可以了。并且也非常方便扩展。如下面的TaxCalculator1。
同时也有另外一种思路,在TaxCalculator2中没有什么虚函数,也不存在派生类,不过它运行的时候需要一个配置文件,在配置文件中描述地区差异。
当然,这里说的是一种非常简单的情况,在实际的应用中比这个要复杂的多。
就上面分析的来看,似乎用派生和配置两种方案都可以。如果是OO思想的“崇拜者”很可能觉得第一种方法更好,因为第二种方法不是面向对象的思路。
在项目中遇到这个问题时,是和插件机制联系起来的。也就是说插件之间从逻辑上讲是“派生”的关系(一个插件为一个DLL文件)。如果按照类派生的方式来处理,则需要将不同的派生类分别编译成不同的DLL发布出去;如果用配置文件则只需要发布一个DLL文件另外附加上不同的配置文件。
从插件发布的角度考虑,用配置文件的代价要更小。所以在实际的项目中,采用第二种方式居多。并且在非插件系统中用派生方式实现的模块也尽量考虑用配置文件的方案。
其实在这里我考虑的最主要的因素是“成本”,分为下面两个部分。
用派生的方式实现,在维护期间需要维护的是代码;用配置文件的方式实现,在维护期间代码不需要维护,只需要改变配置就可以满足要求。我们认为维护代码的成本比维护配置的成本要高。
用派生实现,需要发布给用户多个DLL文件;用配置文件实现,需要发布给用户一个DLL文件,多个配置文件。我们认为发布DLL的成本比发布配置文件的成本要高。
结合上面的成本因素来考虑,用配置文件的成本要低,所以选择这种方式。
我们的产品是什么?以前很直观的认为程序员的产品就是代码。
代码和设计文档、计划文档一样都不是最终产品,它们都属于文档的范畴。最终生成产品的不是我们程序员,而是编译器。代码是一种文档,编译后生成的二进制文件才是产品。
在项目中,我们会考虑从设计文档到代码需要的成本,但极少考虑从代码到二进制需要的成本。原因很简单,因为从代码到二进制的过程太廉价了。通常我们不需要考虑编译过程的成本因素。
由此来看,上面提到的“发布成本”是可以忽略不计的。
关于维护成本这一点,就是仁者见仁,智者见智了。
有的人就喜欢读代码:) 所以很难说维护代码和维护配置文件那一个成本高了。不过有一点没有争议,那就是到了用户那边,二进制文件可是没有办法改的了。
有些喜欢刨根究底的人就会进一步钻牛角尖,就像我一样。
如果用动态语言又会是什么样的情况呢?
因为动态语言不需要编译成二进制文件,所以它就是一种可以运行的文档了。可以将我们系统中的配置文件当作动态语言的一种,不过它只能决定简单的行为。因为配置文件毕竟不支持“封装”、“继承”和“多态”。用真的动态语言的话,既可以得到配置文件灵活的优势,又可以得到编程语言强大的功能。
从这点来看,动态语言在这个场合还是非常有用的。