工具类是好的。提供机制但不提供策略,这是一个linux的编程哲学。我原来提到过,在某篇文章中看过GoF中的Gamma现在也更喜欢库而不是框架。
我现在编程已经不太看重这些了,当然因为必须在现有的语言、库和工具下工作,很自然的就会经常性的形成类似于框架的东西,但是我会经常问自己是否能够避免:如果去框架化不会带来更多的麻烦,我就会把它拆掉。
认知
那框架完全是废物吗?非也。能产生这种东西,就表明它必定有它自己的用途。我们有一个业务,这个业务有它自己的模型、规则、流程等等。但是有些不确定的东西会未来才接进来,那么我们就非得有一个框架不可:比如图形界面就是这样。【1】
不过更多时候我发现事情真的有更简单的办法,把机制或者功能集合中的一些元素粘合一下,这样很简单,产生变化的时候重构的工作量也小。而且并不影响重用,或者说能够更好的重用(因为各部分粒度比较小)。
关键是真正认识我们要处理的业务的实质是什么。这个实质不是指这个业务对人类来说是什么,而是说这个业务在现有的不能抛弃的抽象层上是什么。
对我当前的目标(记住这是可变化的)而言,这个抽象层包括计算机本身、操作系统、基础库和通用的协议。要注意的是,抽象层在某种意义上并不是真的抽象,而是一种具体化。比如你有2G内存,而不是无限的图灵机纸带,比如硬盘很慢;比如软件根据实际情况做出的妥协。
看起来四处都是抽象层,所以上面强调了,“不能抛弃”。过去我很擅长.NET,.NET及围绕它产生的一系列环境是我用过的可以说最舒服的编程基础设施。我也对ASP.NET极其熟悉,基本上可以弄清楚每一个细节。但我最终学会的一件事就是它不是一个不能抛弃的部分。
这说到最后,还是它提供的东西带来的便捷和它按照它的作者的意愿具体化的部分带来的限制或麻烦之间的一个权衡。所有的Web业务从根本上就是按照一定的协议和文档格式(比如HTTP/HTML,又是一个抽象层,但我们不能抛弃,否则没人能用我们的东西)根据参数生成字符串的这么一件事情。
决策
当HTTP和HTML这些东西设计定稿的时候,可以说所有的规划就做完了:在这个基础上有足够的约定和共识落在了纸面上,最后又变成了机制和策略。只要不破坏他们,事情就玩的转;剩下的东西就是多加进去的(这和图形界面框架的必要性形成了一个对比),就必须“给个理由先”。
很多人不愿意这样看问题,包括最初我沉溺在ASP.NET中的时候。因为这会让我们感觉回到了ASP时代,是一种倒退;如果跟别人交流,看起来好像我们土的掉渣、不求上进。我不知道我们是如何产生这种感情的,也许是因为在我们经验比较少的时候,我们就会不够自信、不够坚定。【2】
有一点也是必须要认识到的,不回答这个问题,我们不能说服自己:大家都在用ASP.NET或XX。这其实也就说明了ASP.NET是给谁做的。更多的,我们就必须回答:我当下处境和“大家”一样吗?这个答案决定了我们要不要动手去做:也就说,技术选型。既然有这个词,就有这个词对应的工作量。
对于这个词需要明确的是,我们选的是“型”,而不是若干个成品。只有比较“型”和成品的符合程度,才能得出结论:也许是在人家的框架上做一些库就非常舒服了,也许是做一个自己的框架,更加适合自己的需求。或者不定义任何策略,提供一堆机制,根据问题现场组装。
现在我们决定做一个框架了,我们一直在用ASP.NET,关键是我们在一个别人画的圈子里,玩不出太大的花来。当然,我们的目的不是玩花,而是肯定先要感受到需求。那么我感受到需求了,我觉得ASP.NET束缚了我,我怎么办呢?
执行
首先明确一点:如果说我们承认框架是有用的,我认为框架也应该尽量小(或者尽量空),大多数情况下应该属于可以以较小代价推翻的东西。
而且一个值得注意的要点是,不能把功能和它揉在一起做;因为这样我们会最大概率的得到Linus所谓“漂亮的坚固堡垒”,碰着点真正的(相对于假设的)变化就会歇菜。一个个人经验是,更加重视局部输入输出的明确简单,少玩精巧的对象交互,使组织部分成为一个灵活的粘合层。
具体到要在ASP.NET下做真正的框架,我的建议是从Handler和Module上做,不要用一切微软制订的更上层的东西:WebForm、MVC,这对于框架作者来说不是什么有用的东西,它们逼你削足适履。
我们首先要有自由,才能够把需求让我们产生的那个想象的东西按它本来应该有的样子画出来。另一方面是信心,我们总会有这样那样的顾虑让人裹足不前。
有些人觉得编译器难写、操作系统难写;有些人觉得ASP.NET的作者们写的那些东西难写。我能说的是,凡是ASP.NET实现了的东西,都是没有什么难度的(这就使得工作变得可评估)。无论从技术细节上来说,还是从设计上来说。
对于后者,恰恰仅仅是ASP.NET的作者们,他们自己收集了若干需求,然后产生了一些这个东西应该这样那样的想法。我们不应该被这些影响:除非我们不确信我们的需求是真的,否则我们就不会做出比他们更差的决定。尤其是目标越明确越具体,我们的设计就会越有优越性。
在这个基础上,信心怎么来呢?我们不启动,老在那里准备,永远没有信心。事实上从最初开始,比如继承一下Handler的接口,打印一行Hello world,就能极大的增强信心:剩下的事情就是如何把这行字换成更有用的东西:这部分如何组织,这就是你的框架了。
最后
当然,我们必须有明确的需求,而不是受了别人的影响就说我要做一个MVC、我要更好玩转那些Entities;我们读到的东西更多的是一种参考,有启发就想想没有就暂时扔掉。关键是说我有一个点子,它能让我们生活(至少是我眼前关注的这块业务)的更容易;就是这样。
------
注【1】:比较图形界面框架和图形库的区别就可以知道,前者为了最终用户有一个直观、统一的感受,必须先规划一些东西。
注【2】:话说回来,如果一开始就自信满满,也可能会错过很多东西,最终真的变成一个老冒也不一定。有的时候反复的过程是必要的:有人也许天生能做到极其快速直接的筛选出有用信息排除无用的;但至少我知道我自己是很笨的,很多时候都得试一试才能学到点什么。当然,笨人也可以慢慢掌握更好的判断方法。