就如“最正确的真理是句废话”一样,通用与专用是程序员永远无法摆脱的矛盾。
专用与通用的概念
专用,无非就是定制,是以诸多事先确定的规范为前提,来解决某个问题。专用设计目标明确,无需过多考虑并未出现的隐藏需求,因此此类设计效率较高。
但正是这些前提的限制,让整个系统的灵活性大大降低,不仅使整个系统的后期维护陷入一个指数型增长的高成本维护阶段,而且整个系统的设计无法直接解决其它问题,从而造成资源的极大浪费。
那么通用意味着什么呢?答案很简单,复用。通用的设计使诸多属于专用的概念得到统一,以让它们适应现在和未来的其它专用系统,这样的设计不仅可以让系统具有高度的灵活性,便于后期维护,而且,统一抽象出的概念可以应用于其它系统,使资源得到重复利用。
但是,通用系统的设计需要额外的成本,且应用到专用系统时,由于其统一的设计,其不需要的特性一样会被带入到专用系统当中,造成设计浪费(也叫过度设计)。
专用与通用的本质
在实际设计中,他们两个总是相互依存、相互配合来完成我们的任务的,软件工程出现之前,系统的设计与开发只是小范围的定制与维护,有很强的针对性。但随着软件系统的复杂化加剧,人们开始把设计重点偏向了通用设计――当然这也是软件工程所倡导的,而就在不知不觉中,人们似乎又走向了另一个极端。
“不要重复发明轮子”的呼声伴随各类框架蜂拥而至,让人眼花缭乱,一个不留神,就会掉进盲目权衡的陷阱而不能自拔;众多有实力的公司,也早已开始着力开发几乎适合整个市场的通用产品,打着各种各样的概念旗号,报着名不副实的高价;而开发工具厂商也是以通吃各种环境为目标来抢占市场。
在享受高度封装性带来的便捷的同时,人们发现,越来越上层的通用概念带来却是更长的学习曲线、更多的学习成本,因此我们不得不费尽心机,在重新定向开发与学习通用系统间徘徊。
很多时候,我们并不能准确的把握专用与通用的界限,为什么?因为这两个概念本来就是一个相对的定义。我们不妨来简单表示一下两者的依存关系,在这里我暂且叫它软件系统结构概念图,如下:
从图中来看,除了最上方的成型系统,其下的模块均为通用模块,那么将其推广到广义上讲,其下层必然是上层的通用系统。比如微指令与汇编、汇编与原生高级程序语言(C/C++等)、编程语言与COM组件、控件组与网站通用模块。因此所谓的通用仅仅是在某种程度上对诸多专用特性的抽象,专用则只是依附于其相对意义上的通用系统而建立的。
成本与风险
软件开发是存在成本与风险的,降低这两者,从而获取最大利润,是所有软件企业的最终目标,作为影响到整个软件系统方向的两个因素,专用与通用的成本与风险就必须得到重视。
专用设计成本主要来自重复开发特定模块的资源耗费,以及低灵活度带来的资源浪费。而风险则来自于后期系统变化的不确定性。
通用设计在某种意义上与专用设计相反,它的成本主要来自于上层抽象所耗费的资源,而其风险则体现在过度设计的控制。
我们的任务
作为一个可以稳定发展和进步的体系,必然是一个矛盾体,两个矛盾面互相制约又互相依存,从而推动整个体系的发展。
软件系统也是一样,在整个软件体系中,随着层次的升高,专用成本越来越低,而通用成本则越来越高,因此我们要做的关键,就是寻找通用设计或者专用设计的着力点,亦即专用成本与通用成本的平衡点。
轻型解决方案――敏捷/XP方式
既然我们需要寻找两者之间的平衡点,那么在一个阶段,必然会出现一些这种的方法,以满足大部分开发需要。从目前软件的开发规模来看,敏捷/XP方式不失为一种兼顾专用设计与通用设计的优秀开发方式。
它所具有的“小型发布”、“简单设计”、“测试先行”等方法有效的发挥了专用设计的优势,注重直接需求的设计(即用户既定需求),将通用设计成本与风险降到最低;而“重构”、“编码标准”等方法则体现了通用设计的复用优势,保持软件高质量、简洁、健壮,从而为变化而设计。
程序员会失业吗?
首先回答这个问题,不会。
随着开发工具的抽象层次越来越高,一个层次的开发工作会逐渐被工具替代,该层次的代码工会越来越少,但他们不会消失,因为每个层次都需要少量的程序员来支撑专用设计,而更多的程序员则会在此基础上,走向更上层的通用设计,并在一定的层次停留下来,做该层次的专用设计。
程序员的工作是使用各种计算机工具来解决用户的需求,他们的天职是解决问题(当然包括用户的和自己的),所以,程序员会被工具代替或者所谓的写程序不用人的传言终将会在理性中破灭。
后记:1和0注定了软件是一个权衡的产业,把握这个产业就是把握平衡点,而专用与通用则是这个产业最上层的矛盾。