前言
相信很多人都有類似的經(jīng)歷:隨著業(yè)務(wù)越來越多, 系統(tǒng)的越來越復(fù)雜, 我們都會感覺我們的代碼越來越難看, 重復(fù)代碼越來越多, 越來越難以維護(hù)。 恩, 這確實是個問題, 但有沒有可能解決的辦法? 老實說, 確實很難, 但不是完全沒有可能, 或者說有改善的可能。 最近就關(guān)于這方面進(jìn)行了一些學(xué)習(xí)和考慮, 以純理論的方式總結(jié)了一下, 希望能對對這方面有興趣的同學(xué)有所幫助。
很多面向應(yīng)用的系統(tǒng)是以數(shù)據(jù)為中心的, 在這些系統(tǒng)中, 以數(shù)據(jù)庫存儲數(shù)據(jù); 業(yè)務(wù)邏輯代碼則根據(jù)需求圍繞著數(shù)據(jù)庫中存儲的數(shù)據(jù)來組織邏輯;以購買商品的系統(tǒng)為例, 商品數(shù)據(jù), 交易數(shù)據(jù)和用戶數(shù)據(jù)是系統(tǒng)中的核心數(shù)據(jù), 絕大多數(shù)業(yè)務(wù)代碼則是根據(jù)需求來倒騰這些數(shù)據(jù)。這個非常符合那個關(guān)于程序的定義: 程序 = 數(shù)據(jù) + 行為; 在這里, 數(shù)據(jù)是數(shù)據(jù)庫中的數(shù)據(jù), 行為則對應(yīng)業(yè)務(wù)邏輯。
對于所構(gòu)建的系統(tǒng), 我們自然希望可擴展性好, 可維護(hù)性;這是一個非常有挑戰(zhàn)性對的事情, 大型的應(yīng)用尤其如此; 能否真的做就在很大程度取決于邏輯的組織方式。 這篇文章大體介紹以數(shù)據(jù)庫為中心的應(yīng)用中的三個典型的業(yè)務(wù)邏輯組織方式。
邏輯組織方式
事務(wù)腳本方式
這里的事務(wù)與數(shù)據(jù)庫術(shù)語事務(wù)有所區(qū)別, 這里的事務(wù)更多的指一次業(yè)務(wù)交互。
在應(yīng)用系統(tǒng)中, 大多數(shù)業(yè)務(wù)邏輯可以看做一系列子任務(wù)的集合; 比如用戶購買一個商品時, 可以大體分成幾步:
先根據(jù)商品的信息到數(shù)據(jù)庫中查詢是否有可銷售的商品存在;有的話, 添加一個用戶購買商品的購買記錄;然后把商品數(shù)量減少;其他事情, 比如發(fā)郵件通知用戶等。
以事務(wù)腳本方式組織代碼時, 業(yè)務(wù)邏輯組織上沒有層次之分, 在實現(xiàn)一個具體業(yè)務(wù)時, 根據(jù)其業(yè)務(wù)的需要從前到后進(jìn)行一系列的事務(wù)調(diào)用; 就購買商品為例, 先從數(shù)據(jù)庫中查詢商品數(shù)量, 然后判斷是否足夠, 足夠的話添加用戶購買商品的記錄, 然后操作數(shù)據(jù)庫減少商品。這種方式有個明顯的特點, 一個事務(wù)腳本實現(xiàn)以一個用例或者或者一個功能。這個方式優(yōu)點很明顯, 簡單,直觀, 易學(xué)易用,開發(fā)速度快;這些容易理解, 因為這些寫代碼的方式與直觀的思維方式類似, 在實際中, 很多系統(tǒng)都是這樣實現(xiàn)的;尤其那些快速開發(fā)系統(tǒng); 但是抽象度低, 容易導(dǎo)致重復(fù)代碼多,與其他系統(tǒng)的耦合程度高, 維護(hù)麻煩,尤其是對于復(fù)雜的系統(tǒng)來說。 舉個例子來說,購買商品購買這個功能,桌面版提供了之后,手機版的也需要實現(xiàn), 由于手機版與桌面版是兩個不同的用例, 如果用事務(wù)腳本來組織代碼的話, 很自然的就會出現(xiàn)類似的代碼出現(xiàn)在了不同的地方的情況。 一個很明顯的優(yōu)化是封裝成函數(shù), 但是封裝成函數(shù)這個事情的模塊化程度低, 在業(yè)務(wù)復(fù)雜的情況下, 對業(yè)務(wù)邏輯的有效管理和維護(hù)是一個挑戰(zhàn)。
事務(wù)腳本這種方式適用于相對簡單的業(yè)務(wù)邏輯環(huán)境,而且在現(xiàn)實中, 很多業(yè)務(wù)本身就是簡單的, 這種方式可以在開發(fā)高效, 運行高效的前提下工作的很好; 另外對于快速開發(fā)環(huán)境中也非常適用。 但是當(dāng)業(yè)務(wù)邏輯復(fù)雜, 而且上線后維護(hù)期很長或維護(hù)量很大的系統(tǒng)來說,可能不是一種很好的方式。
表模塊方式
在事務(wù)腳本方式當(dāng)中,很容易導(dǎo)致:相同或者類似的代碼重復(fù)出現(xiàn);相關(guān)邏輯分布在多個地方。
對于前一個問題, 可以通過把相同或者相似邏輯封裝成函數(shù)來改進(jìn), 第二個問題通過流程或規(guī)范可以得到控制。 但是, 還是會在業(yè)務(wù)復(fù)雜的情況下對業(yè)務(wù)邏輯的有效管理和維護(hù)是一個挑戰(zhàn) 因為缺乏一種有效的編碼的機制來控制這樣的問題。
表模塊組織方可以從機制上提供一個相對好的解決辦法, 其大概思路是,把與一個或者多個數(shù)據(jù)庫表(或者視圖)有關(guān)的邏輯組織成一個類, 把對與這個表有關(guān)的邏輯組織成這個類的方法。以上面那個購買商品為例, 查詢商品是否足夠可能是一個單獨的方法, 修改商品數(shù)量是一個單獨的方法;購買商品是一個方法,所完成的事情就是把前面兩個方法組織起來。 一旦有了這個邏輯, 只要是需要用到購買商品邏輯的地方, 直接調(diào)用這個購買商品的方法就可以了; 除了這個購買商品之外, 其他與商品有關(guān)邏輯都組織在這個類里面,避免了與商品有關(guān)的邏輯分布到多個地方。
除了提供一個代碼組織的方式外,這種組織方式還有一些其他的好處:不需要數(shù)據(jù)庫表就直接可以測試,也便于打樁測試; 與很多數(shù)語言提供的數(shù)據(jù)庫操作API配合使用方便, 很多數(shù)據(jù)庫操作API返回的結(jié)果都市記錄集的方式, 尤其以微軟提供的相關(guān)API為典型代表, .NET提供的Dataset更是功能強大。實際上, 微軟提供的開發(fā)平臺倡導(dǎo)的就是以表模塊方式組織邏輯, 并提供了各種便利的開發(fā)工具和API; 在管理代碼的有效性和復(fù)雜度上有比較好的平衡,他比前面的事務(wù)腳本方式相對繁瑣點, 比后面好提到的領(lǐng)域模型方式簡單很多。
領(lǐng)域模型
領(lǐng)域模型方式組織代碼就是OO的編程思想, 把領(lǐng)域邏輯對象化, 從而達(dá)到在復(fù)雜的業(yè)務(wù)邏輯是有好的可擴展性和可維護(hù)性。表模塊組織方式在管理代碼的有效性和復(fù)雜度上有比較好的平衡, 但是在其提供的抽象機制畢竟有限; 在管理復(fù)雜的業(yè)務(wù)邏輯方面有些不給力。比如, 對于不同類型的商品, 其購買邏輯可能不一樣;這時候, 面向?qū)幋a的威力會就能比較好的發(fā)揮了, 商品這個例子中, 購買時的行為可能不一樣, 利用多態(tài)機制, 對調(diào)用者來說可能是透明的。
領(lǐng)域模型這種方式與表模型的方式的區(qū)別在于OO的力度不一樣; 表模型以表為單位來組織, 領(lǐng)域模型可能則以表里面的記錄為單位來組織的, 因此代碼中, 一個表只有一個類實例, 而領(lǐng)域模型則會針對一條記錄有個對象。
模型這種方式的優(yōu)點是便于有效的管理復(fù)雜性和可擴展性, 對于復(fù)雜的業(yè)務(wù)邏輯以及那種維護(hù)周期很長的系統(tǒng)來說比較適用; 但其缺點也很明: OO建模復(fù)雜,開發(fā)周期相對會長些;學(xué)習(xí)成本高, 尤其對于新團隊來說; 同樣, 如果代碼組織不好, 也會出現(xiàn)其他方式中出現(xiàn)的類似問題, 如代碼重復(fù)等。
小結(jié)
三種不同的邏輯組織方式各有特點, 適用于不同的場合, 可以根據(jù)實際情況選擇, 一般來說, 簡單應(yīng)用, 要求快速開發(fā)快, 維護(hù)周期短的可以考慮事務(wù)腳本方式; 業(yè)務(wù)邏輯復(fù)雜, 維護(hù)周期長時, 在開發(fā)人員技能滿足的條件下可以考慮領(lǐng)域模型; 在這個兩個中間的情況可以考慮表模塊方式, 尤其是在微軟的平臺上。 在實際中,由于實際業(yè)務(wù)的復(fù)雜性, 很多時候以一種單一的方式組織還不夠, 可能幾個方式綜合起來運用。 比如, 把核心業(yè)務(wù)按領(lǐng)域?qū)ο蟮姆绞浇M織, 之上再以事務(wù)腳本來組織多變的應(yīng)用業(yè)務(wù)。
it知識庫:以數(shù)據(jù)庫為中心的系統(tǒng)中的業(yè)務(wù)邏輯組織方式,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。