在幾乎每一個(gè)軟件設(shè)計(jì)的基礎(chǔ)上都有一種感知、抽象和分解的方法論。這種理念采用特定的抽象和分解技術(shù)將導(dǎo)致更好的設(shè)計(jì)。在處理變更的場景中,主要有軟件開發(fā)的組件方法和服務(wù)方法,本文分析了它們在處理變更方面的差異。
1.核心的問題: 需求的改變
對企業(yè)而言,應(yīng)對變化是日常生活中必須加以利用和實(shí)現(xiàn)的一個(gè)事實(shí)。合并、收購和新技術(shù)的引入是業(yè)務(wù)環(huán)境變化的驅(qū)動(dòng)因素。業(yè)務(wù)敏捷性是指企業(yè)在不斷變化和不可預(yù)測的環(huán)境中蓬勃發(fā)展的能力。
了解哪些方面更有可能發(fā)生變化,哪些方面不會(huì)發(fā)生變化,對于處理變化至關(guān)重要。盡管業(yè)務(wù)中有許多事情在變化,但有些要素往往保持不變。從中期來看,企業(yè)的核心能力相對穩(wěn)定; 由于業(yè)務(wù)程序的改變或新技術(shù)的采用,企業(yè)的運(yùn)作方式可能受到變化的影響。從長遠(yuǎn)來看,業(yè)務(wù)的幾乎每個(gè)方面都可能發(fā)生變化。
為了滿足不斷變化的業(yè)務(wù)需求,軟件系統(tǒng)必須不斷地進(jìn)化。
業(yè)務(wù)系統(tǒng)需求變化是軟件設(shè)計(jì)的一個(gè)事實(shí),但并非所有的軟件開發(fā)方法都能對其解釋,不同的方法在如何分解系統(tǒng)應(yīng)對變化方面有著不同的哲學(xué)。
在20世紀(jì)70年代,結(jié)構(gòu)化分析的發(fā)展是為了應(yīng)對由許多程序員合作開發(fā)的復(fù)雜系統(tǒng)。結(jié)構(gòu)化分析主要以功能分解為基礎(chǔ)。自頂向下的功能分解從系統(tǒng)的頂層描述開始,然后一步一步地細(xì)化這個(gè)視圖。通過每次細(xì)化,系統(tǒng)被分解成更低級別和更小的模塊。自頂向下分解需要確定主要的系統(tǒng)需求和功能,然后在連續(xù)的步驟中分解它們,直到可以設(shè)計(jì)特定于功能的模塊。
雖然功能分解在較穩(wěn)定的系統(tǒng)類型方面取得了成功,但在處理業(yè)務(wù)變化以及隨后的系統(tǒng)維護(hù)效率較低。要更改數(shù)據(jù)結(jié)構(gòu),通常需要更改與該結(jié)構(gòu)相關(guān)的所有函數(shù)。因此,系統(tǒng)很容易變得不穩(wěn)定,因?yàn)檩p微的修改就會(huì)產(chǎn)生嚴(yán)重的連鎖反應(yīng)。
面向?qū)ο蟮姆妒酵ㄟ^在類中封裝數(shù)據(jù)及其相應(yīng)的操作來解決重用和維護(hù)問題。問題域中的對象概念比數(shù)據(jù)結(jié)構(gòu)和函數(shù)具有更高的穩(wěn)定性; 因此系統(tǒng)的整體架構(gòu)通常是穩(wěn)定的。此外,面向?qū)ο蠓妒降膬?nèi)部細(xì)節(jié)更改不會(huì)擴(kuò)展到系統(tǒng)體系結(jié)構(gòu)中。
軟件開發(fā)方法可以大致分為兩大類: 需求預(yù)測方法和需求適應(yīng)方法。第一種假設(shè)在編碼之前可以識別和解決幾乎所有的問題。后者采用了更實(shí)用的方法,認(rèn)為業(yè)務(wù)系統(tǒng)開發(fā)是一個(gè)漸進(jìn)的過程,變更是軟件設(shè)計(jì)中不可避免的一個(gè)方面,預(yù)計(jì)將在每個(gè)階段發(fā)生。
為了滿足不斷變化的業(yè)務(wù)需求,軟件系統(tǒng)必須不斷地進(jìn)化。因此,軟件開發(fā)過程和維護(hù)過程之間的分離變得越來越不重要。在這里,支持持續(xù)軟件演進(jìn)有兩種設(shè)計(jì)方法: 基于組件的開發(fā)和基于服務(wù)的開發(fā)。
2.適應(yīng)需求的變化: 組件化與服務(wù)化
軟件生產(chǎn)的靈活性是技術(shù)和非技術(shù)因素綜合作用的結(jié)果。在處理變更時(shí),組件和服務(wù)之間的差異受到這里討論的因素的影響。
2.1 組件:預(yù)制組裝
基于組件的開發(fā)思想是通過組裝預(yù)制軟件組件來生產(chǎn)軟件應(yīng)用程序,從而實(shí)現(xiàn)軟件開發(fā)過程的工業(yè)化。為了響應(yīng)變化和不斷變化的需求,基于組件的開發(fā)有兩個(gè)基本思想。首先,如果可以從預(yù)制軟件組件快速組裝應(yīng)用程序,那么軟件開發(fā)可以得到顯著改善。其次,將向開發(fā)人員提供越來越多的可互操作的軟件組件,包括一般組件和專業(yè)化組件。
2.2 服務(wù):需求與需求實(shí)現(xiàn)機(jī)制的邏輯分離
當(dāng)客戶預(yù)訂從 A 地到 B 地的火車票時(shí),他既不控制火車的運(yùn)行,也不選擇乘務(wù)員。在這種情況下,客戶只對結(jié)果感興趣,而不能控制實(shí)現(xiàn)結(jié)果的機(jī)制。服務(wù)被定義為: “任何一方可以提供給另一方的本質(zhì)上是無形的,并且不會(huì)導(dǎo)致任何所有權(quán)的行為或表現(xiàn)。它的生產(chǎn)可能與實(shí)物產(chǎn)品有關(guān),也可能與實(shí)物產(chǎn)品無關(guān)?!痹谲浖?,這被稱為“松耦合”。軟件服務(wù)是一個(gè)粗粒度的、可發(fā)現(xiàn)的實(shí)體,它作為單個(gè)實(shí)例存在,并與應(yīng)用程序和其他服務(wù)交互。服務(wù)的概念不同于組件的概念,因?yàn)榉?wù)不定義任何結(jié)構(gòu)約束,而是定義接口。
2.3 約束
盡管面向服務(wù)的軟件開發(fā)模式和基于組件的開發(fā)模式有著共同的特點(diǎn),但也存在著較大的差異。它們共同的特點(diǎn)是軟件系統(tǒng)的各個(gè)部分可以單獨(dú)開發(fā),然后再添加到系統(tǒng)中(進(jìn)行綁定)。然而,它們綁定的方法大不相同。
基于組件的軟件假設(shè)了組件的早期綁定, 也就是說,調(diào)用單元確切地知道在運(yùn)行時(shí)之前要聯(lián)系哪個(gè)組件。基于服務(wù)的開發(fā)采用了更靈活的方法,將綁定延遲到運(yùn)行時(shí),從而每次都能更改供應(yīng)源。服務(wù)方法不僅允許在提供者中靈活變更,而且還適應(yīng)需求質(zhì)量隨時(shí)間的變化。
在基于組件的開發(fā)中,軟件組件是“從盒子里拿出來的”,然后插入到系統(tǒng)中,可能還添加了一些“粘合”代碼。在這種情況下,所需功能的確切來源是在運(yùn)行時(shí)之前確定的。基于服務(wù)的應(yīng)用程序是動(dòng)態(tài)的。應(yīng)用程序可以由許多服務(wù)組成。對于每個(gè)服務(wù),可能存在許多提供者,它們提供相同的服務(wù),但具有不同的質(zhì)量特征組合。每次調(diào)用服務(wù)時(shí),可以選擇不同的提供者來協(xié)商條款和條件,然后最終綁定服務(wù)。服務(wù)的提供者和使用者之間是松散耦合的。
在這里,服務(wù)由許多不同的服務(wù)組合而成,以提供某種結(jié)果。但是,這種組合對于服務(wù)使用者是透明的。
2.4 抽象與粒度
影響軟件變更機(jī)制的一個(gè)因素是變更的粒度。粒度是指要更改的工件規(guī)模,范圍從粗到中等到非常細(xì)的粒度。粒度是一個(gè)相對概念,只能在特定的場景中精確定義。例如,如果一個(gè)服務(wù)實(shí)現(xiàn)了銀行系統(tǒng)的所有功能,那么它可以被認(rèn)為是粗粒度的。如果它只支持信貸余額檢查,那么它就被認(rèn)為是細(xì)粒度的。
在20世紀(jì)90年代早期的面向?qū)ο蟾锩?,很明顯,面向?qū)ο蠹夹g(shù)不足以滿足現(xiàn)實(shí)世界軟件系統(tǒng)快速變化的需求。雖然面向?qū)ο蟮姆椒ㄌ峁┝素S富的模型來描述問題領(lǐng)域,但這還不足以適應(yīng)不斷變化的需求。具體來說,對象過于細(xì)粒度,沒有明確區(qū)分計(jì)算和組合方面,提出的組件來封裝一組對象的計(jì)算細(xì)節(jié)。
服務(wù)應(yīng)該發(fā)布在與現(xiàn)實(shí)世界活動(dòng)或可識別的業(yè)務(wù)功能相對應(yīng)的抽象級別上。服務(wù)及其方法的適當(dāng)粒度級別相對較粗。服務(wù)通常支持單個(gè)獨(dú)特的業(yè)務(wù)概念或流程。它包含實(shí)現(xiàn)業(yè)務(wù)概念的軟件,因此可以在類似的上下文中重用它。
2.5 傳輸與通信
組件和服務(wù)之間交付機(jī)制的差異可能是個(gè)革命性概念。軟件工程主要集中于為軟件生產(chǎn)提供技術(shù)和管理支持,作為一種面向產(chǎn)品的概念。組件是面向產(chǎn)品的,其中軟件通過 CD 或其他媒體交付。然而,基于互聯(lián)網(wǎng)的計(jì)算擴(kuò)散帶來了新的概念、機(jī)遇和挑戰(zhàn),不僅在廣泛的一般服務(wù)規(guī)定方面,而且也在重新思考軟件交付的方法和模式方面提供了機(jī)會(huì)。將軟件作為服務(wù)交付的主要好處包括通過松散耦合提高業(yè)務(wù)敏捷性的潛力,以及隨著業(yè)務(wù)需求變化而發(fā)展的能力。
在面向服務(wù)的模型中,軟件功能作為服務(wù)交付,其中每次都需要確定功能的服務(wù)元素,協(xié)商、執(zhí)行條款和條件,然后“丟棄”這使得即使在最小的功能單元級別也可以靈活地進(jìn)行更改。除了技術(shù)模型的不同之外,將軟件作為服務(wù)交付還會(huì)帶來新的業(yè)務(wù)模型,這些業(yè)務(wù)模型建立在這種遠(yuǎn)景提供的機(jī)會(huì)之上。示例包括用于計(jì)費(fèi)軟件服務(wù)的業(yè)務(wù)模型、服務(wù)協(xié)商規(guī)則以及信任評估和提供。
2.6 架構(gòu)
組件體系結(jié)構(gòu)是控制組件之間通信的一組接口和交互規(guī)則的規(guī)范。大多數(shù)組件體系結(jié)構(gòu)代表了緊耦合的情況。例如,在 CORBA (一種基于組件的體系結(jié)構(gòu))中,客戶端和服務(wù)器之間存在緊密耦合,因?yàn)閮烧弑仨毰c客戶端的框架和服務(wù)器端的相應(yīng)框架共享相同的接口。此外,大多數(shù)基于組件的體系結(jié)構(gòu)的實(shí)現(xiàn)都是封閉的系統(tǒng),因?yàn)樗鼈冎荒芴幚韺S屑夹g(shù)。
面向服務(wù)的體系結(jié)構(gòu)(SOA或者微服務(wù))是一種設(shè)計(jì)軟件系統(tǒng)的方法,通過發(fā)布和自動(dòng)發(fā)現(xiàn)的接口向終端用戶應(yīng)用程序或其他服務(wù)提供服務(wù)。服務(wù)使用者通過代理與服務(wù)提供者解耦。面向服務(wù)的體系結(jié)構(gòu)在現(xiàn)有 IT 環(huán)境之上添加了一個(gè)抽象層。通常,可以在組件基礎(chǔ)結(jié)構(gòu)上添加服務(wù)層。
3.挑戰(zhàn)
通過組件或服務(wù)實(shí)現(xiàn)軟件靈活性涉及到技術(shù)和非技術(shù)挑戰(zhàn)。在解決方案成為商業(yè)現(xiàn)實(shí)之前,必須解決這些挑戰(zhàn)。
3.1 信任
在軟件的上下文中,正如與之相關(guān)的描述中所承諾的那樣,信任是對組件或服務(wù)將提供其功能性和非功能性義務(wù)的信心。通過檢查源代碼來測試組件并不是一種實(shí)用的解決方案。然而,信任來自未知來源的組件可以通過在使用前多次測試來部分解決。此外,對源代碼的任何更改都可能使組件契約規(guī)范失效。
在基于服務(wù)的開發(fā)中,信任問題要復(fù)雜得多,因?yàn)楹茈y預(yù)測提供者是否符合商定的服務(wù)水平。當(dāng)軟件以服務(wù)形式交付時(shí),必須監(jiān)控服務(wù)級別協(xié)議是否符合規(guī)定。對于由其他服務(wù)組成的服務(wù),這個(gè)問題變得更加復(fù)雜。在這種情況下,服務(wù)的最終質(zhì)量將取決于組成服務(wù)的服務(wù)質(zhì)量。
3.2 組合管理
與動(dòng)態(tài)服務(wù)組合相比,由許多組件組合的系統(tǒng)是相對受控的。隨著越來越多的服務(wù)提供者在大型分布式系統(tǒng)中公開他們的服務(wù),人工管理和組合服務(wù)變得不可行; 這個(gè)過程必須完全自動(dòng)化。與這種開放環(huán)境相關(guān)的是管理回滾、計(jì)費(fèi)、許可和事務(wù)語義的問題。
3.3 適應(yīng)與高級發(fā)現(xiàn)
組件選擇是一個(gè)設(shè)計(jì)期間的活動(dòng),隨后可能需要某種適應(yīng)性。這種適應(yīng)性有時(shí)被稱為膠水代碼。在基于服務(wù)的開發(fā)中,服務(wù)發(fā)現(xiàn)和選擇在運(yùn)行時(shí)進(jìn)行; 也就是說,在確定了提供的來源之后。這使得在使用前測試服務(wù)幾乎不切實(shí)際,因?yàn)榉?wù)的源以及使用條件可能在兩個(gè)連續(xù)調(diào)用之間有所不同。
在基于服務(wù)的開發(fā)中自動(dòng)發(fā)現(xiàn)是相對于其前身基于組件的開發(fā)的最重要的進(jìn)步。
使用組件構(gòu)建軟件的一個(gè)主要限制是組件的指定方式。專有標(biāo)準(zhǔn)和依賴于實(shí)現(xiàn)的組件規(guī)范阻礙了基于組件的開發(fā)實(shí)現(xiàn)其促進(jìn)復(fù)用的主要目標(biāo)。
基于服務(wù)開發(fā)中的連接點(diǎn)是服務(wù)規(guī)范,而不是實(shí)現(xiàn)。這提供了實(shí)現(xiàn)透明度,并最小化了變更對軟件系統(tǒng)的影響。
3.4 執(zhí)行效率
運(yùn)行時(shí)綁定的關(guān)鍵概念是基于服務(wù)所固有的。雖然實(shí)現(xiàn)這樣的概念有利于靈活性,但也會(huì)導(dǎo)致執(zhí)行開銷,特別是當(dāng)每次調(diào)用功能時(shí)都要進(jìn)行服務(wù)發(fā)現(xiàn)和匹配的時(shí)候。
4.小結(jié)
需求變更在許多軟件系統(tǒng)的生命周期中至關(guān)重要,特別是那些服務(wù)于高度不穩(wěn)定業(yè)務(wù)領(lǐng)域的軟件系統(tǒng)。組件和服務(wù)雖然相似,但并不相同; 它們有不同的方法論和抽象,都支持一定程度的演進(jìn)。方法論和抽象級別的差異使得服務(wù)成為更好的變更解決方案。
所有未來的軟件可能都是基于服務(wù)的?與其說是為了實(shí)用性,不如說是為了炒作。事實(shí)上,服務(wù)的概念適用于需求經(jīng)常變化的系統(tǒng),這些系統(tǒng)可以容忍某種低效。雖然組件是實(shí)現(xiàn)服務(wù)的好方法,但理想的基于組件系統(tǒng)并不一定產(chǎn)生理想的面向服務(wù)系統(tǒng)。因此,服務(wù)不會(huì)完全替換組件,而是補(bǔ)充它們。