架構(gòu)漫談系列(1) 關注點分離

很想寫相關的內(nèi)容降狠,一直以來這方面的東西很雜对竣,自己各方面都多多少少有些總結(jié),但是沒有系統(tǒng)的成文喊熟,始終覺得是個遺憾柏肪。
這是這個系列的第一篇。
本文說的架構(gòu)芥牌,還并不是說的Tier層的架構(gòu)烦味,這里面不會涉及到分布式、緩存壁拉、網(wǎng)絡結(jié)構(gòu)等等的布局谬俄,而是集中在軟件的內(nèi)部,是代碼層級的弃理,考慮這點架構(gòu)的點溃论,目的是在于幫助我們寫出清晰、易維護的軟件痘昌。

關注點分離(Separation of concerns, SoC)

這個準則應該作為我們開發(fā)和架構(gòu)的指導性的原則钥勋。在該原則下,軟件應該按照其業(yè)務來將軟件本身劃分成不同的部分辆苔,從而進一步降低耦合性算灸,不過,這感覺是句廢話驻啤,大家好像都懂菲驴。

那么首先,關注點是什么呢骑冗?

比如說一組對代碼有影響的業(yè)務邏輯赊瞬,或?qū)δ硞€具體業(yè)務有影響的業(yè)務規(guī)則。它其實可以很通用贼涩,比如針對x86環(huán)境優(yōu)化代碼的細節(jié)巧涧;也可以很具體,比如某個將要初始化的類的名字遥倦,只要它對我們是有用的褒侧,我們就稱它為其中的一個關注點。

舉例來說谊迄,如果某個軟件有個邏輯:是將某些產(chǎn)品高亮顯示出來闷供,以顯示這些產(chǎn)品的獨特性。
那么统诺,把這些產(chǎn)品挑選出來的邏輯歪脏,應該和把這些產(chǎn)品做高亮的邏輯分離開來,這是兩個不同的關注點(只是剛好這兩個關注點是互相關聯(lián)的而已)粮呢。

在架構(gòu)上婿失,如何去應用這條準則呢钞艇?比如說,把業(yè)務邏輯的行為分成基本的實現(xiàn)層(infrastruture)和UI層(理想的情況下豪硅,業(yè)務規(guī)則和業(yè)務邏輯都應該分離到不同的項目里面去哩照,他們也不能互相產(chǎn)生依賴的關系)。這種結(jié)構(gòu)能幫助我們保證業(yè)務邏輯更容易的測試和應用懒浮,而且在底層也沒有互相耦合在一起飘弧。
關注點分離是我們對于軟件分層的一個核心的考慮點。

把握好這個尺度砚著,有助于我們建造模塊化的應用程序次伶。它的價值在于簡化開發(fā)和提高維護性。這個準則做好了稽穆,各獨立部分就能重用冠王,也可以相對獨立的開發(fā)和更新,某個模塊更新了舌镶,其他的模塊不必做額外的修改柱彻。

但是,聽起來還是好抽象的感覺餐胀。

舉例來說哟楷,ASP.NET MVC就是關注點分離的一個體現(xiàn),它將原來的ASP.NET WebForm分離成模型(model)-視圖(view)-控制器(controller)骂澄,從而把業(yè)務邏輯吓蘑、數(shù)據(jù)惕虑、界面分離坟冲,這也是組織代碼結(jié)構(gòu)的一個形式。

MVC的基本結(jié)構(gòu):

  • Model層表示應用程序的數(shù)據(jù)核心溃蔫,通常負責在數(shù)據(jù)庫中存取數(shù)據(jù)健提。

  • View是應用程序的顯示層,通常是依據(jù)模型的數(shù)據(jù)而建立伟叛。

  • Controller是用來控制和處理輸入輸出的私痹,是處理用戶交互的部分,也負責向模型(Model層)發(fā)送數(shù)據(jù)统刮。

    MVC的這個設計各個關注點是分開的紊遵,這樣有助于我們管理和開發(fā)復雜的應用程序,我們可以在某個時間點只集中精力在其中的某一個關注點侥蒙,而不是所有的部分暗膜。舉例來說,前端的開發(fā)人員可以配合設計團隊繞過業(yè)務邏輯鞭衩,專注在視圖和交互設計部分学搜。另外的一端娃善,DBA也可以配合某個團隊專注在數(shù)據(jù)持久化的部分,而中間的業(yè)務邏輯層又可以由其他團隊集中精力來負責瑞佩。這種分層也簡化了分組開發(fā)聚磺,讓測試也更為容易。

除了ASP.NET MVC還有其他的框架也是這樣的關注點分離的思想炬丸,比如Django瘫寝,Structs,Spring等等御雕。

那么分層思想都有哪些方法呢矢沿,總不至于只是用個MVC就結(jié)束了吧?

其實東西還是比較多的酸纲,下面捣鲸,將介紹一些分層的思想。

縱向分離

大家都懂闽坡,即便是最初級的程序員也都接觸過栽惶,可能是你并沒有意識到而已。
我們十好幾年前的三層架構(gòu)疾嗅,界面層(UI Layer)外厂,業(yè)務邏輯層(Business Layer)和數(shù)據(jù)持久化層(Data Access Layer),就是這一種自上而下的縱向的分層手法代承。

橫向分離

大家也懂汁蝶。我們倡導的模塊化的編程,把我們的軟件拆分成模塊或子系統(tǒng)论悴。
從左到右是模塊1掖棉、模塊2、模塊3膀估,這是一種水平方向的切割幔亥。
這跟縱向的分離是兩個不同的方向,橫向分離大多是模塊化的過程察纯。

切面分離

有些內(nèi)容是多個層之間都需要的帕棉,比如日志(logging),在你的系統(tǒng)里面饼记,界面層香伴、邏輯層、數(shù)據(jù)訪問層可能都需要寫日志具则,這種跨到多層同樣邏輯就可以考慮切面分離即纲。
在asp.net mvc中,我們可以使用filter來實現(xiàn), Spring中也有SpringAOP等等乡洼。

依賴方向分離

我們考慮這幾點:

  • 有些類要修改的幾率比其他的類修改的幾率大得多崇裁。
  • 具體的類比抽象類修改的幾率大得多匕坯。
  • 修改被依賴得很多的類可能引起很大的改動。
  • 某些類比其他類被重用的可能性大得多拔稳。

依據(jù)這些考慮點葛峻,我們來決定某個類應該放在哪個層次里面,或者考慮將某一層切割成多層巴比。

關注數(shù)據(jù)分離

在組織數(shù)據(jù)時术奖,應該盡量考慮數(shù)據(jù)本身的固有屬性,如果不是它們的固有屬性轻绞,那么應該分離出來采记。

比如產(chǎn)品的類就不應該關聯(lián)customer類,因為產(chǎn)品不應該跟客戶直接產(chǎn)生數(shù)據(jù)關系政勃,產(chǎn)品的顏色唧龄、型號、描述才是產(chǎn)品該有的固有屬性奸远。

至于客戶既棺,應該是用訂單類來把他們聯(lián)系在一起。

關注行為分離

跟上面講的一樣懒叛,行為也應該是事物或?qū)ο蟮墓逃械谋旧淼男袨橥杳幔黠@偏離原來行為的,應該考慮成另外的關注點兒分離開薛窥。

比如有一個函數(shù)叫做CreateNewCustomer()胖烛,那么CreateNewCustomer的行為就應該限定在創(chuàng)建一個新客戶上面,給新客戶自動發(fā)優(yōu)惠券的動作就不能放到這個函數(shù)里面诅迷。

擴展分離

如果基于某種設計佩番,原先不具有某些行為需要增加,可以考慮通過擴展或插件的形式來完成竟贯,將這些功能放入到插件或擴展中答捕,就是擴展分離逝钥。

比如Firefox屑那、Chrome的去廣告的插件,這些功能增加了系統(tǒng)原本的行為艘款,將這些行為分離到插件里面去持际,就是擴展分離。

委托分離

如果某個行為還無法具體確定哗咆,可以使用委托的方式蜘欲。
比如C#的delegate,當我們還不知道某些具體行為應該如何實現(xiàn)晌柬,或者不應該在此處對該行為進行實現(xiàn)姥份,或者有多個行為可以互相替代郭脂,就可以將函數(shù)的參數(shù)指定為一個delegate。

至于delegate具體怎樣實現(xiàn)澈歉,那是其他部分應該關注的點展鸡。

比如現(xiàn)在需要將Customer的信息持久化,就可以把這個請求委托給DatabaseManager或WebSerivceManager埃难,由他們自行處理數(shù)據(jù)莹弊,然后返回給我結(jié)果。

反轉(zhuǎn)分離

現(xiàn)在有了很多的依賴注入的框架涡尘,像Autofac忍弛,Unit,Castle Windsor等等考抄,這些幫助我們做依賴翻轉(zhuǎn)细疚,從而倒置依賴關系。

要指出是川梅,上面提到了9種分離層次的概念惠昔,每一種概念都可以任意的與其他概念組合在一起,從而產(chǎn)生更多的變化挑势。

在實際的開發(fā)過程中镇防,沒有東西是一成不變的,而層次和架構(gòu)也應該是在開發(fā)的過程里面不斷完善和重構(gòu)潮饱。

初級程序員最煩的是需求或業(yè)務的修改来氧,一些我們覺得奇奇怪怪的修改導致大家不斷的修改代碼,心里很煩香拉,在心里也默默的把產(chǎn)品經(jīng)理被翻過來倒過去罵了千百遍啦扬。

但是,在實際的工作中你會發(fā)現(xiàn)凫碌,軟件開發(fā)就是這樣扑毡,沒有什么是不變的。

如果一定要找出一個不變的點盛险,我想那應該是:

唯一不變的瞄摊,就是變化。

關于不斷的修改與重構(gòu)苦掘,也可以參考《重構(gòu)-改善既有代碼的設計》换帜,記得封面上寫的是:

軟件開發(fā)的不朽經(jīng)典
生動闡述重構(gòu)原理和具體做法
普通程序員進階到編程高手必須修煉的秘笈

呃,再往下面離題越來越遠了鹤啡。
至此惯驼,關注點分離這塊內(nèi)容暫告一段落。

小春微信
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市祟牲,隨后出現(xiàn)的幾起案子隙畜,更是在濱河造成了極大的恐慌,老刑警劉巖说贝,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禾蚕,死亡現(xiàn)場離奇詭異,居然都是意外死亡狂丝,警方通過查閱死者的電腦和手機换淆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來几颜,“玉大人倍试,你說我怎么就攤上這事〉翱蓿” “怎么了县习?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谆趾。 經(jīng)常有香客問我躁愿,道長,這世上最難降的妖魔是什么沪蓬? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任彤钟,我火速辦了婚禮,結(jié)果婚禮上跷叉,老公的妹妹穿的比我還像新娘逸雹。我一直安慰自己,他們只是感情好云挟,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布梆砸。 她就那樣靜靜地躺著,像睡著了一般园欣。 火紅的嫁衣襯著肌膚如雪帖世。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天沸枯,我揣著相機與錄音日矫,去河邊找鬼。 笑死辉饱,一個胖子當著我的面吹牛搬男,可吹牛的內(nèi)容都是我干的拣展。 我是一名探鬼主播彭沼,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼备埃!你這毒婦竟也來了姓惑?” 一聲冷哼從身側(cè)響起褐奴,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎于毙,沒想到半個月后敦冬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡唯沮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年脖旱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片介蛉。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡萌庆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出币旧,到底是詐尸還是另有隱情践险,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布吹菱,位于F島的核電站巍虫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鳍刷。R本人自食惡果不足惜占遥,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望输瓜。 院中可真熱鬧筷频,春花似錦、人聲如沸前痘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芹缔。三九已至坯癣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間最欠,已是汗流浹背示罗。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芝硬,地道東北人蚜点。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像拌阴,于是被迫代替她去往敵國和親绍绘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容