人们总是偏爱“大词”。一个表达方式,如果听起来足够响亮,写在纸上能够吸引眼球,那就会变成很多人的新宠。但同样是这些大词,经过太多人的传递、消费之后,原本的含义反而像硬币上的图案一样被磨损殆尽:几乎没有人知道这些说法到底是指什么了。在IT业界,“平台(platform)”、“框架(framework)”、“构架(architecture)”等等就是这种人见人爱的大词。几乎每个厂商都愿意请来其中的一位、甚至多位为自己推销。久而久之,这些说法似乎适用于各个领域、各个层面:所有的软件系统都是“平台”,所有的开发者都在自矜于独有的“框架”。原本有确切意义的“好词”,经过这一番争夺和滥用,也只能衰减为所谓的“buzzwords”,供市场营销人士们玩味了。
我想让这些词中的一个——“框架”——荡污涤垢,重现青春。要完成这样的任务,必须动用重典才行。软件业圣经《设计模式》对框架有如下定义:“A framework is a set of cooperating classes that make up a reusable design for a specific class of software(一个框架,就是一组相互协作的类,对于特定的一类软件,框架构成了一种可重用的设计)”。这个定义虽然主要着眼于面向对象的软件开发,但已经基本上给出了这个词的核心含义:框架是软件系统的设计、开发过程中的一个概念,它强调对以完成的设计、代码的重复使用,并且,一个框架主要适用于实现某一特定类型的软件系统。
为了更好地说明框架是什么,也许还应该看看框架不是什么。
框架不是现成可用的应用系统。它仍是一个半成品,等待后来者做“二次开发”,实现为具体的应用系统。
框架不是“平台”。后者的概念更加浮泛和模糊——人们说的一个平台,可以是一种操作系统,一种应用服务器,一种数据库软件,一种通信中间件等等,因此“平台”几乎成了所有系统软件的统称。在平台的大家族中,框架的概念可能与近来人们常说的“应用平台”最为接近,但平台主要指提供特定服务的系统软件,而框架则更侧重于设计、开发过程,或者可以说,框架通过调用平台提供的服务而起作用。
框架不是工具包(toolkit)/类库(library) /API。目前流行的很多框架中,就包括了大量的类库和API,但是调用API并不就是在使用框架开发。仅仅使用API时,开发者完成系统的主体部分,并不时地调用类库实现特定任务。而框架构成了通用的、具有一般性的系统主体部分,“二次开发者”只是像做填空题一样,根据具体业务,完成特定应用系统中与众不同特殊的部分。
框架不是构架(architecture)。构架确定了系统整体结构、层次划分、不同部分之间的协作等设计考虑。框架比构架更具体,更偏重于技术实现。确定框架后,构架也随之确定,而对于同一种构架(比如web开发中的MVC),可以通过多种框架(比如Apache Struts或Apache Velocity)实现。
2
那么,在企业应用系统开发中,框架具有什么样的意义?要阐明这一点,大概要看一看在这个领域里软件开发方式的演变。在计算机应用普及之前,只有少数大企业才负担得起企业信息系统软件,这一类的软件开发也已委托定制(custom-made software)为主。在企业信息化基础设施逐步完备之后,多数中、小企业也要在预算不高的前提下实施企业应用系统,按照以前的方式逐个定制开发,是这种类型的企业难以承受的。因此,对于一些需求简明的系统,往往会购买现成软件(shrink-wrapped software)解决问题。但是各个企业具体业务不同,需求很难统一,现成软件只能满足最通用的情况和最一致的操作(比如财会系统、网站内容发布系统等),对于头绪众多的业务处理就难以胜任了。
如何最大程度地萃取不同企业应用系统的共性,重复使用已经完成的设计和代码,对企业应用系统中典型场景给出最佳解决方案——这是一个“一般性”的问题;如何让一个早先完成的软件产品贴切地适应极为多变、复杂的企业需求——这是一个“特殊性”的问题。作为对这一组冲突的一种解决方案,不少厂商推出了自己的企业应用框架。这些框架往往是从大量的委托项目开发中精选出的系统“不变项”,因此具有很强的普适性和实用性。
目前,主流企业应用框架中大都包含对以下问题的现成解决方案:
* 持久性(persistence):实现数据存储、处理,数据与对象映射,数据缓存(caching)。
* 事务(transaction):确保一组关联操作正常、完整的执行。
* 安全性(security):保证系统的通信安全、数据安全。
* 负载均衡(load balance):在大量并发访问时,保持系统可用。
* 监控(system monitoring/management):监控系统运行状况,设置系统参数。
* 日志(logging):记录系统运行情况和异常,记录特定用户操作。
* 应用集成 (application integration):与其他系统、应用程序集成。
* 认证/权限/组织角色管理(authentication/authorization):管理系统用户、组织职权结构,限制特定用户对特定功能、特定数据的访问。
* 业务模型(domain model):管理系统中业务对象的属性、字段。
* 业务逻辑(business logic/rules):实现业务规则和业务逻辑。
* 工作流(work flow):实现多用户、多环节之间的业务处理流程。
* 文件管理(file management):管理文档,实现系统内部的文件传递。
* 报表/打印 (reporting/printing):实现数据打印,实现报表的定制和输出。
* 门户/信息发布 (portal solution):发布企业相关的信息、新闻,提供企业客户的访问入口。
* 通信(communication/messaging):系统内部的消息、通知;系统与外部角色(比如企业客户)之间通过不同通信媒介(电话、网站、邮件等)的互动。
* 特定行业/领域模块 (business modules):实现特定行业、流域相关的业务模块。
以上诸方面中,除了前四项目前主要由应用服务器解决之外,其他的部分本身都是专门的软件开发领域。框架的作用,在于确定上述每种因素的具体技术实现,并规定它们在系统中的组织方式和协作方式,从而给出完整的企业应用解决方案。
企业应用框架的特点首先是,当应用框架确定之后,系统的整个构架,也就是主体结构就已经固定。因此框架的选取往往是方案选型的首要问题。
其次,人们常常听信“组件式开发”的一面之词,认为系统搭建的过程类似于搭积木,好像是用胶水代码(glue code)拼合现成的组件或模块。其实采用框架开发时,系统的构建过程更类似于填空——系统骨架早已完成,开发者填写特定的代码,由系统来调用。《设计模式》中提到的“好莱坞原则(the Hollywood principle——Don't call us, we'll call you)”,非常符合我们谈的这种情况。很多框架还允许下游厂商开发系统插件(plug-ins),以满足特定需要——这是另一种形式的“填空”。
另外,对于实现具体应用系统的二次开发者来说,不少任务都无需通过编程实现。比如要给一个业务模型增添一个新字段,或是要设置一种新的工作流程,这些工作都可以通过简单的图形用户界面(GUI)操作,或是修改部署描述符(DD),或是编写脚本来完成。也就是说,相当多(而不是全部)的开发任务是通过声明/配置的(declarative),而不是编程的(programmatic)的方式实现的。系统往往会在启动或运行时载入相关的配置,据此实现特定的功能。
企业应用框架是菜场里的半成品。当我们面对要么自己下厨、要么去饭馆吃饭的选择时,我们往往会采取这种省时省力的折衷方案。但是选择之所以为选择,就因为其中肯定包含对收益和代价的权衡,都隐含着复杂的利弊关系(pros and cons)。下面我们也来检讨一下企业应用框架的情况:
Pros:
* 缩短开发周期
毫无疑问,采用框架的开发,要比一切从头做起快速、高效得多。通过一般化(generalization)和重用(reuse)机制,框架能最大限度地加快一个特定应用系统的实现。
* 客户化
如上所述,基于框架的系统有很多功能通过配置而不是编程实现,这样也给用户带来了一定便利。比如,企业内部的IT人员经过一定培训,就能够自己完成一种新的工作流程的设置。这对于不断变化的业务需求是一个很理想的解决方案。
* 不重新发明轮子
框架对于大量典型场景给出了最优的实践。在具体开发时,与其无视前人的成果,重新构思答案,不如套用这些成熟、稳定的做法。这不仅能加快开发进度,更能够提升系统的质量和健壮性。
* 可维护性/知识共享
完全通过委托开发完成的系统很难由其他厂商维护。框架往往是多个企业、大量开发者实践的成果,因此能在一定程度上打破上述壁垒,增进系统的可维护性。当框架使用者形成社区之后,还能实现更高层次上的知识共享。
Cons:
* 太多
半成品总有其代价。超市配好的一包菜里,老是又我们用不到的调料——但是我们却不得不为之付费。同样,为了达到一般性和普适性,框架总比紧凑、贴切的特定应用多出不少内容。二次开发完成后,企业获得的只是一种特定的实现,却要为所有的客户化可能性付费,为所有用不上的功能付费。这是一个相当让人尴尬的事实。
* 太少
框架总是一种限制。就像半成品菜限制了我们的烹调方法,框架也限制了我们实际应用的可能性。当框架本身设计的足够普适时,我们不太会感到类似的限制。但是,情况往往正好相反——面对一个足够特殊的需求,二次开发者总有一种冲破框架的渴望。最后的解决办法,往往是狡计、妥协和框架补丁的结合体。
* 效率
上面说过,基于框架的系统中,具体功能经常是通过配置实现的。与硬编码(hard-coded)的方式相比较,这虽然能提供很大的灵活性,但也往往牺牲了运行时的效率。
* 锁定
一个采用特定框架的系统几乎肯定被锁定在这个厂商的产品上。换言之,框架意味着all or nothing式的态度,很难调和两种不同的框架,各取所长,更难把应用系统从一个框架迁移到另一个——这往往要求系统的全部改写。
* 学习曲线
一种框架也就是一种方言。要精通特定框架的开发,你要熟悉其中的所有的用法、思路和弱点。对于开发者,这也意味着比较陡峭的学习曲线。
3
上面谈到的种种弊端,还属于一般开发框架共有的缺陷。对于市面上流行的很多企业应用框架来说,更大的问题是框架产品自身的价格过高。我在别处也讲过,企业应用系统项目往往不能靠运行安装程序,再作简单的设置就完成,而是一个复杂、漫长、不断尝试/修改的过程,或者说,更近似于一种服务而不是简单的产品销售。但是框架厂商的产品(或者说是半成品)价格过高,经常就蚕食了整个系统的大部分开发预算,使方案总价偏重于框架本身而不是后期开发。对于需求不甚符合原有框架,需要大量开发的项目,或是需求本身不够清晰的项目,这都几乎肯定会导致整个项目的失败。
软件工程宗师F. Brooks曾经表述过这样一个道理:没有银弹(No Silver Bullet/NSB)。那意思是说,没有一种万应药能够戏剧性地提升软件开发的效率和质量。最近的很多舆论好像是专门和这个经典论述抬杠,动不动就把一些特殊的解决方案奉为银弹。对于企业应用开发而言,基于框架的开发模式是多种选择中的一种。在不少情况下,这种选择是不错的,但同时应该留意随之而来的风险,更不该以为,选定了框架就一定能保证项目成功。
很多企业应用项目的难点,在于客户自身缺乏规范的企业管理制度和合格的计算机应用水平。客户不具备成型的业务流程,也无法明晰表达需求,不知道怎样的应用形式对自身业务更合理:这种需求不清、或是需求剧烈变更的困境是困扰大量企业应用开发项目的症结。简言之,企业应用项目的成败经常是“业务”、“技术”、“管理”三种因素共同作用的结果,而单纯引入框架,只能解决部分“技术问题”。如果过于乐观地估计框架在其中的作用,甚至认为它能解决任何项目的任何问题,这对于本领域的各个环节(厂商、项目开发商、企业客户)都只能起到消极作用。
我个人的建议是:在搭建企业应用系统时,针对应用情况不同、预算/时限不同、对系统指标要求不同,有多种替代方案可以从中选择。当需求明确、固定,又有现成产品完全满足需要时,或者当企业想要以极低预算消除某个业务瓶颈时,应该优先考虑现成产品;在需求明确、固定,但很难被现成产品完全覆盖时,可以选择应用框架,并由合格开发商完成实施;在需求不够明确,或者预感到需求会发生剧烈变更时,采用开发源码的应用框架,从而避免高昂的初期投资,并“软化”框架带来的种种限制,是另一种可供选择的思路。还是那个比方,一顿饭怎么吃,究竟是下馆子、买半成品或者全由自己动手,还要视具体情形而定——我也希望,每个企业都能吃上可口顺心的应用大餐。