軟件體系結(jié)構(gòu)概念
構(gòu)件
構(gòu)件是具有某種功能的可復(fù)用的軟件結(jié)構(gòu)單元,表示系統(tǒng)中主要的計算元素和數(shù)據(jù)存儲。
構(gòu)件是一個封裝的實體,只能通過接口來進行交互。構(gòu)件的功能以服務(wù)的形式體現(xiàn)出來,并通過接口對外發(fā)布,進而與其他構(gòu)件產(chǎn)生關(guān)聯(lián)。
連接
連接是構(gòu)件間建立和維護行為關(guān)聯(lián)與信息傳遞的途徑。
連接件
連接件表示構(gòu)件之間的交互并實現(xiàn)構(gòu)件之間的連接。
- 管道(pipe)
- 過程調(diào)用( procedure call )
- 事件廣播( event broadcast )
- 客戶機-服務(wù)器( client-server )
- 數(shù)據(jù)庫連接( SQL )
軟件體系結(jié)構(gòu)的目標
- 可重用性:復(fù)用已實現(xiàn)證明的體系結(jié)構(gòu),或提供可重用資產(chǎn)。
- 可擴展性:易于增加新的需求。
- 可改變性:易于適應(yīng)需求變更。
- 簡單性:復(fù)雜問題簡單化。
- 有效性:展現(xiàn)系統(tǒng)滿足需求的能力。
軟件體系結(jié)構(gòu)的發(fā)展
風(fēng)格、模式和框架
- 體系結(jié)構(gòu)風(fēng)格:用于描述某一 特定應(yīng)用領(lǐng)域中系統(tǒng)組織的慣用模式,反映了領(lǐng)域中眾多系統(tǒng)所共有的結(jié)構(gòu)和語義特性。
eg: MVC就是一種體系結(jié)構(gòu)風(fēng)格。
- 設(shè)計模式:描述了軟件系統(tǒng)設(shè)計過程中常見問題的一-些解決方案,通常是從大量的成功實踐中總結(jié)出來的且被廣泛公認的實踐和知識。
觀察者模式是一種常見的設(shè)計模式,主要用于解決事件處理的問題。
- 軟件框架:軟件框架是由開發(fā)人員定制的應(yīng)用系統(tǒng)的骨架,是整個或部分系統(tǒng)的可重用設(shè)計,由一組抽象構(gòu)件和構(gòu)件實例間的交互方式組成。
eg: Django就是一個開放源代碼的外部應(yīng)用框架。
框架與體系結(jié)構(gòu)的關(guān)系?
體系結(jié)構(gòu)的呈現(xiàn)形式是一個設(shè)計規(guī)約,而框架則是“半成品”的軟件;
體系結(jié)構(gòu)的目的是指導(dǎo)軟件系統(tǒng)的開發(fā),而框架的目的是設(shè)計復(fù)用。
體系結(jié)構(gòu)可由多種框架實現(xiàn)(左:MVC,右:框架)
框架與設(shè)計模式的關(guān)系
框架給出的是整個應(yīng)用的體系結(jié)構(gòu);而設(shè)計模式則給出了單一設(shè)計問題的解決方案,且可以在不同的應(yīng)用程序或者框架中進行應(yīng)用。
舉例:一個網(wǎng)絡(luò)游戲可以基于網(wǎng)易的Pomelo框架開發(fā),這是一個基于Node.js的高性能、分布式游戲服務(wù)器框架;在實現(xiàn)某個動畫功能時,可能會使用觀察者模式實現(xiàn)自動化的通知更新。
設(shè)計模式的目標是改善代碼結(jié)構(gòu),提高程序的結(jié)構(gòu)質(zhì)量;框架強調(diào)的是設(shè)計的重用性和系統(tǒng)的可擴展性,以縮短開發(fā)周期,提高開發(fā)質(zhì)量。
軟件設(shè)計原則
-
抽象
抽象是關(guān)注事物中與問題相關(guān)部分而忽略其他無關(guān)部分的一種思考方法。
>如果系統(tǒng)中的SQL Server換成MySQL,SQLServerConnection需要全部換為MySQLConnection 。
符合抽象原則的系統(tǒng)設(shè)計,應(yīng)用系統(tǒng)發(fā)生更改的時候,只會影響接口的具體實現(xiàn)。
封裝
封裝和信息隱藏是指每個軟件單元對其他所有單元都隱藏自己的設(shè)計決策,各個單元的特性通過其外部可見的接口來描述。模塊化
模塊化是在邏輯和物理上將整個系統(tǒng)分解成多個更小的部分,其實質(zhì)是“分而治之” ,即將一 個復(fù)雜問題分解成若干個簡單問題,然后逐個解決。
系統(tǒng)分解原則
系統(tǒng)分解的目標:高內(nèi)聚、低耦合。
內(nèi)聚性是一個模塊或子 系統(tǒng)內(nèi)部的依賴程度。
- 如果一個模塊或子系統(tǒng)含有許多彼此相關(guān)的元素,并且它們執(zhí)行類似任務(wù),那么其內(nèi)聚性比較高;如果一個模塊或子系統(tǒng)含有許多彼此不相關(guān)的元素,其內(nèi)聚性就比較低。
耦合性是兩個模塊或子系統(tǒng)之間依賴關(guān)系的強度。- 如果兩個模塊或子系統(tǒng)是松散耦合的,二者相互獨立,那么當其中一個發(fā)生變化時對另一個產(chǎn)生的影響就很小;如果兩個模塊或子系統(tǒng)是緊密耦合的,其中一個發(fā)生變化就可能對另一個產(chǎn)生較大影響。
系統(tǒng)分解舉例
-
層次化
分層( Layering )
每一層可以訪問下層,不能訪問上層。
封閉式結(jié)構(gòu):每一層只能訪問與其相鄰的下一層
開放式結(jié)構(gòu):每- -層還可以訪問下面更低的層次
層次數(shù)目不應(yīng)超過7+2層
劃分( Partitioning )
系統(tǒng)被分解成相互對等的若干模塊單元。
每個模塊之間依賴較少,可以獨立運行。
注意:模塊單元增加了處理開銷,過度分層或劃分會增加復(fù)雜性。
eg: 安卓操作系統(tǒng)層次結(jié)構(gòu)
-
復(fù)用
復(fù)用( Reuse)是利用某些已開發(fā)的、對建立新系統(tǒng)有用的軟件元素來生成新的軟件系統(tǒng),其好處在于提高生產(chǎn)效率,提高軟件質(zhì)量。 - 源代碼復(fù)用:對構(gòu)件庫中的源代碼構(gòu)件進行復(fù)用
- 軟件體系結(jié)構(gòu)復(fù)用:對已有的軟件體系結(jié)構(gòu)進行復(fù)用
- 框架復(fù)用:對特定領(lǐng)域中存在的一個公共體系結(jié)構(gòu)及其構(gòu)件進行復(fù)用
- 設(shè)計模式:通過為對象協(xié)作提供思想和范例來強調(diào)方法的復(fù)用
軟件體系結(jié)構(gòu)風(fēng)格
軟件體系結(jié)構(gòu)風(fēng)格( Architectural Styles )是描述特定系統(tǒng)組織方式的慣用范例,強調(diào)了軟件系統(tǒng)中通用的組織結(jié)構(gòu)。常見體系結(jié)構(gòu)風(fēng)格
-
主程序-子程序
主程序-子程,序風(fēng)格是結(jié)構(gòu)化程序設(shè)計的一種典型風(fēng)格,從功能的觀點設(shè)計系統(tǒng),通過逐步分解和細化,形成整個系統(tǒng)的體系結(jié)構(gòu)。
-
面向?qū)ο箫L(fēng)格
- 系統(tǒng)被看作是對象的集合,每個對象都有一個它自己的功能集合;
- 數(shù)據(jù)及作用在數(shù)據(jù)上的操作被封裝成抽象數(shù)據(jù)類型;
-
只通過接口與外界交互,內(nèi)部的設(shè)計決策則被封裝起來。
-
管道-過濾器風(fēng)格
管道過濾器風(fēng)格把系統(tǒng)任務(wù)分成若干連續(xù)的處理步驟,這些步驟由通過系統(tǒng)的數(shù)據(jù)流連接, 一個步驟的輸出是下一個步驟的輸入。 -
以數(shù)據(jù)為中心的風(fēng)格
倉庫體系結(jié)構(gòu)( Repository Architecture )是一-種以數(shù)據(jù)為中心的體系結(jié)構(gòu),適合于數(shù)據(jù)由一個模塊產(chǎn)生而由其他模塊使用的情形。
問題:每個功能模塊與倉庫之間的耦合非常高。
舉例:剪貼板是一個用來進行短時間的數(shù)據(jù)存儲, 并在文檔/應(yīng)用之間進行數(shù)據(jù)傳遞和交換的軟件程序。
-
客戶機/服務(wù)器結(jié)構(gòu)
客戶機/服務(wù)器體系結(jié)構(gòu)( Client/Server )是一種分布式系統(tǒng)模型,作為服務(wù)器的子系統(tǒng)為其他客戶機的子系統(tǒng)提供服務(wù), 作為客戶機的子系統(tǒng)負責與用戶的交互。
兩層C/S結(jié)構(gòu)- 服務(wù)器只負責數(shù)據(jù)的管理
-
客戶機實現(xiàn)應(yīng)用邏輯和用戶的交互
胖客戶端:客戶端執(zhí)行大部分的數(shù)據(jù)處理操作。
瘦客戶端:客戶端具有很少或沒有業(yè)務(wù)邏輯。
三層C/S結(jié)構(gòu)
表示層:包括所有與客戶機交互的邊界對象,如窗口、表單、網(wǎng)頁等。
功能層(業(yè)務(wù)邏輯層):包括所有的控制和實體對象,實現(xiàn)應(yīng)用程序的處理邏輯和規(guī)則。
數(shù)據(jù)層:實現(xiàn)對數(shù)據(jù)庫的存儲、查詢和更新。
B/S結(jié)構(gòu)
游覽器/服務(wù)器結(jié)構(gòu)式三層C/S風(fēng)格的一種實現(xiàn)方式。
集群結(jié)構(gòu)
如果功能層或者數(shù)據(jù)層分布在多臺服務(wù)器上,就形成了集群式的系統(tǒng)結(jié)構(gòu)。
MVC結(jié)構(gòu)
影響Web系統(tǒng)模塊化的一些因素
模型-視圖-控制器(MVC)結(jié)構(gòu)將應(yīng)用程序的數(shù)據(jù)模型、業(yè)務(wù)邏輯和用戶界面分別放在獨立構(gòu)件中,這樣對用戶界面的修改不會對數(shù)據(jù)模型/業(yè)務(wù)邏輯造成太大影響。
由控制器來決定視圖與模型之間的依賴關(guān)系。
- 每次請求必須經(jīng)過"控制器-> 模型->視圖”過程,才能看到最終展現(xiàn)的界面。
- 視圖是依賴于模型的。
- 渲染視圖在服務(wù)端完成,呈現(xiàn)給瀏覽器的是帶有模型的視圖頁面,性能難優(yōu)化。
MVC改進方案
首先從游覽器發(fā)出AJAX請求,服務(wù)端接收請求,返回JSON數(shù)據(jù)給游覽器,游覽器進行渲染。
RESTful API
由于前端的發(fā)展,已經(jīng)很有必要把前端模板從后端服務(wù)器上剝離出來。這樣,后端可以專注于業(yè)務(wù)邏輯。基于MVC的后端服務(wù)器
充分利用GET、PUT、POST、DELETE四種HTTP請求。
對與web而言,我們必須讓前后端通過同一域名的同一端口訪問到,否則就會出現(xiàn)跨域的問題。跨域就是說我們不能用ajax在一個域名上獲取另一個域名或另一個端口提供的數(shù)據(jù)。解決:nginx
異步任務(wù)
假如在用戶要求執(zhí)行某種任務(wù)之后,需要執(zhí)行1min才能執(zhí)行結(jié)束,而游覽器的超時限制為30s,這時就需要用到異步任務(wù),任務(wù)管理器返回任務(wù)的id再啟動任務(wù),用戶拿到id后可以隨時查看任務(wù)的運行情況。
異步任務(wù)的實現(xiàn)方式
- 事件風(fēng)格
eg:調(diào)試器
事件管理器:IDE(集成開發(fā)環(huán)境)
事件源:調(diào)試器
事件處理器:編輯器與變量監(jiān)視器
事件系統(tǒng)是將應(yīng)用看成是一 個構(gòu)件集合, 每個構(gòu)件直至發(fā)生對它有影響的事件時才有所動作。
事件風(fēng)格的實現(xiàn)策略
- 選擇廣播式
二者是一種松耦合的關(guān)系。
- 觀察者模式
觀察者被注入到被觀察者中進行監(jiān)聽,隨時對被觀察者的變化做出反應(yīng)。
基于經(jīng)驗的選擇原則
- 層次化的思想在任何系統(tǒng)中都可能得到應(yīng)用
- 如果問題可分解為連續(xù)的幾個階段,那么考慮使用順序批處理風(fēng)格或管道-過濾器風(fēng)格
- 如果核心問題是應(yīng)用程序中數(shù)據(jù)的理解、管理與表示,那么考慮使用倉庫或者抽象數(shù)據(jù)類型( ADT ) /OO風(fēng)格
- 如果數(shù)據(jù)格式的表示可能發(fā)生變化, ADT/OO可限制這種變化所影響的范圍
- 如果數(shù)據(jù)是持久存在的,則使用倉庫結(jié)構(gòu)
- 如果任務(wù)之間的控制流可預(yù)先設(shè)定、無須配置,那么考慮使用主程序子過程風(fēng)格、OO風(fēng)格
- 如果任務(wù)需要高度的靈活性與可配置性、松散耦合性或者任務(wù)是被動性的,那么考慮使用事件系統(tǒng)或C/S風(fēng)格
- 如果設(shè)計了某種計算,但沒有機器可以支持它運行,那么考慮使用虛擬機/解釋器體系結(jié)構(gòu)
- 如果要實現(xiàn)一些經(jīng)常發(fā)生變化的業(yè)務(wù)邏輯,考慮使用基于規(guī)則的系統(tǒng)
軟件設(shè)計過程
軟件總體設(shè)計
系統(tǒng)總體設(shè)計是在需求分析的基礎(chǔ)上定義系統(tǒng)的設(shè)計目標,將整個系統(tǒng)劃分成若干子系統(tǒng)或模塊,建立整個系統(tǒng)的體系結(jié)構(gòu),并選擇合適的系統(tǒng)設(shè)計策略。
權(quán)衡設(shè)計目標
-
空間與速度
如果響應(yīng)時間或吞吐量不滿足需求,就有可能使用更多的存儲空間來進行加速。如果軟件不滿足存儲空間的限制,就可能犧牲速度對數(shù)據(jù)進行壓縮處理。 -
交付時間與功能
如果開發(fā)進度發(fā)生落后,可以考慮減少一定的功能來保證按時交付,也可以考慮推遲交付時間。
合同軟件通常更強調(diào)功能性,成品軟件更側(cè)重于交付時間。 -
交付時間與質(zhì)量
如果測試落后于進度,可以先發(fā)布一個有少量缺陷的系統(tǒng),隨后再進行升級和修復(fù)。 -
交付時間與人員
如果開發(fā)進度發(fā)生落后,加班是一個可行的方法。在項目后期,增加人手是不可取的。
確定子系統(tǒng)或模塊
選擇系統(tǒng)部署方案
系統(tǒng)部署方案是描述系統(tǒng)運行期間構(gòu)件和硬件節(jié)點之間的關(guān)系,在系統(tǒng)設(shè)計階段處理軟件/硬件的映射問題,可能會增加新的子系統(tǒng)或模塊的定義。
定義設(shè)計策略
對于微信搶票應(yīng)用來說,我們可以采用單線程、事件驅(qū)動和異步任務(wù)處理來實現(xiàn)整個控制流。