關注分離的藝術

jopen 9年前發布 | 10K 次閱讀 分離

關注分離的藝術

前言

在軟件工程中,關注的分離是指在系統中為達到目的對軟件元素的劃分與對比。通過適當的關注分離,將復雜的東西變成可管理的。這篇文章的目的是促進對關注分離的原則的理解,以及提供一個基礎概念的設置來幫助軟件工程師開發出可維護的系統。

關注點分離原則

關注點分離原則所描述的是系統的元素應該表現出互不相干的目的。也就是說,沒有會分擔另外一個元素職責的,或者其 它不相干職責的元素。關注點的分離是通過明確邊界來達成的。邊界是任何邏輯或者物理的限制,它能給一組特定的職責劃定界限。一些邊界的例子包括在一個應用 程序中定義了系統核心行為的方法,對象,組件以及服務;針對源代碼組織結構的項目,方案,以及目錄的層級結構;用于處理組織的應用程序層級或分片結構;以 及用于產品發布組織結構的版本庫和安裝文件。盡管達成關注點分離的處理經常涉及一組職責的分離,但其目標并不是將系統限制成一個不可分割的部分,而是去將 系統組織成互不重復的高凝聚的責任單位。正如阿爾伯特愛因斯坦所言 “讓一切盡可能簡約而不簡單。”本質上講,關注點分離關乎于秩序。關注點分離的全局目標是建立一個組織良好的系統,其每個部分都滿足一個有意義和直白的作 用,從而最大化其適應改變的能力。

關注點分離的價值

將關注點分離原則應用于軟件設計有許多的好處。首先,單個組件少了重復并且目的單一,會使得整個系統更易于維護。其次,作為提高了可維護性的副產品,系統 整體變得更加穩定。第三,這一需要確保每個組件只把關注點放在一組單一明確職責的策略,常常可以得到天然的可擴展性。第四,由組件專注于單一目標所形成的 解耦,使得在其它系統中的復用,或者在同一個系統中的不同上下文的容 留,變得更加的容易。關注點分離原則在應用于商業組織機構時也可以帶來好處。在大公司中,確保組織及其子機構分配到獨立明確的職責,將有助于通過最小化團 隊之間的協調工作,并最大化每個團隊專注于其各自職責的潛能,來促進整體目標的達成。關注點分離原則同樣能促進企業級規模的系統性問題的解決。當責任被正 確的分配,問題的定位就會變得更加容易,解決起來更加快速, 個人的職責能力也得到了增加。這些領域中的每一個都可以回過頭來使得質量控制過程得到促進。無論所面對的是有人構成的組織,還是軟件系統,關注點分離原則 都能通過消除不必要的重復和分配適當的責任來幫助對于復雜性的管理。在下一節,將討論在應用程序的設計中實現關注點分離,可以使用的各種技術。

水平分離

關注點的水平分離指的是將一個應用程序分離成滿足應用程序中相同角色邏輯功能層級的過程。一個通行的針對圖形用戶界面應 用程序的分離就是對展現層、業務層和資源訪問層進行分離的過程。這些類別涵蓋了大部分應用程序所需要的主要關注點,并呈現出一種最小化了應用程序中依賴層 次的組織結構。圖 1 就描述了一個典型的三層級應用程序:

關注分離的藝術

    圖 1

表示層包含與應用程序用戶界面相關的處理和組件。這包括組件定義一個應用程序的可視化顯示,并可能包括先進的設計理念,如控制器,演示層,或表示模 型。表示層的主要目標是封裝所有用戶界面的關注,以便允許應用程序域獨立變化。表示層應該包括所有組件和過程,只涉及到應用程序的可視化顯示需求,并應排 除其他所有組件和流程。這允許在應用程序中的其他層不同于他的顯示關系。業務層包含與應用程序域相關的流程和組件。這包括定義對象模型、管理業務邏輯、控 制系統工作流程的組件。業務層可以通過專門的組件為代表的工作流程,為業務流程,并在應用程序使用的實體,或通過傳統的面向對象的域模型封裝了數據和行 為。業務層的主要目標是封裝核心業務關注的應用程序的數據和行為如何被曝光,或如何具體地獲得數據。業務層應該包括所有的組件和流程,只涉及到應用程序的 業務域,并且應該排除所有其他組件和流程。資源訪問層包含相關的外部信息的訪問過程和組件。這包括與本地數據存儲或遠程服務接口的組件。資源訪問層的目標 是提供一個圍繞數據訪問特定的細節的抽象層。這包括建立數據庫和服務連接的任務,維護數據庫模式或存儲過程的知識,服務協議的知識,以及服務實體和業務實 體之間的數據的傳送。資源訪問層應該包括所有的組件和過程,只涉及到系統訪問數據的外部,并且應該排除所有其他組件和過程。面向服務的應用程序使用的另一 個公共部門是將應用程序劃分為服務接口層、業務層和資源訪問層,如圖 2 所示:

關注分離的藝術

Figure 2

這部分,業務和資源訪問層服務于先前討論的相同的目標,暴露的服務封裝成一個服務接口層。這層包括服務接口,如業務流程的曝光,通過各種協議服務的 約定和數據類型的管理。服務接口層的主要目標是封裝所有服務接口,以便允許應用程序域獨立地改變。服務接口層應該包括所有的組件和過程,只涉及到應用程序 的曝光服務,并且應該排除所有其他組件和過程。分組處理涉及基于他們的應用程序中的作用,提高整個系統的可管理性。這些好處包括易于維護,通過一致的體系 結構和隔離的過程,增加了絕緣的變化的影響,增加適應性變化,并增加了潛在的重用。

垂直分離

垂直分離指的是將應用程序劃分為與子系統功能相似的功能模塊。垂直分離將整體應用的特點,在一個單一的邊界內,將任何接口、業務和資源訪問問題關聯。圖 3 描述了一個應用程序分成三個模塊:

關注分離的藝術

Figure 3

將一個應用程序的功能分離出來,闡明了每個功能的責任和依賴關系,可以幫助測試和整體維護。從邏輯上講,邊界可以定義為幫助組織,或物理上,獨立的 開發和維護。邏輯邊界意味著模塊化的存在,雖然用于表示分離的方法可能與應用程序的實際部署或運行時行為無關。這對于提高應用程序的可維護性是有益的,因 為在物理上分離功能的未來的努力是有益的。圖4描述了一個包含邏輯邊界的應用程序:

關注分離的藝術

Figure 4

物理邊界通常被用在開發插件或者組合式應用程序這些場景中, 可以使得其功能特性由不同的開發團隊來管理. 支持模塊插件技術的應用程序經常采用諸如自動發現,或者基于一個外部配置源來對模塊進行初始化的技術。圖 5 所展示的托管框架就包含了由不同的開發團隊開發的模塊:

關注分離的藝術

    圖 5

而垂直的分離,會基于總體上能實現一個應用程序中的特定功能,對彼此相關的一個關注點集合進行組合, 而這并不排除對其它關注點分離策略的使用。例如,每個模塊其自身可能會被設計成使用層級來圈定模塊內部組件各自的角色。圖 6 展示了一個同時使用垂直和水平關注點分離策略的應用程序:

關注分離的藝術

圖 6

切片式分離

關注點的切片式分離,更有名的對應術語是面向切面編程, 指的是將跨域關注點從應用程序的核心關注點中分離出來的過程。跨域關注點,或者說切片,就是那些會穿插在應用程序中多個邊界中的關注點。日志就是一個會跨 越多個系統組件執行的動作示例。圖 7 展示了一個包含一些跨域關注點的應用程序:

關注分離的藝術

圖 7

由于其廣泛分布于整個應用程序的多個位置,所以跨域關注點很難被維護。將它們同核心的關注點混在一起,就會變得更加復雜起來,這導致應用程序更難于 被維護。通過分理出這些關注點,使得核心關注點和這些跨域的關注點都更易于管理。切片分離不同于其他的分離技術,它依賴于一種編譯時或者運行時的預處理, 以同應用程序跨域關注點分離策略相融合。融合兩個關注點的過程過去被比喻為“編排”。 通過使用不同的策略,跨域關注點可以被分離,并為了保持運行時的聚合,會被編排回到應用程序之中。切片分離工具在大范圍的編程語言中都是可用的。更多有關 這個主題的信息,包括設置切片分離的工具集合,可以看看這里的《面向切面編程》。

依賴方向

關注分離的一個好的特性是依賴方向的完美建立。一個完美的依賴方向確立了消費者和依賴的角色,因此依賴的角色是被最有可能被可復用的實體占用。用一個簡單的例子來說明依賴方向的概念是業務組件和功能組件之間的一般關系。假設提供一個命令審查流程的系統要求高效的緩存頻繁請求的數據。為了提高命令審查的緩存,一個緩存功能組件也許是從命令審查流程的剩余部分中分離出來的。圖8表示這個項目被分成兩個組件:

關注分離的藝術

8

因為緩存功能是不查詢處理更加通用的功能,所以兩者之中緩存組件具有更高的復用潛力。因此,該場景中最佳的依賴指向是從業務組件指向工具組件。這一依賴顯示在了圖 9 中:

關注分離的藝術

圖 9

這樣的一種關系可以讓緩存組件不用去理會查詢處理如果進行,使其可以為以后的處理過程復用。

數據關注

采用關注分離策略來使數據轉變為合適的模塊化的信息,從而讓系統將信息管理起來。當數據模型采用面向對象和數據庫設計時,由于數據庫的基本需求往往需要遵循特定的功能,因此這里所說的主要是面向對象的數據關注。

當 在對象模型里組織數據的時候,對外的信息應該是表示實體所固有的信息。例如,給一個銷售產品給客戶的系統,定義一個產品的對象應該不包含客戶的相關信息。 這是由于產品不應該包含購買這個產品的用戶的信息。一個較好的解決方法應該是生成一個組合客戶和產品信息的訂單對象。這可以讓產品對象在未來被其他不關心 客戶信息的程序復用。

除了考慮到數據模型在不同的環境中復用外,當維護較復雜的系統時數據組織的直觀性也是很有幫助的。例如,如果 一個新的開發者負責對已存在產品對象的指定的部分組成的序列號的訪問, 開發者可能會先試著找出產品指定的部分,然后在這些部分尋找“序列號”或者相似名字的屬性。開發者一般不會想到查找諸如“產品號轉換為序列號”專業術語之 類的東西去定位產品對象,因為這不是數據自然的表現。這類似于通過人們已有序列號的腕表來生成一個人的序列號。

然而,有時當數據的自然組織方式不能為信息提供一個有效的查詢機制。例如,一個極其復雜的產品對象,這個對象需要頻繁的檢測獲取所有銅元素的總數量,這通過檢查或者對象的組成元素之間的交叉引用就不是那么有效了。

在 這個案例中,當自然模型不能滿足自身需求時,一個對象模型的完整性可以通過補充概念類型去滿足特殊的需求去維護。例如,如果產品的組成保留了一個靜態變 量,一個概念性的模塊表示由同級的產品信息組成的產品的貴金屬信息(例如“ProductPreciousMetalManifest“) 。如果產品的組合頻繁的改變,并且組合的流程是集中的,那么貴重金屬信息或許可以作為這個流程的一部分而被更新。此外,一個專用的模塊 (如"PreciousMetalDetector")能便利去動態返回產品的貴重金屬信息。

就像第一個例子那樣,分離概念從其他自然模型得到的好處是模塊被另一個程序復用時不會引起非固有屬性的額外開銷,和保持易維護性。

行為關注

行為分離涉及到系統流程在邏輯上,管理上,代碼單元的可復用上的分離。這表示關注分離的最基本的類別。

在面向對 象系統內,細膩的行為使用方法分離,而寬泛的行為通過對象,組件,應用,和服務分離。就像數據分離,封裝行為應該也包含邊界。例如。一個命名 為"CreateCustomer()"的方法就應該只包含創建一個新客戶的行為。而不能包含為新客戶下訂單的行為。 類似的,一個命名為"ProductAssembler" 組件的就應該只包含產品組裝的數據和行為,為不能包含客戶的數據和行為。

為了達到好的行為分離,這通常是一個反復的過程。一個系統的基本行為在設計階段只是一般的設想,但是在實現系統的時候,設計經常會被反復的重構直到細節部分慢慢的呈現出來。

當組織行為時,你的目標應該是尋求:1.沒有重復的功能。2.限制行為的范圍達到最小化。3.限制行為的范圍在含有邊界的描述以內。4.限制行為的范圍在含有邊界的應有的行為以內。5.最小化外部依賴。6最大可能的復用。

擴展關注

擴展是一種關注分離的策略,它可以將新的動作附加到現有的關注集合。擴展被用來增強現有的關注,需要的動作不會被添加到目標系統,它不是系統的固有動作, 也不會不切實際地被納入作為系統核心功能集合的一部分。圖 10 顯示了一個擴展跟一個目標系統的依賴關系:

關注分離的藝術

    圖10

擴展在對關鍵事件的通知進行的響應中與目標系統發生互動。擴展所提供的行為示例,包括新視圖和空間的顯示,改變正常進行的處理過程,還有目標系統中 的數據修改。擴展一般采用托管加載的形式,一般通過配置或者一個動態發現過程進行注冊。當一個企業中有多個客戶端應用程序正在被維護,你可能會發現一個客 戶端所提供的擴展或許也能被其他的客戶端使用。如果擴展是針對目標應用程序進行了高度定制的,并且提供了某種相對簡單的性能,在一個新的應用程序中能采取 的最佳措施就是復制該功能.。反之,如果擴展的行為規模較大且復雜度較高,那么一般通過一個企業服務來提供其行為或許是更好的辦法。如果由服務所提供的行 為仍然不適宜作為主系統的一個核心依賴,那么就可以針對它開發一個新的擴展來同代表了應用程序的服務進行交互。

委派關注

委派關注指的是將責任分派給能滿足該行為的一個子組件的過程。這一策略從執行那里將責任的關注點分離,并且有利于設計出 根據外部條件表現出不同行為細節的組件。使用這一策略, 組件代理針對另外一個組件的某些或者全部請求和方法調用被設計成以一種特殊的方式滿足請求。例如,組件會被設計成需要返回的分配給當前用戶的角色清單,以 請求的形式分發給一個或者更多個被設計成從本地 XML 文件,數據庫甚或一個遠程服務獲取角色信息的子組件。圖 11 描述了將授權關注向針對特定不同數據源的組件的委派策略:

關注分離的藝術

    圖 11

委派可以使用策略模式Plug-in 模式Microsoft Provider 模型 做進一步發展,而其他的模式變體則可以使組件的行為在外部被實現。

反向關注

反向關注,亦稱作控制反轉,指的是將關注移到既定邊界之外的過程。一些對反向關注的使用包括影響面分離,非必要過程最少化,組件從特殊抽象策略處解耦,還 有搬遷基礎設施組件的職責。一些特定的應用程序包括減輕有關硬件的交互,工作流管理,注冊過程以及獲得依賴。圖12 顯示了一個分享關注的過程,其中展現組件和域組件都已經將關注移動到了基礎設施級別的組件:

關注分離的藝術

圖 12

可以看到對關注進行反轉的一個示例就是對 模板方法 模 式的使用。這種模式被用來對一個過程的行為進行規約化,以此來通過集成實現行為的各種變化。當把這一模式應用到一個現有的組件上的時候,所需處理過程應該 執行的步驟就是將其規約并封裝到一個基類之中。然后現有的組件會要繼承自這個新的幾類,組件內部只保留特殊的行為。其他類型的組件則可以自由選擇是否繼承 自這個幾類來提供不同的實現。這應該就是一種算法序列的關注反轉的示例。 另外一個反轉關注的示例還可以在將一個交互式控制臺應用程序轉化成一個 GUI 應用程序時被觀察到 一個典型的交互式控制臺應用程序提供了一個能先用戶顯示信息并等待數據被輸入的主循環。當要被轉成 GUI 應用程序時,程序的主要控制邏輯部分一般由基礎設施組件來提供,而用戶交互的提醒機制則使用 觀察者模式 來 完成。這就轉而使用戶計劃的處理主要控制邏輯去依賴于應用程序的基礎設施,或者這些關注點的托管環境。依賴注入是一個被應用到有關于從外部獲取依賴的關注 反轉的術語。依賴注入的目標是將對于依賴如何獲取的關注從一個邊界內的核心關注分離。這樣的通過根據上下文來對組件進行不同的依賴供應,提高的可重用性。 依賴注入的過程一般涉及到容器、依賴和接收者這些角色。由一個組件所占據的容器角色,它所負責是想一個接收者組件分配依賴。容器一般使用 工廠 模 式來進行實現,以實現接收者和依賴組件的創建。依賴的角色由將要被提供給接收者的資源所占據。容易常常被實現為讓現有的對象可以被注冊成為一個依賴來使 用, 或者在需要時創建出新的實體。接收者的角色有從容器那里接收依賴的組件所占據。接收者需要使用有容器所提供的某種策略來聲明所需要的依賴。識別依賴信息的 策略一般采用反射的運用來檢查接收者一個或者更多個成員的類型,而且可能還需要利用屬性/注解來隱式或顯式的指定依賴。圖13中的一個序列圖展示這些角 色。

關注分離的藝術

    圖13

一個對依賴注入的使用示例就是將緩存功能從一個業務組件中抽象出來,替換使用工廠(Factory )或者工廠方法(Factory Method)模式。通過使用依賴注入來想一個接收者供應緩存組件,無需特定工廠的耦合增加,接收者就可以同緩存組件保持松耦合。另外一個例子就是使用依賴注入來控制緩存組件創建的數量,替換之以 單例模式(Singleton Pattern) 的使用。這樣就能讓應用程序在整個應用程序的生命周期中都只使用一個實體,或者是去控制決定哪一個接收者接收到哪一個組件的實體。這也提升了通過模擬依賴 的供應,隔離出依賴一對組件進行測試的能力,而不需要所需的單例跟隨它們的使用者同時被測試。組件使用諸如工廠,工廠方法,抽象工廠,單例,插件,服務定 位器,這些模式來抽象對象創建或者依賴獲取的關注,是考慮用依賴注入進行補充或者替換的一種良好選擇。通過使用依賴注入代替、或者與這些或者其它這樣的模 式合作,使用的組件可以從抽象策略那里完全抽象出來。

夸張練習

現實的情況常常是一次設計上的選擇,特別是那些針對靈活性和可重用性的設計,其負面影響往往只會在系統變得穩定之后才會 變得明顯起來。靈活和可重用性上的問題其根源往往是沒有遵守關注點分離原則。有一個過程可以對關注點的優化起到輔助作用,那就是考慮將設計應用到比較夸張 的場景環境下。通過這項練習,夸大系統的使用條件,使其超過了對系統能力的已知預期,從而揭示出一個設計方法中潛在的薄弱之處。例如,當要設計一個被兩個 現有系統所使用的對象模型時, 人們應該考慮當對象模型被 50 個系統共享時會產生的后果。通過夸大設計的使用條件,缺乏組織的責任將變得很容易被識別。為了展示這項練習,考慮如下針對創建一個新的綜合客戶關系管理系 統的關注: 在一個企業中,一個 IT 部門被要求創建一個定制的 CRM 應用程序,它可以讓不同的開發團隊貢獻功能的特定模塊。企業中主要的客戶關系環節將是營銷,結算和技術支持,貫穿其中可能就是被分配用來支持每個環節的功 能的多個開發團隊。應用程序也被要求能顯示一個主屏界面,可以通過姓名,地址,電話號碼,訂購編碼和其它已經注冊過的產品編碼,等等查詢條件,來對客戶進 行查詢。而結果視圖和工作流則應該依據制定的時間采用了那種業務功能來決定。例如,在提交客戶的查詢條件時,銷售用戶看到的顯示應該是有關于過去的購買趨 勢,信用等級分數以及建議的銷售上限視圖;而向結算用戶所展示的則可能是客戶的支付記錄,糾紛歷史,和突出的余額。初步分析表明,五個不同的搜索條件域會 導致總共有三種工作流程的變化,而所有環節需要獲取的信息將會涉及到三個后臺系統。因為變化程度比較低,所以做出的選擇就是在將主視圖,客戶搜索功能和工 作流初始化放到一個搜索模塊中。增加新的搜索條件和工作流程被理解為需要由搜索模塊開發組來進行修改,但相信這些修改需求不會太頻繁。而將夸張練習應用到 這一設計決定,考慮如果業務環節或者后臺系統的數量被增加到 50 個,會有什么后果接踵而至。將搜索功能和工作流的初始化集中到一起的后果就是,增加這些關注的范圍的同時,也將增加搜索模塊開發組的責任和工作壓力。這會 包含對所有功能特性和變更請求的有關關注點的范圍界定,分析,設計,編碼和測試。反過來這可能會導致搜索模塊組對于增加開發資源數量的需求。也還有可能導 致這些關注點合并的同一個初始假設也會影響到其它針對搜索模塊所作出的設計決定。這可能已經導致設計決定可能不太容易適應這種責任的增加,而需要做某些程 度上的內部設計來處理新的關注。通過這一練習可以關注到的一個突出問題就是需要由搜索組付出的工作量跟由該系統所支持的業務環節和工作流程的數量成比例相 關。初始方案不能隨著需求的增加而擴展,這一事實所表明的可能就是關注被不恰當的分布在整個系統中了。加強搜索功能的決定及其所導致的把工作流做到搜索模 塊中的選擇,是識別每個用例之間相似處所導致的。所沒有給與同等考慮的則是每個用戶應該以特別的方式看待這一事實,還有責任的數量沒有真正的邊界這一事 實。以為搜索屏幕為許多模塊提供了集中的功能呢,就可以說它擁有了固有的基礎設施級的關注。然而,每個情況中的細節并不是一樣的,而且可以被認為是每個對 應模塊的固有關注。隨著對于固有職責的識別,可選的方法應該包括一個用來鞏固共同關注的框架的開發,但可以分出每個領域特定的關注。這樣一種方式可以通過 要求每個模塊提供一個可以注冊可用搜索條件,并提供調用對應工作流程的處理能力的附件來完成。一個框架應該來負責顯示搜索條件的統一視圖,并提供一個通用 的基礎設施,來講每個搜索條件同對應的工作流處理器相關聯,通過使用這種方式,搜索模塊可以被設計成能容納無限數量的用例. 而夸張練習在創建高靈活性的設計中很有用,這僅僅是其實現關注分離最佳方案這一原始目標的一個副產品。夸張聯系可能可以同獲取一個病人的體溫的醫療實踐進 行類比,這項醫療實踐測試的是可能的潛在問題所對應的癥狀。這一練習嘗試去通過檢驗潛在設計設計的可擴展性這一方面,來確定關聯到關注分離上的問題。這可 能被類比于圖 14 所示的用放大鏡去觀察細節。

關注分離的藝術

    圖14

它是通過將設計的實際范圍擴大,使得小的問題更加容易被識別出來。一旦被識別出來,隨后就可以來確定該采取什么樣的行動了。

分離焦慮

對關注分離原則進行的應用所涉及到的先進概念和架構,其為應用程序所帶來的一定程度上的復雜級別會超過僅僅只解決應用程 序原本關注領域上的復雜度。而對于在這些編程技術上沒什么經驗的開發者而言,其反應是看到了有將個人關于設計技能的所有本領統統加入的機會,充滿了=熱情 的興奮之意,而不好的反應就是對與復雜性的附加兩,會導致行動上以盡可能最方便的權宜之計來完成工作。這些技術常常導致缺乏經驗且頭腦更加戰術性的開發者 在他們初次學習遇到挫折時認為這樣的設計“過于復雜”或者“設計過度“了,然后就只是在日常基礎的層面上來使用這樣的架構。更有甚者,常常有永遠存在的, 來自于項目經理、產品經理、更高級別的管理者、市場人員或者最終用戶的需要即時滿足其需求的現實壓力,會使得情況趨向于鼓勵和獎勵權宜之計,而不是深思熟 慮的長遠設計。這些條件給開發好的設計所帶來的障礙超過了僅僅只需要去解決的技術問題。而那些能促進關注分離的設計常常會增加應用程序的復雜度,所以應該 指出它們其實也幫助去除了一些由于缺乏關注分離而導致的復雜度。對于許多應用程序而言,常常是有序的復雜度和無序的復雜度間的折中。沒有表現出一定程度上 的關注分離的應用程序常常由于需在理解部分之前先理解整理而難于學習,而且難于去維護和擴展。高度復雜,而缺乏模塊化的應用程序也會導致開發人員的高頻率 周轉(這往往會使得設計和實現的問題更進一步), 或者吸引那些討厭改變的人尋求在組織內打造使自己職業不可或缺的”迷宮“。開發團隊應該因為復雜而復雜(除非是進入了一個目標比較模糊的競爭之中), 而認為避免先進的設計就等同于避免掉復雜性的這一觀點則應該被驅散。

總結

簡而言之,關注分離原則的目標就是建立秩序。通過確保系統之中的元素只擁有單個唯一的用途,復雜的系統可以設計得將生產力和可維護性得到最大化。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!