敏捷與結(jié)構(gòu)性模塊化(一)
1 簡介
敏捷開發(fā)方法論日益流行,然而大多數(shù)“敏捷”專家和分析師都在孤立地討論敏捷,也就是說忽視了系統(tǒng)“結(jié)構(gòu)”(Kirk Knoernschild是一個例外,他編寫了一本名為《Java Application Architecture》的圖書闡述這一理念)??紤]到“敏捷”是基礎(chǔ)實體的一個重要特性或?qū)傩?,那么,這種疏忽令人感到很驚訝。一個實體要具有“敏捷”的特性,它必須具有高度的結(jié)構(gòu)性模塊化(structural modularity)特征(參見Scott Page的《Diversity & Complexity》)。
也許正因為這種疏忽,許多組織在敏捷開發(fā)流程方面進行投入但忽略了應(yīng)用程序的結(jié)構(gòu)。除了“如何實現(xiàn)一個敏捷的系統(tǒng)?”這個問題以外, 有人肯定還會問, “如何構(gòu)建一個在結(jié)構(gòu)上具備高度模塊化的系統(tǒng)?”
這個系列的文章將從探討結(jié)構(gòu)性模塊化和敏捷之間的關(guān)系開始。
2 結(jié)構(gòu)、模塊化與敏捷
業(yè)務(wù)主管和應(yīng)用開發(fā)人員經(jīng)常面臨相同的挑戰(zhàn)。無論是商業(yè)領(lǐng)域還是服務(wù)于商業(yè)的軟件,它都必須在成本范圍內(nèi)構(gòu)建和維護。如果要保持實體的持續(xù)運營,就必須能夠以低成本的方式快速響應(yīng)難以預(yù)料的變化。
如果我們希望高效地管理一個系統(tǒng),就必須先理解該系統(tǒng)。只有理解了系統(tǒng),可控制的變更和定向升級才能成為可能。
當然,我們并不需要理解系統(tǒng)的每個組成部分的詳細情況和特性,只需要理解所負責的系統(tǒng)的相關(guān)參數(shù)以及相應(yīng)等級層次的行為即可。
隱藏服務(wù)實現(xiàn)
從外部角度來看,我們僅僅關(guān)心系統(tǒng)暴露的行為、提供的服務(wù)類型以及該服務(wù)的屬性。例如,服務(wù)可靠嗎?與替代方案相比有競爭力嗎?
圖1:服務(wù)的使用者
作為服務(wù)的使用者,我們并不關(guān)心服務(wù)的特性是如何實現(xiàn)的,我們只關(guān)心所提供的功能(Capability)是否可以滿足我們的需求(Requirement)。
理解結(jié)構(gòu)以便管理
不同于使用者,服務(wù)的實現(xiàn)方式對于服務(wù)的提供者而言,是極為重要的。為了更好的理解,我們?yōu)樨撠熖峁┓?wù)的系統(tǒng)建立概念模型,這是通過將系統(tǒng)分解成一組更小的相互關(guān)聯(lián)的單元實現(xiàn)的。如果這個實體是某個公司,這張組件圖就代表了“組織結(jié)構(gòu)圖(Organization Chart’)”;如果這個實體是軟件應(yīng)用程序,那么這張圖就是模塊間依賴關(guān)系的映射圖。
嘗試理解抽象系統(tǒng)的第一步如下圖所示。
圖2: 服務(wù)提供者和系統(tǒng)維護者
從上圖的例子,我們可以馬上知道:
- 系統(tǒng)由15個組件組成。
- 每個組件的名稱。
- 這些模塊間的依賴,盡管我們無法知道這些依賴為何存在。
- 盡管我們并不知道每個組件各自所承擔的責任,從關(guān)聯(lián)性出發(fā),我們依然可以推斷出“Tom”模塊在系統(tǒng)中所占據(jù)的地位很有可能比“Dick”模塊更為重要。
需要注意的是,這些組件可能并不是我們所創(chuàng)建的,我們也不必理解這些組件之間的內(nèi)在結(jié)構(gòu)。就像作為服務(wù)的使用者,只需關(guān)心服務(wù)所提供的功能,我們作為組件的使用者,只是需要它們的功能。
需求和功能(Requirements & Capabilities)
到目前為止,我們僅僅知道組件之間存在依賴性,并不知道為什么會存在這些依賴性。另外目前的狀態(tài)是與時間無關(guān)的。如果隨著時間的推移,發(fā)生了變化又該怎樣呢?
最初我們可能會借助于實體的名字,再加上版本號(version)或者版本范圍(version range),結(jié)構(gòu)的變化由版本的變化體現(xiàn)出來。然而,如圖3所示,版本名稱(versioned name)盡管表明了系統(tǒng)的改變,但卻無法解釋為什么Susan 2.0不能像Susan 1.0那樣與Tom 2.1一起協(xié)同工作。
這是為什么呢?
圖3:如何跟蹤結(jié)構(gòu)隨時間的變化?系統(tǒng)以前能夠正確運行,后來由于一個組件的升級導(dǎo)致整個系統(tǒng)出錯。為什么呢?
只有當我們仔細研究系統(tǒng)的功能和需求后,才能了解問題的原因。Tom 2.1需要管理者(Manager)的功能,這個功能在Susan 1.0中提供。然而稍后的Susan 2.0,由于她的職業(yè)規(guī)劃,決定進行再培訓(xùn),這時的Susan 2.0被賦予了新的Plumber 1.0功能,也就意味著其不再擁有管理者的功能了。
這個簡單的例子向我們展示了模塊間的依賴關(guān)系需要由需求和功能來表達,而不是它們的名字(Apache Maven項目最近正在討論為制件的名字采用版本范圍。盡管這是一個進步,但依然有缺陷,因為依賴還是用實體的名字來進行描述。)。這些描述應(yīng)當能顯示模塊的本質(zhì),即模塊應(yīng)當能自我描述(需求、功能以及依賴應(yīng)該進行文檔化,但是隨著時間的推移,這些描述會變得過時,如最初的文檔制定之后,系統(tǒng)又發(fā)生了變化,而文檔并沒有得到更新。)。
圖4:組織化結(jié)構(gòu):按照功能、需求的術(shù)語以及語義化的版本來進行定義
如圖所示,我們完全可以不引用具體實體的名字,而直接使用需求和功能來描述一個系統(tǒng)
系統(tǒng)演化和語義化版本的角色
目前,功能與需求是我們了解系統(tǒng)結(jié)構(gòu)的主要途徑。然而,要理解時間推移所帶來的變化,我們依然還會遇到問題。
- 在組織結(jié)構(gòu)圖中,如果某個員工晉升了,那么原有的關(guān)聯(lián)性是否依舊有效(功能增強)?
- 在一組互相關(guān)聯(lián)的軟件組件中,如果我們重構(gòu)了其中的一個模塊(可能改變其公開接口),原有的依賴是否依然有效?
通過簡單的版本化,我們可以觀察到系統(tǒng)所發(fā)生的變化,卻無法了解這些變化所帶來的影響。然而,如果采用語義化版本命名方式(見http://www.osgi.org/wiki/uploads/Links/SemanticVersioning.pdf),我們就能夠傳達系統(tǒng)變化而帶來的潛在影響。
這可以通過以下的方式實現(xiàn):
- 將功能根據(jù)major.minor.micro 的版本模式來進行版本化。同時我們達成共識,minor 或 micro這兩個版本域代表非破壞性的變化(non-breaking change)。例如,2.7.1?2.8.7。相反,major版本域的變化,例如,2.7.1?3.0.0表示有破壞性的變化(breaking change),組件的改變可能影響到它的使用者。
- 需求則使用可接受的功能的版本范圍來表示。方括號“[”和“]”表示包含此值,而圓括號“(”和“)”表示不含此值。因此,范圍[2.7.1,3.0.0) 表示任何版本高于或等于2.7.1并且低于3.0.0(不含3.0.0)的功能都是可接受的
使用這種方式,我們可以看到如果Helen代替了Joe,Tom的需求依然會得到滿足。然而,同樣有管理者功能的Harry卻因為其功能仍是1.7版本,不在Tom的[2,3)需求范圍內(nèi),所以無法進行替換。
通過使用語義化版本的命名方式可以表達系統(tǒng)變更所帶來的影響。再加上需求和功能,我們具備了足夠信息,能夠保證在滿足系統(tǒng)各部分依賴的前提下,進行模塊的替換。
我們的工作到此告一段落,這樣簡單的系統(tǒng)是敏捷且易維護的!
敏捷——從上至下貫穿各層
最后的挑戰(zhàn)與復(fù)雜性息息相關(guān)。試想如果下列情況出現(xiàn)時會發(fā)生什么:1)系統(tǒng)的規(guī)模和難度不斷增長?2)系統(tǒng)的模塊數(shù)量大幅增加,并且模塊間的互相依賴性也大幅增加?有些讀者在前面的例子中,可能已經(jīng)注意到出現(xiàn)了某種程度的自相似性(self-similarity),你們或許已經(jīng)從中猜到了答案。
服務(wù)的使用者選擇我們的服務(wù)是因為服務(wù)所宣稱的功能符合它們的需求(見圖1)。而提供服務(wù)的系統(tǒng)的實現(xiàn)方式,對服務(wù)的使用者而言是不可見的。向下的每一層都沿用這一模式。系統(tǒng)的結(jié)構(gòu)自然而然地根據(jù)各組件的功能和需求進行描述。(見圖4)。這時組件的內(nèi)部結(jié)構(gòu)對于系統(tǒng)而言是不可見的。如圖5所示,許多邏輯層都可能使用這種模式。
圖5:敏捷的結(jié)構(gòu):每層只暴露必要的信息。每層都是由組件間的依賴所組成的,這些依賴通過需求和功能來進行表述。
所有真正敏捷的系統(tǒng)都是以分層的層級結(jié)構(gòu)建立起來的。在每個結(jié)構(gòu)化的層次中,各組件的自描述都遵循以下的規(guī)則:只描述當前層次的有關(guān)信息,關(guān)于更低層次的不必要細節(jié)是不會描述的。
這種模式不斷出現(xiàn)于自然系統(tǒng)和人造系統(tǒng)中。自然生態(tài)系統(tǒng)中所構(gòu)建的大量結(jié)構(gòu)都是由嵌套的模塊化組件所組成的。例如:
這項進程起源于20世紀90年代中后期,許多公司開始采用包括面向服務(wù)架構(gòu)(Service Oriented Architecture,SOA)和企業(yè)服務(wù)總線(Enterprise Service Buses ,ESB’s)為代表的粗粒度模塊化技術(shù)。商業(yè)程序通過已知的服務(wù)接口或消息傳遞的方式,較為寬松地聯(lián)系在一起。SOA提倡更加“敏捷”的IT環(huán)境,即商業(yè)系統(tǒng)應(yīng)該更加易于升級或替換。
然而在許多實際場景中,核心的應(yīng)用程序一直沒有更改。很多現(xiàn)有的程序只是簡單地將接口暴露為SOA服務(wù)。從這一角度來看,SOA實質(zhì)上并不能如其保證的那樣節(jié)省開支和使商業(yè)快速化:http://apsblog.burtongroup.com/2009/01/soa-is-dead-long-live-services.html。
這是因為內(nèi)部缺乏模塊化,加入SOA之后的程序和沒加之前一樣難以修改
變得敏捷?
我們將在此章節(jié),對目前為止的觀點進行小結(jié)。
為了“敏捷”,系統(tǒng)必須符合以下的特性:
- 層級化的結(jié)構(gòu)(Hierarchical Structure):系統(tǒng)必須層級化,每一層由更低一層的組件構(gòu)成。
- 隔離性(Isolation):對于每個結(jié)構(gòu)化的層級,高度的隔離性確保參與運行的組件的內(nèi)部結(jié)構(gòu)將是不可見的。
- 抽象化(Abstraction):對于每一層,參與運行的組件的行為通過需求和功能加以表達。
- 自描述(Self-Describing):在每層之中,參與運行的模塊間的關(guān)系都必須是自描述的。也就是說,依賴性定義將通過需求和功能進行表達。
- 變化的影響(Impact of Change):通過語義化的版本命名,變化對依賴的影響可以進行表述。
系統(tǒng)按上述原則建立,將是:
- 易于理解的(Understandable):基于層級化的結(jié)構(gòu),系統(tǒng)在每一層的結(jié)構(gòu)都易于理解。
- 高適應(yīng)性的(Adaptable):在每一層中,結(jié)構(gòu)性模塊化保證了變更的影響可以局限在那些相關(guān)的模塊內(nèi)部,高度模塊化所建立起來的邊界能夠保護系統(tǒng)的其他部分不受影響。
- 可演化的(Evolvable):每層中的組件都可以被代替。因此,系統(tǒng)可以支持多樣化(diversity)并且是可演化的。
系統(tǒng)可以通過結(jié)構(gòu)性模塊化來實現(xiàn)敏捷。
在這個系列的下一部分,我們將會討論OSGi?——Java?的模塊化框架——如何滿足結(jié)構(gòu)性模塊化的需求,從而為流行的敏捷方法學奠定基礎(chǔ),最終形成敏捷的企業(yè)。
原文英文地址:Agility and Structural Modularity – part I
作者簡介
Richard Nicholson是Paremus 的CEO和創(chuàng)始人,這是一個2001年成立的軟件公司,總部位于英國。
在意識到高度可維護以及高度敏捷的系統(tǒng)在本質(zhì)上必須是高度模塊化的之后,Paremus在2004年開始研究下一代的軟件系統(tǒng)。這種持續(xù)的努力體現(xiàn)在了Paremus Service Fabric產(chǎn)品之中,這是一個高度可適應(yīng)的、基于OSGi的自裝配運行時,可用于企業(yè)級和云環(huán)境。作為OSGi聯(lián)盟的主席(2010-2012),Richard開始推進OSGi Cloud并鼓勵OSGi聯(lián)盟參與到敏捷軟件社區(qū)中。
Richard在很多的研究領(lǐng)域都保持了濃厚的興趣,這支撐了Service Fabric的研發(fā),他的研究領(lǐng)域包括復(fù)雜的適應(yīng)性系統(tǒng)(Complex Adaptive System)以及敏捷(Agility)、模塊化組裝(Modular Assembly)、結(jié)構(gòu)化多樣性(Structural Diversity)和適應(yīng)性(Adaption)之間的關(guān)系。
成立Paremus之前,Richard在花旗集團/Salomon Smith Barney,領(lǐng)導(dǎo)著歐洲系統(tǒng)工程(European System Engineering)相關(guān)的工作。Richard獲得了曼切斯特大學的物理學榮譽學位,并在格林尼治皇家天文臺( Royal Greenwich Observatory)獲得天體學物理博士。
Richard的博客:http://adaptevolve.paremus.com。
Paremus的博客:http://blogs.paremus.com。
轉(zhuǎn)自:http://www.infoq.com/cn/articles/agile-and-structural-modularity-part1