摘要:企業應用在某些方面要比電信軟件簡單得多多線程問題沒有那么困難,無需關注硬件設備與軟件的集成。但是,在某些方面,企業應用又比電信軟件復雜得多企業應用一般都涉及到大量復雜數據,而且必須處理很多不合邏輯的業務規則。
構建計算機系統并非易事。隨著系統復雜性的增大,構建相應軟件的難度將呈指數增大。
同其他行業一樣,我們只有在不斷的學習中進步,從成功經驗中學習,從失敗教訓中學習,才有望克服這些困難。
這本書的內容就是這樣一些“學習”經驗。
只有通過模式的總結和學習,才能更有效地與他人進行交流。
—選自《企業應用架構模式》
0.1 架構軟件業的人樂于做這樣的事——找一些詞匯,并把它們引申到大量微妙而又互相矛盾的含義。一個最大的受害者就是“架構”(architecture)這個詞。我個人對“架構”的感覺是,它是一個讓人印象深刻的詞,主要用來表示一些非常重要的東西。當然,我也會小心,不讓這些對“系統結構”的“不恭之詞”,影響到讀者對本書的興趣。
很多人都試圖給“架構”下定義,而這些定義本身卻很難統一。能夠統一的內容有兩點:一點是“最高層次的系統分解”;另一點是“系統中不易改變的決定”。越來越多的人發現:表述一個系統架構的方法不只一種;一個系統中也可能有很多種不同的架構,而且,對于什么在架構上意義重大的看法也會隨著系統的生命周期變化。
Ralph Johnson經常在郵件列表上發帖,并提出一些令人關注的見解。就在我完成本書初稿的同時,他又發表了一些關于“架構”的觀點。他認為,架構是一種主觀上的東西,是專家級項目開發人員對系統設計的一些可共享的理解。一般地,這種可共享的理解表現為系統中主要的組成部分以及這些組成間的交互關系。它還包括一些決定,開發者們希望這些決定能及早做出,因為在開發者看來它們是難以改變的。架構的主觀性也來源于此——如果你發現某些決定并不像你想象的那么難以改變,那么它就不再與架構相關。到了最后,架構自然就濃縮成一些重要的東西,不論這些東西是什么。
在本書中,我提出一些自己的理解,涉及企業應用主要組成部分和我希望能盡早做出的決定。在這些架構模式中,我最欣賞的就是“層次”,將在第1章中進行詳細介紹。全書實際上就是關于如何將企業應用組織成不同的層次,以及這些層次之間如何協同工作。大多數重要的企業應用都是按照某種形式的層次分層設計的;當然,在某些情況下,別的設計方式(如管道方式、過濾器方式等)也有它們自己的價值。在本書中我們將不會討論這些方式,而把注意力集中在層次方式上,因為它是應用最廣的設計方式。
本書中的一些模式毫無疑問是關于架構的,它們表示了企業應用各主要組成部分間的重要決定;另外一些模式是關于設計的,有助于架構的實現。我沒有刻意區分這兩類模式,因為正如我們前面討論的,是否與架構相關往往帶有主觀性。
0.2 企業應用編寫計算機軟件的人很多,我們通常把這些活動都稱為軟件開發。但是軟件的種類是不同的,每種軟件都有自身的挑戰性和復雜性。我是在與幾個從事電信軟件開發的朋友交談后,意識到這個問題的。企業應用在某些方面要比電信軟件簡單得多——多線程問題沒有那么困難,無需關注硬件設備與軟件的集成。但是,在某些方面,企業應用又比電信軟件復雜得多——企業應用一般都涉及到大量復雜數據,而且必須處理很多“不合邏輯”的業務規則。雖然有些模式是適合所有軟件的,但是大多數模式都還只適合某些特定的領域和分支。
我的工作主要是關于企業應用的,因此,這里所談及的模式也都是關于企業應用的。(企業應用還有一些其他的說法,如“信息系統”或更早期的“數據處理”。)那么,這里的“企業應用”具體指的是什么呢?我無法給出一個精確的定義,但是我可以羅列一些個人的理解。
先舉幾個例子。企業應用包括工資單、患者記錄、發貨跟蹤、成本分析、信譽評估、保險、供應鏈、記賬、客戶服務以及外幣交易等。企業應用不包括車輛加油、文字處理、電梯控制、化工廠控制器、電話交換機、操作系統、編譯器以及電子游戲等。
企業應用一般都涉及到持久化數據。數據必須持久化是因為程序的多次運行都需要用到它們——實際上,有些數據需要持久化若干年。在此期間,操作這些數據的程序往往會有很多變化。這些數據的生命周期往往比最初生成它們的那些硬件、操作系統和編譯器還要長。在此期間,數據本身的結構一般也會被擴展,使得它在不影響已有信息的基礎上,還能表示更多新信息。即使是有根本性的變化發生,或公司安裝了一套全新的軟件,這些數據也必須被“遷移”到這些全新的應用上。
企業應用一般都涉及到大量數據——一個中等規模的系統往往都包含1GB以上的數據,這些數據是以百萬條記錄的方式存在的。巨大的數據量導致數據的管理成為系統的主要工作。早期的系統使用的是索引文件系統,如IBM的VSAM和ISAM。現代的系統往往采用數據庫,絕大多數是關系型數據庫。數據庫的設計和演化已使其本身成為新的技術領域。
企業應用一般還涉及到很多人同時訪問數據。對于很多系統來說,人數可能在100人以下,但是對于一些基于Web的系統,人數會呈指數級增長。要確保這些人都能夠正確地訪問數據,就一定會存在這樣或那樣的問題。即使人數沒有那么多,要確保兩個人在同時操作同一數據項時不出現錯誤,也是存在問題的。事務管理工具可以處理這個問題,但是它通常無法做到對應用開發者透明。
企業應用還涉及到大量操作數據的用戶界面屏幕。有幾百個用戶界面是不足為奇的。用戶使用頻率的差異很大,他們也經常沒什么技術背景。因此,為了不同的使用目的,數據需要很多種表現形式。系統一般都有很多批處理過程,當專注于強調用戶交互的用例時,這些批處理過程很容易被忽視。
企業應用很少獨立存在,通常需要與散布在企業周圍的其他企業應用集成。這些各式各樣的系統是在不同時期,采用不同技術構建的,甚至連協作機制都不同:COBOL數據文件、CORBA系統或是消息系統。企業經常希望能用一種統一的通信技術來集成所有系統。當然,每次這樣的集成工作幾乎都很難真正實現,所有留下來的就是一個個風格各異的集成環境。當商業用戶需要同其業務伙伴進行應用集成時,情況就更糟糕。
即使是某個企業統一了集成技術,它們也還是會遇到業務過程中的差異以及數據中概念的不一致性。一個部分可能認為客戶是當前簽有協議的人;而另外一個部門可能還要將那些以前有合同,但現在已經沒有了的人計算在內。再有,一個部門可能只關心產品銷售而不關心服務銷售。粗看起來,這些問題似乎容易解決,但是,一旦幾百個記錄中的每個字段都有可能存在著細微差別,問題的規模就會形成不小的挑戰——就算唯一知道這些字段之間差別的員工還在公司任職(當然,也許他在你察覺到之前就早已辭職不干了)。這樣,數據就必須被不停地讀取、合并、然后寫成各種不同語法和語義的格式。
再接下來的問題是由“業務邏輯”帶來的。我認為“業務邏輯”這個詞很滑稽,因為很難找出什么東西比“業務邏輯”更加沒有邏輯。當我們構建一個操作系統時,總是盡可能地使得系統中的各種事物符合邏輯。而業務邏輯生來就是那樣的,沒有相當的行政努力,不要想改變它,當然,它們都有自己的理由。你必須面對很多奇怪的條件。而且這些條件相互作用的方式也非常怪異。比如,某個銷售人員為了簽下其客戶幾百萬美元的一張單,可能會在商務談判中與對方達成協議,將該項目的年度到賬時間推遲兩天,因為這樣才能與該客戶的賬務周期相吻合。成千上萬的這類“一次特殊情況”最終導致了復雜的業務“無邏輯”,使得商業軟件開發那么困難。在這種情況下,必須盡量將這些業務邏輯組織成有效的方式,因為我們可以確定的是,這些“邏輯”一定會隨著時間不斷變化。
對于一些人來說,“企業應用”這個詞指的是大型系統。但是 需要注意的是,并不是所有的企業應用都是大型的,盡管它們可能都為企業提供巨大的價值。很多人認為,由于小型系統的規模不大,可以不用太注意它們,而且在某種程度上,這種觀點能夠帶來一定的成本節約。如果一個小型系統失敗了,相對于大型系統的失敗,這種失敗就不會顯得那么起眼了。但是,我認為這種思想沒有對小型項目的累積作用給予足夠的重視。試想,如果在小型項目上能夠進行某些改善措施,那么一旦這些改善措施被成功運用于大型項目,它帶來的效果就會非常大。實際上,最好是通過簡化架構和過程,將一個大型項目簡化成小型項目。
0.3 企業應用的種類在我們討論如何設計企業應用以及使用哪些模式之前,明確這樣一個觀點是非常重要的,即企業應用是多種多樣的,不同的問題將導致不同的處理方法。如果有人說“總是這樣做” 的時候,就應該敲響警鐘了。我認為,設計中最具挑戰性(也是我最感興趣)的地方就是了解有哪些候選的設計方法以及各種不同設計方法之間的優劣比較。進行選擇的控件很大,但我在這里只選三個方面。
考慮一個B2C(Business to Customer)的網上零售商:人們通過瀏覽器瀏覽,通過購物車購買商品。通過購物車購買商品。這樣一個系統必須能夠應付大量的客戶,因此,其解決方案不但要考慮到資源利用的有效性,還要考慮到系統的可伸縮性,以便在用戶規模增大時能夠通過增加硬件的辦法加以解決。該系統的業務邏輯可以非常簡單:獲取訂單,進行簡單的價格計算和發貨計算,給出發貨信息。我們希望任何人都能夠訪問該系統,因此用戶界面可以選用通用的Web表現方式,以支持各種不同的瀏覽器。數據源包括用來存放訂單的數據庫,還可能包括某種與庫存系統的通信交流,以便獲得商品的可用性信息和發貨信息。
再考慮一個租約合同自動處理系統。在某些方面,這樣的系統比起前面介紹的B2C系統要簡單,因為它的用戶數很少(在特定時間內不會超過100個),但是它的業務邏輯卻比較復雜。計算每個租約的月供,處理如提早解約和延遲付款這樣的事件,簽訂合同時驗證各種數據,這些都是非常復雜的任務,因為租約領域的許多競爭都是以過去的交易為基礎稍加變化而出現的。正是因為規則的隨意性很大,才使得像這樣一個復雜領域具有挑戰性。
這樣的系統在用戶界面(UI)上也很復雜。這就要求HTML界面要能提供更豐富的功能和更復雜的屏幕,而這些要求往往是HTML界面目前無法達到的,需要更常規的胖客戶界面。用戶交互的復雜性還會帶來事務行為的復雜性:簽訂租約可能要耗時1~2個小時,這期間用戶要處于一個邏輯事務中。一個復雜的數據庫設計方案中可能也會涉及到200多個表以及一些有關資產評估和計價的軟件包。
第三個例子是一家小型公司使用的簡單的“開支跟蹤系統”。這個系統的用戶很少,功能簡單,通過HTML表現方式可以很容易實現,涉及的數據源表項也不多。盡管如此,開發這樣的系統也不是沒有挑戰。一方面你必須快速地開發出它,另一方面你又必須為它以后可能的發展考慮;也許以后會為它增加賠償校驗的功能,也許它會被集成到工資系統中,也許還要增加關于稅務的功能,也許要為公司的CFO生成匯總報表,也許會被集成到一個航空訂票Web Service中,等等。如果在這個系統的開發中,也試圖使用前面兩個例子中的一些架構,可能會影響開發進度。如果一個系統會帶來業務效益(如所有的企業應用應該的那樣),則系統進度延誤同樣也是開銷。如果現在不做決策又有可能影響系統未來的發展。但是,如果現在就考慮了這些靈活性但是考慮不得當,額外的復雜性又可能會影響到系統的發展,進一步延誤系統部署,減少系統的效益。雖然這類系統很小,但是一個企業中往往有很多這樣的系統,這些系統的架構不良性累積起來,后果將會非常可怕。
這三個企業應用的例子都有難點,而且難點各不相同。當然,也不可能有一個適合于三者的通用架構。選擇架構時,必須很清楚地了解面臨的問題,在理解的基礎上再來選擇合適的設計。本書中也沒有一個通用的解決方案。實際上,很多模式僅僅是一些可選方案罷了。即使你選擇了某種模式,也需要進一步根據面臨的問題來修改模式。在構建企業應用時,你不思考是不行的。所有書本知識只是給你提供信息,作為你做決定的基礎。
模式是這樣,工具也同樣如此。在系統開發時應該選取盡可能少的工具,同時也要注意,不同的工具擅長處理的方面也不同,切記不要用錯了工具,否則只會事倍功半。
0.4 關于性能的考慮很多架構的設計決策和性能有關。對于大多數與性能相關的問題,我的辦法是首先建立系統,調試運行,然后通過基于測量的嚴格的優化過程來提高性能。但是,有一些架構上的決策對性能的影響,可能是后期優化難以彌補的。而且即使這種影響可以在后期很容易地彌補,參與這個項目的人們任然會從一開始就擔心這些決策。
在這樣的一本書中討論性能通常很困難。這是因為“眼見為實”:所有那些關于性能的條條框框,不在你的具體系統中配置運行一下,是很難有說服力的。我也經常看到一些設計方案因為性能方面的考慮而被接受或拒絕,但是一旦有人在真實的設置環境中做一些測量,就會證明這些考慮是錯誤的。
本書將提出一些這方面的建議,包括盡量減少遠程調用(它在很長時間內都被認為是優化性能的好建議)。盡管如此,還是建議讀者在運用這些原則之前,在你的應用中具體試一試。同樣,本書中的樣例代碼也有一些地方為了提高可讀性而犧牲了效率。在你的系統中,需要自行決定是否進行優化。在做性能優化后,一定要與優化前進行測量對比,以確定真的得到了優化,否則,你可能只是破壞了代碼的可讀性。
還有一個很重要的推論:配置上的重大變化會使得某些性能優化失效。因此,在升級虛擬機、硬件、數據庫或其他東西到新的版本時,必須重新確認性能優化工作的有效性。很多情況下,配置變更都會對性能優化有影響,有時候你真的會發現,以前為了提升性能做的優化,在新環境下居然影響性能。
關于性能的另一個問題是很多術語的使用不一致。最明顯的例子就是“可伸縮性”(scalability),它可能有6-7種含義。下面我使用其中一些術語。
響應時間是系統完成一次外部請求處理所需要的時間。這些外部請求可能是用戶交互行為,例如按下一個按鈕,或是服務器API調用。
響應性不同于請求處理,它是系統響應請求的速度有多快。這個指標在許多系統里非常重要,因為對于一些系統而言,如果其響應性太慢,用戶將難以忍受——盡管其響應時間可能不慢。如果在請求處理期間,系統一直處于等待狀態,則系統的響應性和響應時間是相同的。然而,如果能夠在處理真正完成之前就給用戶一些信息表明系統已經接到請求,則響應性就會好一些。例如,在文件拷貝過程中,為用戶提供一個“進度條”,將會提高用戶界面的響應性,但并不會提高響應時間。
等待時間是獲得系統任何形式響應的最小時間,即使應該做的工作并不存在。通常它是遠程系統中的大問題。假設我們讓程序什么都不做,只是調用返回即可,則如果在本機上運行程序,一般都會立即得到響應。但是,如果在遠程計算機上運行程序,情況就不一樣,往往需要數秒的時間才能得到響應。因為從發出請求到得到響應的數秒時間主要用于排除使信息在線路上傳輸的困難。作為應用開發者,我經常對等待時間無能為力。這也是為什么要盡量避免遠程調用的原因。
吞吐率是給定時間內能夠處理多大的請求量。如果考察的是文件拷貝,則吞吐率可以用每秒字節量來表示。對于企業應用來說,吞吐率通常用每秒事務數(tps)來度量。這種方法的一個問題是指標依賴于事務的復雜程度。對于特定系統的測試,應該選取普通的事務集合。
在這里,性能或指吞吐率,或者指響應時間,由用戶自己決定。當通過某種優化技術后,使得系統的吞吐率提高了,但是響應時間下降了,這時就不好說系統的性能提高了,最好用更準確的術語表示。從用戶角度而言,響應性往往比響應時間更重要,因此,為了提高響應性而損失一些響應時間或者吞吐率是值得的。
負載是關于系統當前負荷的表述,也許可以用當前有多少用戶與系統相連來表示。負載有時也作為其他指標(如響應時間)的背景。因此,我們可以說:在10個用戶的情況下,請求響應時間是0.5秒,在20個用戶的情況下,請求響應時間是2秒。
負載敏感度是指響應時間隨負載變化的程度。假設:系統A在10~20個用戶的情況下,請求響應時間都是0.5秒;系統B在10個用戶的情況下,請求響應時間是0.2秒,在20個用戶的情況下,請求響應時間上升到2秒。此時,系統A的負載敏感度比系統B低;我們還可以使用術語衰減(degradation),稱系統B衰減得比系統A快。
效率是性能除以資源。如果一個雙CPU系統的性能是30tps,另一個系統有4個同樣的CPU,性能是40tps,則前者效率高于后者。
系統的容量是指最大有效負載或吞吐率的指標。它可以是一個絕對最大值或性能衰減至低于一個可接受的閾值之前的臨界點。
可伸縮性度量的是向系統中增加資源(通常是硬件)對系統性能的影響。一個可伸縮性的系統允許在增加了硬件后,能夠有性能上的合理提高。例如,為了使吞吐率提高一倍,要增加多少服務器等。垂直可伸縮性或稱垂直延展,通常指提高單個服務器的性能,例如增加內存。水平可伸縮性或稱水平延展,通常指增加服務器的數目。
問題是,設計決策對所有性能指標的作用并不相同。比如,某個服務器上運行著兩個軟件系統:Swordfish的容量是20tps,而Camel的容量是40tps。哪一個的性能更高?哪一個的可伸縮性好?僅憑這些數據,我們無法回答關于可伸縮性的問題,我們只能說Camel系統在單片機上的效率更高。假設又增加了一臺服務器后,我們發現:Swordfish的容量是35tps,Camel的容量是50tps。盡管Camel的容量仍然大于Swordfish,但是后者在可伸縮性上卻顯得比前者更好。假設我們繼續增加服務器數目后發現:Swordfish每增加一臺服務器提高15tps,Camel每增加一臺服務器提高10tps。在獲得了這些數據后,我們才可以說,Swordfish的水平可伸縮性比Camel好,盡管Camel在5個服務器以下會有更好的效率。
當構建企業應用系統時,關注硬件的可伸縮性往往比關注容量或效率更重要。如果需要,可伸縮性可以給予你獲得更好性能的選擇,可伸縮性也可以更容易實現。有時,設計人員費了九牛二虎之力才提高了少許容量,其開銷還不如多買一些硬件。換句話說,假設Camel的費用比Swordfish高,高出的部分正好可以買幾臺服務器,那么選擇Swordfish可能更合算,盡管你目前只需要40tps。現在人們經常抱怨軟件對硬件的依賴性越來越大,有時為了運行某些軟件就不得不對硬件進行升級,就像我一樣,為了用最新版本的Word,就必須不斷地升級筆記本電腦。但是總的來說,購買新硬件還是比修改舊軟件來得便宜。同樣,增加更多的服務器也比增加更多的程序員來得便宜——只要你的系統有足夠的可伸縮性。
0.5 模式模式的概念早就有了。我在這里不想把這段歷史重新演繹一遍。只是想簡單談談我對模式和它們為什么是描述設計的重要手段的一些看法。
模式沒有統一的定義。可能最好的起點是Christopher Alexander給出的定義(這也是許多模式狂熱者的靈感來源):“每一個模式描述了一個在我們周圍不斷重復發生的問題以及該問題解決方案的核心。這樣,你就能一次又一次地使用該方案而不必做重復勞動”[Alexander et al.]。盡管Alexander是建筑家,他談論的是建筑模式,但其定義也能很好地適用于軟件業。模式的核心就是特定的解決方案,它有效而且有足夠的通用性,能解決重復出現的問題,模式的另一種視角是把它看成一組建議,而創造模式的藝術則是將很多建議分解開來,形成相互獨立的組,在此基礎上可以相對獨立地討論它們。
模式的關鍵點是它們源于實踐。必須觀察人們的工作過程,發現其中好的設計,并找出“這些解決方案的核心”。這并不是一個簡單的過程,但是一旦發現了某個模式,他將是非常有價值的。對于我來說,價值之一是能夠撰寫這樣一本參考書。你不必通讀本書的全部內容,也不必通讀所有有關于模式的書。你只需要了解到這些模式都是干什么的,它們解決什么問題,它們是如何解決問題的,就足夠了。這樣,一旦碰到類似問題,就可以從書中找出相應的模式。那時,再深入了解相應的模式也不遲。
一旦需要使用模式,就必須知道如何將它運用于當前的問題。使用模式的關鍵之一是不能盲目使用,這也是模式工具為什么都那么慘的原因。我認為模式是一種“半生不熟品”,為了用好它,還必須在自己的項目中把剩下的那一半“火候”補上。我本人每次在使用模式時,都會東改一點西改一點。因此你會多次看到同一解決方案,但沒有一次是完全相同的。
每個模式相對獨立,但又不彼此孤立。有時候它們相互影響,如影隨形。例如,如果在設計中使用了領域模型,那么經常還會用到類表繼承。模式的邊界本來也是模糊的,我在本書中也盡量讓它們各自獨立。如果有人說“使用工作單元”,你就可以直接去看工作單元這個模式如何使用,而不必閱讀全書。
如果你是一個有經驗的企業應用設計師,也許會對大多數模式都很熟悉。希望本書不會給你帶來太大的失望。(實際上我在前言里面已經提醒過了。)模式不是什么新鮮概念。因此,撰寫模式書籍的作者們也不會聲稱我們“發明”了某某模式,而是說我們“發現”了某某模式。我們的職責是記錄通用的解決方案,找出其核心,并把最終的模式記錄下來。對于一個高級設計師,模式的價值并不在于它給予你一些新東西,而在于它能幫助你更好地交流。如果你和你的同事都明白什么是遠程外觀,你就可以這樣非常簡潔地交流大量信息:“這個類是一個遠程外觀模式。”也可以對新人說:“用數據傳輸對象模式來解決這個問題。”他們就可以查找本書來搞清楚如何做。模式為設計提供了一套詞匯,這也是為什么模式的名字這么重要的原因。
本書的大多數模式是用來解決企業應用的,基本模式一章(見第18章)則更通用一些。我把它們包含進來的原因是:在前面的討論中,我引用了這些通用的模式。
0.5.1 模式的結構每個作者都必須選擇表達模式的形式。一些人采用的表達基于模式的一些經典教材如[Alexander et al.]、[Gang of Four]或[POSA]。另一些人用他們自己的方式。我在這個問題上也斟酌了很久。一方面我不想象GOF一樣太精煉,另一方面我還要引用他們的東西。這就形成了本書的模式結構。
第一部分是模式的名字。模式名非常重要,因為模式的目的之一就是為設計者們交流提供一組詞匯。因此,如果我告訴你Web服務器是用前端控制器和轉換試圖構建的,而你又了解這些模式,那么你對我的Web服務器的架構就會非常清楚了。
接下來的兩部分是相關的:意圖和概要。意圖用一兩句話總結模式;概要是模式的一種可視化表示,通常是(但不總是)一個UML圖。這主要是想給模式一個簡單的概況,以幫助記憶。如果你對模式已經“心知肚明”,只是不知道它的名字,那么模式的意圖和概要這兩部分就能為你提供足夠的信息。
接下來的部分描述了模式的動機。這可能不是該模式所能解決的唯一問題,但卻是我認為最具代表性的問題。
“運行機制”部分描述了解決方案。在這一部分,我會討論一些實現問題以及我遇到的變化情況。我會盡可能獨立于平臺來討論——也有一個部分是針對平臺來討論的,如果不感興趣可以跳過這部分。為了便于解釋,我用了一些UML圖來輔助說明。
“使用動機”部分描述了模式何時被使用。這部分討論是使我選擇該模式而不是其他模式的權衡考慮。本書中很多模式都可以相互替代,例如頁面控制器和前端控制器可以相互替代。很少有什么模式是非它不可的。因此,每當我選擇了一種模式之后,我總是問自己“你什么時候不用它?”這個問題也經常驅使我選擇其他方案。
“進一步閱讀”部分給出了與該模式相關的其他讀物。它并不完善。我只選擇我認為有助于理解模式的參考文獻,所以我去掉了對本書內容沒有價值的任何討論,當然其中也可能會遺漏一些我不知道的模式。我也沒有提到一些我認為可能讀者無法找到的參考文獻,再就是一些不太穩定的Web鏈接。
我喜歡為模式增加一個或幾個例子。每個例子都非常簡單,它們是用Java語言或C#語言編寫的。我之所以選擇兩種語言,是因為它們可能是目前絕大多數專業程序員都能讀懂的語言。必須注意,例子本身不是模式。當你使用模式時,不要想當然地認為它會和例子一樣,也不要把例子看成某種形式的宏替換。我把例子編得盡量簡單以突出其中模式相關的部分。當然,省略的部分并不是不重要,只是它們一般都特定于具體環境,這也是為什么模式在使用時一般都必須做適當調整的原因。
為了盡量使例子簡單但是又能夠突出核心意思,我主要選擇那些簡單而又明確的例子,而不是那些來自于系統中的復雜例子。當然,在簡單和過分之間掌握平衡是不容易的,但是我們必須記住:過分強調具體應用環境反而會增加模式的復雜性,使得模式的核心內容不易理解。
這就是為什么我在選擇例子時選取的是一些相互獨立的例子而不是相互關聯的例子的原因。獨立的例子有助于對模式的理解。但是在如何將這些模式聯合在一起使用上卻支持不多。相互關聯的例子則相反,它體現了模式間是如何相互作用的,但是對其中每個模式的理解卻依賴于對其他所有模式的理解。理論上,是可以構造出既相互關聯又相互獨立的例子,但這是一項非常艱巨的工作——至少對于我來說是這樣。因此,我選擇了相互獨立的例子。
例子中的代碼本身也主要用來增強對思想的理解。因此,在其他一些方面考慮可能不夠——特別是錯誤處理,在這方面,我沒有花費很多筆墨,因為到目前為止,我還沒有得出錯誤處理方面的模式。在此,那些代碼純粹用來說明模式,而并不是用來顯示如何對任何特定的業務問題進行建模。
正是由于這些原因,我沒有把這些代碼放到我的網站上供大家下載。為了讓那些基本的思想在應用設置下有所意義,本書的每個樣例代碼都充滿著太多的“腳手架”來簡化它們。
并不是每個模式中都包含上面所述的各個部分。如果我不能想出很好的例子或動機等內容,我就會把相應部分省略。
0.5.2 模式的局限性正如我在前言中所述,對于企業應用開發而言,本書介紹的模式并不全面。我對本書的要求,不在于它是否全面,而在于它是否有用。模式這個領域太大了,單憑一個人的頭腦是無法做到面面俱到的,更不用說是一本書了。
本書中所列的模式都是我在具體領域中遇到的,但這并不表明我已經理解了每一個模式以及它們之間的關系。本書的內容只是反映了我在寫書時的理解,在編寫本書的過程中,我對相關內容的理解也不斷發展和加深,當然,在本書發表之后,我仍然希望本人對模式的理解還能夠繼續發展。對于軟件開發而言,有一點是可以肯定的,那是軟件開發永遠不會停止。
當你使用模式時請記住:它們只是開始,而不是結束。任何作者去囊括項目開發中的所有變化和技術是不可能的。我編寫本書的目的也只是作為一個開始,希望它能夠把我自己的和我所了解的經驗和教訓傳遞給讀者,你們可以在此基礎上繼續努力。請大家記住:所有模式都是不完備的,你們都有責任在自己的系統中完善它們,你們也會在這個過程中得到樂趣。
——選自:《企業應用架構模式》 [Patterns of Enterprise Application Architecture] [英] 福勒 著;王懷民,周斌 譯
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/30009.html
摘要:摘要隨著越來越多的業務接入云計算,云上擁有的各類資源也越來越多,用戶如何時時對其擁有的各類資源進行統計分析成為一個難題。 摘要: 隨著越來越多的業務接入云計算,云上擁有的各類資源也越來越多,用戶如何時時對其擁有的各類資源進行統計分析成為一個難題。ECS控制臺針對這一問題,推出資源概覽功能,目前支持實例和存儲兩種云資源的統計和分析功能,如果您有其它任何的數據可視化需求,歡迎留言告訴我們。...
摘要:事實上,大多數企業會從兩家或更多的服務商那里采購云服務,這一趨勢將在年進一步流行起來,并將帶動微軟阿里巴巴谷歌和甲骨文的收入。云計算實際上已經成為了推動數字化轉型和現代化IT組合的平臺。越來越多的企業正通過租用亞馬遜網絡服務(AWS)、微軟和谷歌等廠商提供的軟件,享受由此帶來的業務敏捷性或成本節約等優勢。 事實上,大多數企業會從兩家或更多的服務商那里采購云服務,這一趨勢將在2019年進...
摘要:事實上,大多數企業會從兩家或更多的服務商那里采購云服務,這一趨勢將在年進一步流行起來,并將帶動微軟阿里巴巴谷歌和甲骨文的收入。 云計算實際上已經成為了推動數字化轉型和現代化IT組合的平臺。越來越多的企業正通過租用亞馬遜網絡服務(AWS)、微軟和谷歌等廠商提供的軟件,享受由此帶來的業務敏捷性或成本節約等優勢。事...
摘要:什么是架構,什么是架構師這似乎是聊架構話題時永恒的問題。代碼寫的好就是架構嗎顯然不是。一個架構師需要足夠的技術的寬度。 什么是架構,什么是架構師?這似乎是聊架構話題時永恒的問題。代碼寫的好就是架構嗎?顯然不是。代碼寫的好只是表象,做所有事情都需要規劃,尤其是一個復雜的軟件系統,這更需要規劃,否則可能連一行代碼都寫不出。復雜...
閱讀 3520·2023-04-25 15:52
閱讀 590·2021-11-19 09:40
閱讀 2617·2021-09-26 09:47
閱讀 1035·2021-09-22 15:17
閱讀 3560·2021-08-13 13:25
閱讀 2241·2019-08-30 15:56
閱讀 3474·2019-08-30 13:56
閱讀 2113·2019-08-30 11:27