本篇博客意在對比軟件工程領域的結構化方法與面向對象化方法,在開始對比以前咱們要先知道這些方法出現的背景,並對這兩種方法有一個大體的瞭解。下面先讓咱們來一塊兒探究一下它們出現的背景。java
對於軟件工程領域而言,它的終極目標是:有效地獲得一個運行的系統及其技術支持文檔,同時該系統須要知足有關的質量要求。web
這樣的系統就是軟件開發方法最終須要達到的目標。在達到這個最終目標的過程當中,咱們須要實施一系列的軟件活動,包括設計,約定接口,制定編程規範等。軟件的需求越多,體積越龐大,咱們實施的軟件活動自己的複雜性也就越高。爲了可以有效地組織起軟件生存週期中這些活動的實施,咱們須要選擇相應的組織框架,進而造成特定的項目生存週期的過程。這也就是結構化方法和麪向對象化方法自己的意義所在,它們能夠幫助咱們更好地規劃與管理軟件工程中具體活動的實施。算法
不少人都以爲本身未曾在軟件工程中使用過結構化的或面向對象化的方法,博主猜想他們這麼體會的主要緣由多是他們並無實施過完整的軟件構建流程,而僅僅是將軟件看成了一段程序來寫。數據庫
寫一段程序和構建一個軟件是有很大不一樣的,拿ACM競賽中的比賽程序舉例,這些程序都有固定的每每不帶提示信息的輸入與輸出,程序寫得好與很差主要取決於算法的性能,有些時候也會參考代碼的風格。但它們相比軟件很大的不一樣之處在於:程序不須要考慮用戶輸入,也不須要考慮用戶體驗。可是軟件工程活動構建的產物——由需求而非輸入輸出定義的軟件須要這些額外的東西。編程
而構建一個軟件則須要細緻的計劃,編寫,測試等,下面就來一塊兒看一下結構化方法吧。後端
通常來講軟件的生命週期能夠被劃分爲:軟件計劃,軟件分析,軟件設計,實際編碼,軟件測試(包括了黑盒,白盒,單元,迴歸測試等)及運行維護等階段表示。結構化方法包含了其中的兩個部分:軟件工程結構化分析(structured analysis,SA) 以及 軟件工程結構化設計(structured design,SD)。瀏覽器
結構化分析是結構化方法的一部分,其主要目標是系統化地使用給定的信息,可以造成對問題的估算求解。緩存
舉個例子,對於軟件工程中的需求分析環節,咱們如何結構化分析呢?服務器
在結構化分析中有三個要素,分別是:數據結構
下面針對這些咱們來逐一闡釋這些問題,首先的問題是在結構化分析中須要使用到的信息。
結構化分析方法中有五個必要的組成元素,分別是:
這幾個基本術語都比較抽象,咱們舉個例子來講明一下它們在現實生活中的映射。
好比咱們要設計一個簡單的門系統,這個系統的需求看起來很明確:門嘛,相信正常人都會理解。但實際上所謂的這個門系統就只是定義了一個模糊的抽象層而已,它定義了:
Markdown
或者其餘富文本格式,博客文本做爲數據在博主與博客園之間流動。而在其餘人瀏覽時,博客園從後端取出博客內容,爲博客加上CSS樣式,最後由瀏覽器渲染展現給瀏覽的人,這其中數據以HTML的格式從博客園的服務器流向了用戶的瀏覽器,這是另外一種數據的流動。剛剛咱們提到了五個抽象的名詞,那麼在實際使用中,對於這些信息流的抽象層咱們該如何發揮他們的做用。換句話說,咱們該如何系統化地使用這些信息?這時模型表達工具就頗有用了。在結構化的方法中通常使用三種模型表達工具:
在這三種模型表達工具中,數據流圖和數據字典在數據庫的設計中可能出現頻率更高些,這兩種模型工具與數據自己關係很緊密。
這三種模型表達工具結合起來涵蓋了系統總體建模的整個流程,下面讓咱們來使用結構化方法完成一個完整的建模過程。
在對總體建模時,咱們首先要藉助數據流圖構建一個系統功能模型。要完成系統功能模型,咱們首先要肯定系統的邊界——數據源和數據潭;在區分好系統和其邊界後,也就建好了系統的頂層流圖,這是再開始對整個系統自頂向下逐步求精地創建系統的層次數據流圖。這裏體現了咱們結構化分析方法中的一個重要思想:自頂向下,逐層分解。
咱們依舊用博客系統來舉例,若是要咱們創建一個簡單的博客系統,其中:
根據需求畫出其數據流圖以下:
這時咱們的頂層數據流圖就已經完成了,但由於此時咱們只有一個需求明確,數據操做並不明確的系統。接下來咱們就須要將這個模糊不清的系統的功能細化,將不一樣的數據流與不一樣的操做鏈接,而非只是跟系統這個黑盒相連。
咱們將博客系統分紅兩部分,一部分是文章系統,一部分是評論系統,而後將這兩部分與它們分別對應的數據流相連,就能夠造成一個具體一點的系統,以下圖所示。
在完成數據流圖的構建後,咱們須要使用數據字典來定義數據流、數據存儲和數據項。
好比博客 = 博客標題 + 博客正文 + 博客做者 + 時間戳
這就是一個簡單的數據字典的定義。
最後須要爲數據加工添加約束條件,好比博客的正文必須大於十個字才能發佈,與上一次博客編輯的時間差要大於10s才能更新等。
說完告終構化分析,下面咱們來說講結構化設計。
與結構化結構化設計的主要目標就是給出一個軟件的解決方案,它主要分爲兩個主要部分:
這兩部分關係是由上到下的,先進行系統的設計,再進行各個模塊的設計,同時也映證告終構化方法的基本原則之一:自頂向下功能分解。
在系統設計中,主要目標是用於肯定各個模塊之間的調用關係和系統的總體結構。因爲結構化分析中獲得的數據流圖並不能徹底匹配結構化設計的需求,系統設計的目標就是爲了過渡這種差別,將上述結構化分析獲得的數據流圖轉換爲模塊圖以供進一步設計。在結構化設計中常採用結構圖來描述程序的結構。
結構圖的基本成分有模塊、調用和數據。下面是一個結構圖的示例
在結構化設計中有一個很是重要的原則,那就是基於模塊化原理的高內聚,低耦合。
將數據流圖中直接轉換獲得的各個子模塊進行改進,經過模塊的分解和合並,力求下降耦合,提升內聚。好比說能夠將多個模塊公用的子功能能夠獨立造成一個模塊,供這些模塊調用。
結構化設計的目標是將一個初始的模塊結構圖轉換爲最終的模塊結構圖,並把各個模塊的描述不清的需求肯定下來,因此對於設計人員來講結構化設計是一種挑戰,設計的質量將直接影響軟件系統開發的質量。
介紹完告終構化方法,下面來粗略瞭解一些面向對象的方法。
面向對象方法的出現晚於結構化方法,但其發展壯大之迅速是軟件開發領域的一個奇蹟。它的概念很是明確,它是一種運用對象、類、繼承、封裝、聚合、 關聯、消息、多態性 等概念來構造系統的軟件開發方法(引自《面向對象的系統分析(第2版)》,邵維忠, 楊芙清著,清華大學出版社,2006.12.)。在這裏博主不展開講面向對象分析與面向對象設計方法,主要講述一些它的特色,覺得後面的對比進行鋪墊。
在面向對象方法中,最重要的概念就是對象的概念:對象是系統中用來描述客觀事物的一個實體,它是構成系統的一個基本單位。
對象是構成世界的一個獨立的單位,它具備兩方面的特徵,一方面是靜態特徵,另外一方面是動態特徵。
面向對象的方法中對象的屬性和操做是合爲一體的,它們一塊兒構成一個獨立的實體。對象內部細節對外部來講是不可見的,對象自動維護本身的狀態使本身保持正常運轉,外部不須要維護對象的狀態變化。
上面咱們初步瞭解了兩種方法,如今讓咱們來一塊兒看一下它們的差異。
對於結構化方法,一切系統都是由信息流構成的。信息流中既包含了一些必要的數據變換,每一個信息流都有本身的起點和歸宿,又包含了驅動信息流動的數據操做。整個系統能夠被看做是經過數據操做把流動的信息流來組織起來的模型。
因此在結構化方法中,信息流的概念很重要,不管是在分析仍是在設計時咱們都須要當心翼翼地對待信息流動的方法,源頭,終點。
而在面向對象方法中,一切系統都是由對象構成的。對象之間的相互做用和相互影響構成了各式各樣複雜多變的系統.
結構化的設計關注的是事件的發生,因此更像是面向過程程序設計的風格,好比說C程序的風格。面向對象的設計關注的是對象的功能,好比說Java程序的風格。
在我看來,結構化方法更像是小說,而面向對象的方法更偏向於產品說明書。
提及小說,小說三要素分別是:人物,環境與故事情節。
人物
身上的方法小說該如何吸引人呢?須要咱們的人物形象刻畫豐滿、故事情節動人,均可以吸引咱們。所以在咱們閱讀小說的時候,注重更多的是發生在這我的物身上的情節,固然,環境對於整個故事的推動也很重要。聯繫面向過程的程序,一個面向過程的程序描寫的是什麼——以C語言爲例,一個主函數,定義局部變量、全局變量,而後調用子函數,子函數的目的是對變量、數據結構進行操做,是發生在該變量以及該數據結構身上的事情,在主函數中,
void open(Door *door) { // do... } int main() { // do... open(_door); // do... }
這段代碼描述的是門的「開」行爲:一個行爲「開」發生在了門上。這是一個故事情節,講述了這個行爲的發生。面向過程關注的是過程的發生,針對咱們的軟件來講,就是:你有什麼樣的情節,就編寫什麼樣的軟件。
而產品說明書,很明顯是在描述一個產品的屬性。一個產品的規格如何、他有什麼樣的功能,列齊了在一個表上,至於你怎麼使用那就是使用者的,我把這個產品的規格、功能都呈現給你,隨便你去用。不是說用private
保護起來就叫作封裝了,它是用來區份內外的。對於外部的調用者,對象自己提供的就是一張產品使用說明書,你只須要知道怎麼用,門怎麼開,須要多大的力度,門把手須要轉多少度,角度最大能長多大,這些都是產品自身的屬性。舉個例子:
class Door { void open() { // do... } }
這就比如是一張產品的說明書,這個產品的名字叫Door,它呈現的是open這個接口,外部調用者只須要知道,哦,這個東西能夠開啊。而對於門來講,它也不care外部是誰在用,它只須要在open時狀態正常就能夠了。封裝區份內外,內部我來維護、外部我無論,當我修改了open內部的東西時,外部的人根本看不出來我改了,他該用照經常使用,這是由面向對象帶來的可維護性。
對於結構化設計來講,由於其建模所須要的就是「過程」和「數據」,而在客觀事物中過程與數據偏偏是最容易變化的性質,因此結構化方法的可維護性就要比面向對象的方法可維護性要差。改動A的同時須要B、C分別做出相應的改動。因此在可維護性上,結構化方法不如面向對象的方法。
在上面咱們提到告終構化方法的可維護性較差,在這個需求變化愈來愈快的時代顯得力不從心。可是結構化的設計方法必然是有其優勢和長處才能依然立足於軟件工程領域的,也是C/C++語言一直被用做底層語言的一個重要特色:足夠快,性能高。
1980年至今,CPU性能提升了近10W倍,但內存的訪問性能和效率只提升了不足100倍,主要緣由其實並不在於內存部件進展較慢,而在於程序對內存的訪問效率大大下降。而面向對象方法的一些弊端由於其特性的濫用而凸顯出來。與結構化須要即訪問不一樣,面向對象程序要通過不少間接過程才能訪問到目標內存地址,這種間接使得有些時候程序並不能充分利用硬件的最佳性能。面向對象方法的性能問題主要體如今如下方面:
過分封裝。從好的方面來講,封裝簡化了系統設計,將複雜問題抽象成較簡單的獨立對象,經過對象的相互調用去實現方案,但因爲對象包含本身封裝的數據,使得運行一個邏輯時數據會分散在不一樣的內存區域,會產生較多的Cache Miss。
數據佈局。咱們通常會認爲,將相互之間關聯的數據緊湊地放在一塊兒對緩存友好,然而,在實際應用場景中,咱們須要考慮數據的存取模式。一般來講,面向對象中一個方法只會訪問一個對象不多的數據,卻由於數據佈局的問題不得不載入大量的無關數據,這對於緩存是很是不利的。
結構化方法從本質上說與Cache設計的基本原則局部性原理契合,因此結構化的方法更符合計算機的本質,因此它更快;而面向對象化的方法更符合人的思惟方式,更有利於代碼的實現。
經過以上對比分析咱們能夠得出一個直觀結論:在應用時,對於更接近底層的軟件系統,如Linux系統這種對性能要求較高且與計算機核心息息相關的系統,以及那些對代碼和可維護性並無太高要求的(好比一些小型的大做業工程)通常使用結構化的方法和編程模型指導設計就能夠;而對於大型的偏向應用層的軟件,好比像Office系列軟件等須要多人協做,對性能速度要求沒有苛刻要求的,爲了代碼的可維護性與健壯性,使用面向對象的方法更適合。
以上是博主綜合了一些文獻和博客思考得出的結論,歡迎各位指正。