有一天,我问一个同学说,“如果让你通过程序开发一个虚拟地球出来,模拟不同的人的行为,模拟天气,地理,人文,股票涨跌,模拟情感,思考,数学,你怎么做?”那哥们眼睛一亮,马上就说,以人为例。教师,官员,学生,工人都不一样,都从人这个基类继承!天气可以定义一个天气接口,通过工厂模式提供一组天气的集合…
我问,突然哪一天,你需要加一个字段,定义学生是不是程序员!他说,那加一个字段就好了。我说,代码都发布出去了。那哥们开始冥思苦想了。总之你发现,不可能预知未来的需求!人的类型体系,根本定义不完!鬼知道黑客帝国里的那个大胡子是怎么做到的!
如果你对这个问题感兴趣,那就请继续阅读本文。
先从类库和框架说起,类库(Library)和框架(Framework)是不同的。 类库只提供单一方面的功能,比如网络库,数学分析库。评价库的好坏,就是其性能和易用性。易用性就是别人能看懂,上手就能用,而且最好平台无关,框架无关,能用在桌面程序上,还能用在webservice上。
框架更有意思,如果类库是轮子,框架就是汽车,框架内肯定包含一组类库,承载的应用就是乘客。我们当然希望框架越强大越好,可是你怎么定义强大呢?你当然希望它足够普适!希望这套框架能不经修改,运行在不同的平台上,同时通过严密的接口和继承体系,满足我们在某一方面的所有需求。哇,听起来真不错!
类库已经不够过瘾了,现在大家都喜欢搞搞自己的框架,美其名曰XXXFramework。笔者也是这类脑残粉之一。我希望我写的传感器框架能包含所有与传感器相关的场景,希望写的数据挖掘框架包含所有可能会存在的与数据分析相关的需求。是不是很酷?但真正动手写起来,差点把我搞死。在没有明确需求的情况下,凭空写出一套普适性极强的框架,简直是不可能的任务。大家想到这里,肯定会问为什么。打个比方说,传感器有很多种,比如最简单的温度,湿度,还有复杂的心电信号,甚至你可以把股票的API抽象为一个传感器。那么,你怎么定义传感器这样的Entity?
一种做法,搞一套严密的体系,给出一堆接口(可读接口,可控制接口,需要进行功率控制的接口)和抽象类,有多少传感器就写多少种Class, 然后给别人一看,哇,漂亮的一套继承树结构!所有应用都面向抽象,看起来高端大气上档次。 我就是这么做的,但真正的情况并非如此,总有温度传感器同时提供了湿度,总有传感器会有奇怪但又特重要的参数,更何况怎么去个性化的配置这些传感器的端口,网络连接,电源管理等等的问题?最终,笔者怒写代码一寒假,头发掉了很多,发现这样的框架极其冗余,为了框架而框架, 而不论基础库写得再怎么完善,总是无法料想未来新的需求!最终走进了死胡同。
另一种做法,是直接定义一个字典Dictionary, 键是属性名,值是属性值,想要什么属性,就通过读写字典搞定了!我去!顿时发现,你原来写的那一套东西,辛辛辛苦写的继承体系,愣是不如这样的字典好用!然后怒改代码一个月,又把所有的实体类型,都改成了Dictionary, 甚至连函数的参数,都定义成了字典!爽。。。。有人说都用Object吧?那也太简单粗暴了。
我们可以认为这是是强类型和弱类型的两种极端。强类型主义者,所有的快感都来自敲键盘的”.”之后的自动提示,当然还有编译器提供的编译帮助。对弱类型主义者来说,写框架太容易了,厚厚的文档,告诉别人某字段叫什么名字,某方法怎么调用,稍微不小心就会出现运行时错误。每当我看到params object[] args这样的函数参数,就想骂人。
我们都知道,任何变量都可以被序列化和反序列化为字符串,字节流,所有的那些强弱类型,对计算机来说都是浮云,它们只是内存里的几个字节而已。不同的语言和类库,最终只是玩着字节的舞蹈,把字节串转换成另外一种字节串。所以说C语言提供了最低级的直接访问,没有类和lamda等等那些奇淫技巧。但科学界搞了这么多年的编程语言和特性,肯定不是白发明的,都肯定有其自己的道理。
程序员都有这样的理想,你就是国王,管理着你的都城:它有着完整的排水,供暖和交通网络,有着严密的组织结构,每个成员都各司其职,整个系统稳健又高效。想象这样一套系统,真是让人激动的战战发抖。可是当写了这么多的代码,走了这么多的弯路,最终你其实发现,你永远在复杂性和简单性之间做平衡,在抽象和具体之间做平衡,在继承和组合之间做平衡,在强类型和弱类型之间做平衡。
对绝大多数程序员来说,想写一套好类库可以,但写好一套通用的基础框架几乎不可能。原因是,当你使用强类型构建底层时,后期的继承体系会让你负重不堪。用弱类型方法构建之后,却发现你走上了中国哲学的虚空之路,一切皆虚。 越通用的“框架”,就意味着它的底层几乎无所作为,上层开发者看着脚下的空气,苦笑着另开炉灶。所以,框架是和需求紧密相关的,在需求不确定的情况下,覆盖所有可能的场景?笑!
哲学和数学是万物之根, 程序员是现代最接近于哲学家和数学家的职业。从哲学演绎出了政治,经济等人文知识。而自然哲学与数学结合,产生了解释万物运作的物理学。计算机科学从另外一种角度将人类的知识体系展示了出来,算法本身需要数学的精密,数据结构和软件架构则无不体现着哲学的智慧。如同政治哲学指导人类建立都城和政权一样,计算机哲学帮助程序员建立了接口抽象,松耦合,高内聚等基本观点。本来,把理论实践出来将花费很大的成本(想象你要盖一座高楼),程序则成为几乎是最低成本的实践哲学和数学的机会。
曾经有人说,函数式编程更接近于世界的本质,现在想来也是,每种实体的属性,都是我们因为问题和需求人为强加进去的,世界的本质是作用和函数,是纯弱类型的。我们之所以发明强类型,是因为强类型更接近人的思考模式,更方便维护。你认可这点吗?
回到开头的问题,现有的编程语言和工具,几乎根本不可能构造出一个虚拟地球!原有的那些设计模式,在这样一种空泛而宏大的需求下如同雕虫小技,完全无济于事。现有的工具无法自动生成新工具(没有自学习功能)。 再想象一下人脑,人脑从来没有定义任何的实体类型和接口,没有任何的属性,纯粹靠着一个网络和网络间的交互,却构建出如此精密的的机器出来! 如此看来,我们的技术,实在太原始了!
虚拟地球的理想,只能通过弱类型来定义了,如同我喜欢用字典来表现对象,认为一般的实体对象本质就是键值对。某些工具能够在某些程度构造一个虚拟地球,我猜那是矩阵,矩阵是自带了X,Y两种索引值的键值对,多个矩阵能构成物体,物体之间的作用可以表达为矩阵之间的运算,作用产生的新矩阵还可以再被处理。如同IEnumerable接口可实现运算链一样,矩阵也能做到。矩阵内部还可以再镶嵌子矩阵,以描述对象的包含结构。我们的理想,就靠矩阵了! 想想黑客帝国, 想想matlab!!
笔者写到这里都要困死了,那种写通用框架的想法,先抛到脑后吧,我不是微软,写不了像WPF这种牛逼的框架,那种十几个个类串下来的继承结构,只有闲的蛋疼的人才会去仔细分析。以后我再也不敢去写什么框架了,只敢写库了,简单好用,满足需求提供功能就够了。那种统一的思想,丢给那些哲学家吧,我不干了….