人們總是偏愛“大詞”。一個表達方式,如果聽起來足夠響亮,寫在紙上能夠吸引眼球,那就會變成很多人的新寵。但同樣是這些大詞,經過太多人的傳遞、消費之后,原本的含義反而像硬幣上的圖案一樣被磨損殆盡:幾乎沒有人知道這些說法到底是指什么了。在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)。那意思是說,沒有一種萬應藥能夠戲劇性地提升軟件開發的效率和質量。最近的很多輿論好像是專門和這個經典論述抬杠,動不動就把一些特殊的解決方案奉為銀彈。對于企業應用開發而言,基于框架的開發模式是多種選擇中的一種。在不少情況下,這種選擇是不錯的,但同時應該留意隨之而來的風險,更不該以為,選定了框架就一定能保證項目成功。
很多企業應用項目的難點,在于客戶自身缺乏規范的企業管理制度和合格的計算機應用水平。客戶不具備成型的業務流程,也無法明晰表達需求,不知道怎樣的應用形式對自身業務更合理:這種需求不清、或是需求劇烈變更的困境是困擾大量企業應用開發項目的癥結。簡言之,企業應用項目的成敗經常是“業務”、“技術”、“管理”三種因素共同作用的結果,而單純引入框架,只能解決部分“技術問題”。如果過于樂觀地估計框架在其中的作用,甚至認為它能解決任何項目的任何問題,這對于本領域的各個環節(廠商、項目開發商、企業客戶)都只能起到消極作用。
我個人的建議是:在搭建企業應用系統時,針對應用情況不同、預算/時限不同、對系統指標要求不同,有多種替代方案可以從中選擇。當需求明確、固定,又有現成產品完全滿足需要時,或者當企業想要以極低預算消除某個業務瓶頸時,應該優先考慮現成產品;在需求明確、固定,但很難被現成產品完全覆蓋時,可以選擇應用框架,并由合格開發商完成實施;在需求不夠明確,或者預感到需求會發生劇烈變更時,采用開發源碼的應用框架,從而避免高昂的初期投資,并“軟化”框架帶來的種種限制,是另一種可供選擇的思路。還是那個比方,一頓飯怎么吃,究竟是下館子、買半成品或者全由自己動手,還要視具體情形而定——我也希望,每個企業都能吃上可口順心的應用大餐。