我們知道一個軟件從無到有需要經過如下幾個階段分析設計編程調試部署和運行
編程階段我們通常使用Java/NET這樣面向對象語言工具可以帶來很多設計上的好處但是也存在一個奇怪的現象很多程序員雖然在使用OO語言但是卻在code非OO的代碼最終導致系統性能降低或失敗這個現象在Java語言尤其顯得突出難怪有些人就把問題歸結於Java語言本身睡不著覺怪床歪又為了面子問題說自己轉向NET實際上是在 回避自己的問題和弱點
那麼這些人的問題和弱點體現在什麼地方呢?從上面軟件生產過程來看每個階段都對前面有所依賴 在編程階段出問題追根溯源問題無疑出在分析和設計階段分析設計作為一個軟件產生的龍頭有著映射實際需求世界 到計算機世界這樣一個拷貝任務如何做到拷貝不走樣是衡量映射方法好壞與否的主要判斷標准
目前將需求從客觀現實世界映射到計算機軟件世界主要有兩種方式傳統數據庫分析設計和面向對象建模( objectoriented class model) 當前軟件主要潮流無疑是面向對象占據主流雖然它可能不是唯一最好最簡單的解決方案但是它是最普通也是最恰當的
也就是說在分析設計階段采取圍繞什麼為核心(是對象還是數據表為核心)的分析方法決定了後面編碼階段的編程特點如果以數據表為核心進行分析設計 也就是根據需求首先得到數據表名和字段然後培訓程序員學會SQL語句如何操作這些數據表那麼程序員為實現數據表的前後順序操作 必然會將代碼寫成過程式的風格
相反如果分析設計首先根據需求得出對象模型(class Model)那麼程序員使用對象語言再加上框架輔助就很順理成章走上OO編程風格 至於OO代碼相比傳統過程編碼的好處不是本文重點可參考J道()相關討論擴展性和維護性好開發越深入開發速度越快無疑是OO系統主要優點
本文重點主要是比較OO建模和數據表建模兩者特點這兩者我們已經發現屬於兩個不同方向也就是說屬於兩個完全不同的領域在J道其他文章裡我們 其實已經把這兩個領域上升為不同的學科數據表建模屬於數學范疇思維而OO建模屬於哲學思維
下面我們看看面向對象的Class Model和Database Model是如何來表達客觀世界的也就是他們在表達需求上有些什麼不同?
面向對象模型(Class Model)
類代表一個對象類型類在代碼運行階段將被創建為一個個對象實例 每個類由兩個部分組成屬性和行為屬性通常是一些數據狀態值也就是說類將數據封裝隱藏在自己內部了 訪問這些數據屬性必須通過類公開的方法或者接口
別小看這樣一個小小包裝卻決定了以後代碼的維護性和擴展性 打個比喻日常生活中我們經常用各種盒子和袋子包裝一些東西這樣做就是為了方便這些東西的攜帶或儲藏小到生活 大到客觀世界每個地方都是包裝分類的影子無論大小公司都是一個封裝行政部分單位劃分倉庫物流更需要包裝 我們從來不會因為嫌麻煩而不願意引入一個似乎多余的盒子或袋子那麼有什麼理由不在我們賴之生存的軟件中(靠編軟件吃飯) 引入封裝概念呢?
這裡可以再深入想像一下不願意用盒子和袋子的攜帶東西大部分是一些急脾氣的毛頭小伙子而偏偏這些小伙子又從事 軟件工作看來軟件的非對象化是注定的只是一個玩笑
類的方法行為也有多種類型如公開 私有等我們可以設計一些方法為公開接口而將另外一些行為隱藏起來 這樣一個看似簡單靈活的選擇卻能夠應付我們日後頻繁的修改軟件不修改就不叫軟件軟件修改了就崩潰是業務軟件 專業的軟件是抗修改的而且能夠極其方便快速地被修改這些都依靠接口公開和隱藏這樣一個簡單魔術
類的關系
我們不能只用一個一個單獨的類來表達客觀世界因為客觀世界存在千絲萬縷的各種關系在計算機領域無疑我們使用 類的關系來表達映射這些關系這裡我們只探討類在建模方法上的關系而不是UML中類的通用關系 類在建模上主要有如下幾個關系
類與類關系經常是這樣一個類包含一個類(構造性structural)或者借助另外一個類達到某個功能(功能性) 在對需求建模分析中構造性的這種關系也稱為關聯(Association)是我們關注重點當然這種關系很顯然表達的是一種 靜態的結構比如電腦包含屏幕他們之間的關系就是一種關聯
聚合(Aggregation)是一種表格式樣的關聯表示一個類包含多項子類這種關系是一種整體與部分的關系 一個汽車有四個輪子四個輪子是汽車的部分
組成(Composition)是一種更強烈的聚合關系一個對象實際是由其子對象組成子對象也唯一屬於父對象
繼承也是類建模中經常用到的關系繼承可以將一些數據屬性抽象到父類中避免重復如入庫單和出庫單有 很多屬性是差不多的唯一不動的就是入庫和出庫的行為那麼我們可以抽象一個庫單為父類使用繼承關系分別 表達入庫單和出庫單
在Evans DDD中提到通過訪問聚合根來遍歷導航關聯對象這樣做的好處很明顯保證了對象的從屬性非常符合 我們日常生活邏輯比如你要得到盒子裡面的東西必須首先得到盒子然後經過一些准備如打開盒子才能得到 盒子裡面的東西假設一下如果沒有這樣封裝導航關系盒子和東西都是可以透明並行得到你想得到東西就能夠 直接獲得而不必經過打開盒子這一關這樣的訪問方式首先怪誕其次是不安全如果盒子和東西放在數據表中就會發生 這種情況
數據庫模型(Database Model 傳統ER模型 )
好了下面我們談論關系數據表模型以前我們樸素的分析設計都是根據需求直接建立數據表的方式來進行的為什麼稱為樸素 是因為我們好像只有數據結構 算法方面的知識也認為只有這樣做才叫做軟件 那麼既然這條路能夠走出來我們看看這個領域是如何映射客觀世界的
數據表由於技術提供龐大數據存儲和可靠的數據訪問正在不斷從技術領域走向社會領域很多不懂計算機的人 也知道需要建立數據庫來管理一些事務但是不代表我們就必須圍繞數據庫的分析設計
數據表是類似前面的類也是一種表達客觀世界的基本單元表有多列字段表的字段是保存數據的每個字段有數據類型 注意這裡沒有數據的封裝和公開表的字段是赤裸的只要有數據庫訪問權限任何人都可以訪問沒有結構層次關系 都是扁平並列的如果你想在數據表字段之間試圖看出客觀世界中的層次和封裝那就錯了在拷貝不走樣這個條件下 這個映射方法至少把這個信息拷貝丟了
數據表也有一些行為這些行為是基於實體的一些規則
約束(Constraints) 能夠保證不同表字段之間的關系完整安全性保證數據庫的數據安全
觸發器(Triggers)提供了實體在修改 新增和刪除之前或之後的一些附加行為
存儲過程(Database stored procedures)提供數據專有的腳本性語言存儲過程象一個數學公式雖然具有抽象簡潔美學但是這種簡潔是悶葫蘆美學不是大眾美學只有公式存儲 過程發明者自己了解精通別人無法插手軟件不是科學不是比誰智商高科研水平高軟件是人機工程更講究集體講究別人是否方便與你協同擴展軟件
關系數據表的遍歷訪問是通過列字段遍歷或表join等方式實現SQL語句是這樣標准語言 只要會寫SQL語句就能訪問那些失去層次失去客觀世界特征的蒼白的數據這樣的系統能夠多少真實 反映客觀需求是有問號的?SQL語句是否方便修改是否經得起頻繁修改而不出錯都是有疑問的地方是否 SQL語句越復雜修改越快或者另外一個程序員能夠很快修改不是自己寫的SQL語句這些都是問題所在
數據表關系
數據表的關系主要是通過外健或專門關聯表來表達的這種關系雖然可以反映:或:N這樣關系但是無法 表達關系的性質是緊密組成關系式的關聯還是無關緊要的普通關系正因為如此使用數據表分析設計時 我們會有蜘蛛網的關系表這些關系由於在後期無法分辨性質無法進行整理增加了系統復雜性
更重要的是分析就是對一個可能陌生領域進行探尋如果使用數據表的分析設計方法那麼我們實際就是 在陌生領域中尋找數據表這樣一個形式那麼有可能產生誤判斷將一個實則是表達關系的東東誤認為是一個實體表 因為關系表必然帶來關系這樣就必然產生蜘蛛網式的數據表模型將簡單問題復雜化
總結
要談方法這個世界其實只存在兩種一是將復雜問題簡單化的方法一個是將簡單問題復雜化的方法 你使用什麼樣的方法你就有什麼樣的世界觀就是什麼樣的人但是對於軟件這個領域你只能選擇前者
因為方法的不同軟件路線也就存在下面幾個路線完全面向對象類建模路線(J道網站和筆者一直致力於這種路線的推介) 一種是對象和關系數據庫混合型還有一種就是過去的完全關系數據庫類型軟件(如Foxpro/VB/Delphi等)
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27332.html