時(shí)間過得有點(diǎn)快庞萍,距離《淺談代碼層級與接口設(shè)計(jì)》已經(jīng)有一年多了惹苗。在去年的基礎(chǔ)上只是更加明確了代碼整體的架構(gòu)設(shè)計(jì)套耕,目的快速響應(yīng)了當(dāng)前公司業(yè)務(wù)的需求构灸。
代碼整體架構(gòu)
架構(gòu)圖比較簡單件已,其實(shí)就是在Yii的架構(gòu)上加了點(diǎn)公司的公共業(yè)務(wù)需求而已笋额,如果業(yè)務(wù)簡單common module 和 core可以合成在一起 。
架構(gòu)優(yōu)點(diǎn)
1篷扩、能靈活挑選模塊組合+core進(jìn)行發(fā)布
2兄猩、明確模塊的職責(zé),模塊間進(jìn)行解耦,單獨(dú)模塊更新不影響其他模塊
3厦滤、在編碼過程中鼓勵(lì)團(tuán)隊(duì)中的成員能貢獻(xiàn)更多的common代碼和core代碼援岩,減少重復(fù)編碼
架構(gòu)缺點(diǎn)
1、升級core和common時(shí)掏导,會(huì)影響所有應(yīng)用
2享怀、當(dāng)模塊間的相互調(diào)用時(shí)(業(yè)務(wù)間的交集),無法將應(yīng)用真正的隔離
Logic層的作用
比Yii中多了logic趟咆,logic最終是給controller調(diào)用的添瓷。為什么要多此一舉?
1值纱、按照Yii的機(jī)制鳞贷,controller是可以相互調(diào)用的,但很麻煩虐唠。(我承認(rèn)懶得去看更多細(xì)致的文檔)
Yii::$app->runAction('new_controller/new_action', $params);
雖然這句看上去也挺簡單的搀愧,但是事實(shí)上相當(dāng)重新跑了一次Yii中調(diào)用控制器的流程。在一些業(yè)務(wù)中疆偿,并不需要如此繁瑣咱筛。再者在調(diào)用了其他控制器的方法后,也無法獲取相關(guān)更多細(xì)節(jié)的信息杆故。
2迅箩、當(dāng)控制器中加上了權(quán)限控制的時(shí)候,相互調(diào)用更加直接導(dǎo)致了業(yè)務(wù)邏輯的復(fù)雜处铛。舉例用戶A有權(quán)限(controller/action1)饲趋,沒有(controller/action2)的權(quán)限。當(dāng)業(yè)務(wù)需求發(fā)生改變撤蟆,action1需要調(diào)用到action2時(shí)奕塑。你愿意重復(fù)編碼,還是和產(chǎn)品撕逼家肯?
3龄砰、當(dāng)面臨復(fù)雜、重復(fù)息楔、多變的業(yè)務(wù)體系時(shí)寝贡,業(yè)務(wù)代碼都寫在controller中扒披,會(huì)讓controller顯得特別笨重值依。難以擴(kuò)展和進(jìn)行調(diào)優(yōu)。
所以為了實(shí)現(xiàn)模塊間的業(yè)務(wù)可以相互快速調(diào)用碟案,將Controller架空愿险,多一層Logic。需要時(shí)直接生成另一個(gè)logic的實(shí)例進(jìn)行調(diào)用即可。下面的抽象類Logic的代碼辆亏。
abstract class Logic{
? ? function setCode();
? ? function getCode();
? ? function setData();
? ? function getData();
? ? function setMessage();
? ? function getMessage();
}
Logic層需要給Controller層調(diào)用的方法风秤,必須返回統(tǒng)一的狀態(tài),一般為boolean扮叨,同時(shí)需要調(diào)用setCode方法缤弦,進(jìn)行設(shè)置異常的狀態(tài)。在其他Logic去調(diào)用時(shí)彻磁,根據(jù)getCode就能知道調(diào)用的方法碍沐,是否正常。調(diào)用getMessage就能知道發(fā)生的細(xì)節(jié)衷蜓。
在簡單的業(yè)務(wù)中累提,是沒有必要多這一層logic的,在設(shè)計(jì)上Yii的代碼架構(gòu)已經(jīng)能滿足磁浇,畢竟這是許多人的心血結(jié)晶斋陪。多了一層logic,反而讓controller擔(dān)任的是路由的責(zé)任置吓,但本質(zhì)上是為了讓代碼更加靈活无虚,更多是為了統(tǒng)一的概念而設(shè)定。
1交洗、于個(gè)人而言骑科,令我編碼更加舒適、快捷构拳。畢竟不喜歡controller之間的調(diào)用限制和復(fù)雜咆爽。
2、代碼重構(gòu)(重寫)變得更加方便置森。因?yàn)閏ontroller只是一個(gè)路由斗埂,可以任意調(diào)用logic層中方法。對于路由凫海,是不用關(guān)心實(shí)現(xiàn)的細(xì)節(jié)呛凶。當(dāng)代碼重構(gòu)上線遇到問題時(shí),能簡單改幾行代碼就能恢復(fù)現(xiàn)場行贪。如果重構(gòu)通過漾稀,就能大把大把的清理代碼〗ㄌ保看一份清晰簡單的代碼崭捍,會(huì)讓人很爽。
3啰脚、再者業(yè)務(wù)間的相互靈活調(diào)度殷蛇,能大量減少重復(fù)編碼。雖然會(huì)導(dǎo)致業(yè)務(wù)之間的耦合,但是邏輯性的高度統(tǒng)一粒梦,能讓你的代碼邏輯更加嚴(yán)謹(jǐn)亮航,出現(xiàn)bug時(shí),能快速定位匀们。而事實(shí)上當(dāng)業(yè)務(wù)穩(wěn)定明朗時(shí)缴淋,bug很少會(huì)出現(xiàn)。
Model層的改變
我們查詢SQL時(shí)一般都是用"id,name as title"進(jìn)行字段的篩選泄朴。借鑒于SQL的模式宴猾。我寫了一個(gè)字段解析器(FieldParser),大體如下圖:
在字段解析器中叼旋,對于額外字段仇哆,同時(shí)實(shí)現(xiàn)了SQL一樣的"AS"重命名模式。
所以對于字段解析器優(yōu)缺點(diǎn)很明顯
優(yōu)點(diǎn):
1夫植、字段擴(kuò)展靈活讹剔,能快速響應(yīng)業(yè)務(wù)需求。在開發(fā)中详民,作為后端我一直要求各端字段完全統(tǒng)一延欠,但是事實(shí)上對于產(chǎn)品的需求,根本不可能沈跨。web端能顯示信息更多也更豐富由捎,而App端會(huì)要求更簡潔。有時(shí)候饿凛,需要的字段狞玛,需要各端從其他幾個(gè)接口的邏輯實(shí)現(xiàn)。作為后端付出多一點(diǎn)涧窒,能極大的提高開發(fā)整體的效率心肪。
2、有了字段解析器后纠吴,在業(yè)務(wù)層的查詢很簡單硬鞍,將復(fù)雜的組合性字段交還給了Model層進(jìn)行實(shí)現(xiàn)。從而在代碼層面上實(shí)現(xiàn)了職責(zé)的分離戴已。這樣業(yè)務(wù)(Logic)層只是專注關(guān)心于業(yè)務(wù)的邏輯固该,Model層也更加專注于自身,提供業(yè)務(wù)所需要的數(shù)據(jù)糖儡。在一定程度上伐坏,也降低了代碼的復(fù)雜度。
3休玩、極大的提高了開發(fā)速度著淆。面對各種查詢需求,無非就是從需要的關(guān)系表里面去查找數(shù)據(jù)拴疤,然后返回永部。有了字段解析器的功能,每多一個(gè)額外字段呐矾,其實(shí)就相當(dāng)于往表里面動(dòng)態(tài)添加字段一樣簡單苔埋。
缺點(diǎn):
1、查詢速度會(huì)慢Q逊浮W殚稀!由于將一個(gè)業(yè)務(wù)的所有查詢都統(tǒng)一到一個(gè)模型中罚随,其中的聯(lián)表玉工,不可避免。而在列表查詢時(shí)淘菩,由于是單個(gè)方法查詢的實(shí)現(xiàn)的額外字段遵班。當(dāng)額外字段中查詢越多,速度越慢潮改。目前僅用于內(nèi)部使用的系統(tǒng)狭郑,并發(fā)度不高,而且內(nèi)部要求是首先邏輯正確汇在,響應(yīng)慢點(diǎn)可以接受翰萨。
小結(jié)
寫了這么多,總結(jié)一下:業(yè)務(wù)(代碼)分層糕殉!將不同的問題歸類亩鬼,然后將其統(tǒng)一處理,減少重復(fù)阿蝶,使業(yè)務(wù)更加清晰明了辛孵,進(jìn)而提高效率。
我之前寫的《架構(gòu)演變的探索》也是源自于這種思想赡磅,但形式的表現(xiàn)有太多魄缚。