從混亂到混亂,業(yè)務(wù)邏輯搬家記
1.業(yè)務(wù)邏輯同學(xué)
業(yè)務(wù)邏輯同學(xué)經(jīng)常被大家戲稱是業(yè)務(wù)中最不講邏輯的東西, 這句話道出了他的本質(zhì)。
這家伙不僅善變,而且特別喜歡和程序員作對(duì),尤其喜歡制造混亂,讓程序員懼怕他。
他最早棲息在像ASP 和 JSP這樣的頁面當(dāng)中,整天和那些負(fù)責(zé)界面展示的HTML,CSS們廝混,在這里除了展示邏輯之外,你還能看訪問數(shù)據(jù)庫的代碼, 他們堅(jiān)定不移地以制造混亂為己任,齊心協(xié)力把頁面搞得一團(tuán)糟。
當(dāng)程序員想去修改的時(shí)候就發(fā)現(xiàn), 這種代碼簡直就是“意大利面條”, 極難閱讀,極難維護(hù)。 更不用提什么代碼的復(fù)用了。
每當(dāng)程序員抱怨的時(shí)候, 業(yè)務(wù)邏輯說: “怪我咯? 還不是你們自己惹的禍!”
2 ***次搬家
時(shí)間久了,大家都受不了, 只好想了新的辦法, 分層! 強(qiáng)迫業(yè)務(wù)邏輯和展示邏輯分家 !
業(yè)務(wù)邏輯被迫搬了家,再也無法和展示層的HTML,CSS一起喝酒吃肉, 每次想聊個(gè)天還必須得通過特定接口, 把數(shù)據(jù)發(fā)給展示層才行。 比如業(yè)務(wù)邏輯層會(huì)發(fā)個(gè)View Object 給展示層,把自己的孤獨(dú)和思念捎帶過去。 再后來展示層完全從服務(wù)器端移到了瀏覽器端,業(yè)務(wù)邏輯想打個(gè)招呼就得跨越網(wǎng)絡(luò)的千山萬水了。
業(yè)務(wù)邏輯退而求其次, 和Java bean 打得火熱,不過很快就發(fā)現(xiàn)和Java bean 實(shí)在沒什么好聊的,太單純,沒有一點(diǎn)深度,除了getter/setter方法之外,啥都沒有。
有人把此時(shí)的業(yè)務(wù)邏輯稱為Service , 有人稱為Manager ,業(yè)務(wù)邏輯更喜歡這個(gè)名字,因?yàn)轱@得更加威嚴(yán),更像系統(tǒng)的老大。
無論叫什么,其實(shí)做的事情都是一樣的: 根據(jù)隔壁房間或千里之外的展示層傳過來的指示, 從數(shù)據(jù)庫讀取數(shù)據(jù),形成java bean(有時(shí)候連java bean 都不需要) , 進(jìn)行業(yè)務(wù)邏輯運(yùn)算,再給展示層發(fā)送結(jié)果。
程序員把這種Java bean 形象地稱為貧血模型, 因?yàn)樗稽c(diǎn)業(yè)務(wù)邏輯都沒有, 業(yè)務(wù)邏輯在Service中放著呢。
這種簡單的開發(fā)方式受到了廣大程序員的歡迎,它概念簡單,門檻極低,初學(xué)者很快就能掌握。
建個(gè)數(shù)據(jù)庫表, 創(chuàng)建一個(gè)對(duì)應(yīng)的java 類,使用Hibernate, MyBatis把它映射到數(shù)據(jù)庫表和字段上, 接下來就可以在Service 中隨心所欲地操作這些Java bean 實(shí)現(xiàn)業(yè)務(wù)邏輯了,完全不用什么“高深的”面向?qū)ο蟮姆治龊驮O(shè)計(jì) 。
一個(gè)項(xiàng)目劃分成多個(gè)模塊, 大家都按照這種模式開發(fā), 再加上一些輔助的開發(fā)工具,能夠自動(dòng)化從數(shù)據(jù)庫表生成各種類, 實(shí)在是直接而酸爽。
一大批使用貧血模型的應(yīng)用程序如雨后春筍般地出現(xiàn),慢慢地變成了趨勢,好像用Java做面向?qū)ο蟮腤eb開發(fā)就是這個(gè)樣子。 尤其是后來維護(hù)項(xiàng)目的程序員, 更是覺得天經(jīng)地義。
(碼農(nóng)翻身老劉注: 按照Martin Flower在《企業(yè)應(yīng)用架構(gòu)模式》中的定義,這種方式叫做事務(wù)腳本,其本質(zhì)是用面向?qū)ο蟮恼Z言寫面向過程的程序)
這種模式對(duì)于簡單的增刪改查一點(diǎn)問題都沒有,甚至還有優(yōu)勢 !
業(yè)務(wù)邏輯這家伙經(jīng)常在誘惑程序員,來啊來啊,再多給我的Service/Manager加點(diǎn)邏輯。
隨著系統(tǒng)越來越復(fù)雜, 這家伙得逞了, 大量的業(yè)務(wù)規(guī)則被添加到Service 當(dāng)中,Service越來越臃腫, 開始變成巨無霸的類, 各種狀態(tài)、判斷、if else 交織在一起, 喜歡混亂的業(yè)務(wù)邏輯同學(xué)又激動(dòng)起來, 又回到了“面條代碼”的“美好”時(shí)代。
3 第二次搬家
程序員們決定再次讓業(yè)務(wù)邏輯搬家, 搬到一個(gè)清靜的地方去。
有一天,有個(gè)叫做Eric Evans的大神提出了一個(gè)新方案: 把Service 層和領(lǐng)域?qū)臃珠_。
(碼農(nóng)翻身老劉注: 在Eric Evans的領(lǐng)域驅(qū)動(dòng)開發(fā)中,最下面是基礎(chǔ)設(shè)施層,而不僅僅是數(shù)據(jù)訪問, 我這里為了和之前的圖保持一致,只把數(shù)據(jù)訪問列了出來)
業(yè)務(wù)邏輯同學(xué)很不爽地發(fā)現(xiàn),自己不但和展示層徹底說byebye ,還被拆分到一個(gè)個(gè)的領(lǐng)域?qū)ο螽?dāng)中去了,這些對(duì)象不僅僅是具有g(shù)etter/setter的java bean , 而且擁有相關(guān)的業(yè)務(wù)邏輯、業(yè)務(wù)狀態(tài)、業(yè)務(wù)規(guī)則。 現(xiàn)在各個(gè)領(lǐng)域?qū)ο笠肓奶齑蹬?,也非得調(diào)用相應(yīng)的業(yè)務(wù)接口才可以。
原來的Service 層也成功減肥,變得非常輕薄,不再包含業(yè)務(wù)規(guī)則和知識(shí),只是為下層的領(lǐng)域?qū)ο髤f(xié)調(diào)任務(wù),分配工作,指揮著他們完成業(yè)務(wù)任務(wù),解決問題。
程序員們被美好的前景激勵(lì)著, 努力地幫著業(yè)務(wù)邏輯再次搬家。 喜歡混亂的業(yè)務(wù)邏輯同學(xué)這次要絕望了, 以后的系統(tǒng)都這么搞,自己還有什么活路。
可是沒想到這一次搬家難度很高, 尤其是從需求中分析合適的領(lǐng)域?qū)ο?,?shí)在不是一件輕松的事情,習(xí)慣了之前那種用數(shù)據(jù)庫表驅(qū)動(dòng)的開發(fā)方式,想轉(zhuǎn)到領(lǐng)域模型驅(qū)動(dòng)的開發(fā)方式, 讓大家很不適應(yīng)。
于是業(yè)務(wù)邏輯同學(xué)趁勢鼓噪,算了吧,這種方法太難了,你有豐富的開發(fā)經(jīng)驗(yàn)嗎?、你有優(yōu)秀的面向?qū)ο笤O(shè)計(jì)能力嗎?你能把業(yè)務(wù)領(lǐng)域?qū)<依M(jìn)來一起討論設(shè)計(jì)嗎? 不行吧? 還是退回去吧,貧血模型多好,又簡單又熟悉。
這廝還真得逞了,鑒于大部分遺留系統(tǒng)都是貧血模型,大家沒有勇氣更沒有時(shí)間去重構(gòu),只好將就著繼續(xù)往混亂的Service舔磚加瓦,希望能熬到系統(tǒng)重寫的那一天。
業(yè)務(wù)邏輯再次搬回到熟悉的地方,再次開始幸福的生活。
【本文為51CTO專欄作者“劉欣”的原創(chuàng)稿件,轉(zhuǎn)載請通過作者微信公眾號(hào)coderising獲取授權(quán)】