如何做好項(xiàng)目結(jié)構(gòu)規(guī)劃

在另一篇文章中說明了“規(guī)劃項(xiàng)目結(jié)構(gòu)”的重要性抽减,在這篇文章中則要來談?wù)勅绾螌?shí)踐橄碾。

決定結(jié)構(gòu)的依據(jù)

在決定項(xiàng)目結(jié)構(gòu)的分類方式時(shí),不外乎是依 Feature 或是依 Layer 來設(shè)置所謂的 Package 或是 Namespace史汗,一般都會(huì)與實(shí)體的目錄名稱做搭配停撞,形成一個(gè)同步的樹狀結(jié)構(gòu)悼瓮。這二種分類的差別,其實(shí)說白了就是倒底是要依照 SA 還是 SD 的文件內(nèi)容來做分類的基準(zhǔn)埋市。

在進(jìn)行系統(tǒng)設(shè)計(jì)時(shí)命贴,理所當(dāng)然地會(huì)以 SA 文件為基礎(chǔ)來開展工作胸蛛,因?yàn)橄到y(tǒng)分析本來就是做為設(shè)計(jì)之前的信息分析與統(tǒng)整的工作。在這樣的前提之下省咨,所設(shè)計(jì)出來的 Class 就注定會(huì)帶有 SA 文件分類的屬性玷室。然而在 OOP 的原則之下,單一個(gè) Class 不太可能負(fù)擔(dān)所有的工作箩兽,所以設(shè)計(jì)出一組 Class 用來實(shí)現(xiàn) SA 文件所描述的功能是很常見的手法章喉。當(dāng)設(shè)計(jì)工作再演化下去,為了有系統(tǒng)組織設(shè)計(jì)的結(jié)果落包,就會(huì)在設(shè)計(jì)中導(dǎo)入 Design Pattern 或是 Framework咐蝇,來試圖形成多個(gè) Class 的群組巷查。這時(shí) Class 就具備了第二種的分類屬性岛请,因?yàn)樵诿恳唤M的設(shè)計(jì)中 Class 都會(huì)有特定的角色或定位來協(xié)助完成對(duì)應(yīng)的工作。

在經(jīng)過以上的說明后可以看到盅称,大部份 Class 都最少有二種的分類方式僚匆。然而,項(xiàng)目或者是目錄的結(jié)構(gòu)只能以一種視點(diǎn)來表達(dá)逞盆,抉擇就因此而產(chǎn)生云芦。依 SA 文件會(huì)以功能面或是處理的數(shù)據(jù)類型為主贸桶,所以分類上就會(huì)形成類似 Customer皇筛、Product、Order 這樣的結(jié)構(gòu)旗笔。依 SD 文件則會(huì)是以 Class 的角色定位為主,如果 SD 文件中規(guī)定要使用 MVC 的 Design Pattern拳魁,則分類就會(huì)出現(xiàn) Model撮弧、View贿衍、Controller 這樣的結(jié)構(gòu)。

決定結(jié)構(gòu)的首要考量

至于依 Feature 或是 Layer 何者熟優(yōu)熟劣岂却,就過去的經(jīng)驗(yàn)法則裙椭,我本身是比較傾向依 Feature 來分類揉燃。不過筋栋,在這之前其實(shí)要先考慮的是程序?qū)嶓w切割的問題弊攘。怎么說?在系統(tǒng)成長迈倍、擴(kuò)張到極致時(shí)捣域,勢(shì)必得導(dǎo)入分散式的架構(gòu)設(shè)計(jì)焕梅,也就是程序是散落在不同的運(yùn)行環(huán)境之中,并且大多都以網(wǎng)絡(luò)為交換信息的媒介斜棚。

在進(jìn)入到分散式架構(gòu)的設(shè)計(jì)之前沒有先預(yù)留好必要的彈性,進(jìn)入之后又沒有足夠的決心打掉重來蚤霞。接著下來在設(shè)計(jì)上的調(diào)整工作争便,對(duì)負(fù)責(zé)的人來說將會(huì)是一個(gè)相當(dāng)耗費(fèi)心力的過程断医。

在這個(gè)過程中數(shù)據(jù)傳遞的問題會(huì)是最大的障壁鉴嗤,很多理所當(dāng)然的 Class 之間交換數(shù)據(jù)之手法,在移至遠(yuǎn)端后就晉級(jí)到完全不同的次元兔簇。在不是分散式架構(gòu)時(shí)垄琐,所有的 Class 共用內(nèi)存经柴,所以數(shù)據(jù)在 Class 間可以直接共享坯认、存取。在跨設(shè)備交換時(shí)陋气,則需要增加額外的程序來達(dá)成引润,不論是對(duì)數(shù)據(jù)進(jìn)行包裝或轉(zhuǎn)換椰拒,不是單純地把 Class 分別放置在不同的實(shí)體中就可以順利的運(yùn)作。

再來褒脯,需要進(jìn)行的是:調(diào)整不適用分散式架構(gòu)的設(shè)計(jì)內(nèi)容番川。數(shù)據(jù)傳遞的過程變復(fù)雜了,原本的設(shè)計(jì)就有可能不敷使用践啄,增加接腳屿讽、改變調(diào)用方式都是必經(jīng)的過程吠裆∈愿恚可見范圍的改變也直接沖擊著原有的設(shè)計(jì)思維,不像是所有的 Class 都被裝在同一個(gè)容器中履澳,在跨設(shè)備進(jìn)行遠(yuǎn)端調(diào)用時(shí)不可能“看得見”遠(yuǎn)端所有的 Class距贷,只會(huì)有被設(shè)計(jì)要用來揭露的介面吻谋,所以碰觸到這些部份的設(shè)計(jì)都需要重新來過滨溉。有時(shí)候一些違反設(shè)計(jì)精神长赞、便宜行事的做法得哆,譬如讓不相干的二個(gè) Class 逕行互相調(diào)用,在這種環(huán)境下就會(huì)被嚴(yán)格地指正出來栋操。相關(guān)的問題一般都是潛藏在設(shè)計(jì)的各個(gè)角落矾芙,等到系統(tǒng)運(yùn)作出了問題才會(huì)發(fā)現(xiàn)這樣的計(jì)設(shè)方式行不通近上。當(dāng)系統(tǒng)出錯(cuò)的情況經(jīng)過幾次之后,對(duì)負(fù)責(zé)設(shè)計(jì)的人而言耗掉了心力不說感帅,工作的品質(zhì)也會(huì)面臨嚴(yán)重的挑戰(zhàn)地淀。

既然分割這么麻煩帮毁,那就不要分,所有的 Class 都往同一個(gè)項(xiàng)目丟硬梁,不就什么事都沒有了荧止?以結(jié)論來說阶剑,這不是一個(gè)謹(jǐn)慎的架構(gòu)師會(huì)采用的策略牧愁。這個(gè)方式的好處除了在更新版本時(shí),不用考慮各端點(diǎn)設(shè)備版本配對(duì)的問題兔朦、直接將所有設(shè)備用相同的文件覆蓋過一次之外磨确,我想不到還有其他的優(yōu)點(diǎn)沽甥。

首先,在開發(fā)階段會(huì)碰到的問題是剛才提到的可見范圍的議題乏奥,開發(fā)人員會(huì)因?yàn)樗?fù)責(zé)的 Class 看得見其他遠(yuǎn)端的 Class 而產(chǎn)生混淆摆舟,然后開始不停地質(zhì)疑為什么明明就在眼前卻不能直接調(diào)用。但其中的差別大概也只有負(fù)責(zé)設(shè)計(jì)的人才弄得清楚邓了,光是解釋就要花掉不少的唇舌恨诱。

再來就是部署時(shí),不見得每一個(gè)端點(diǎn)的設(shè)備都有足夠的硬件資源提供給程序運(yùn)作之用骗炉。當(dāng)所有的代碼都放在一起照宝,就會(huì)出現(xiàn)一個(gè)現(xiàn)象是不論在哪種設(shè)備上痕鳍,所提供的程序文件都是一樣的肥大硫豆,會(huì)出現(xiàn)最糟的情況是因資源不足而有運(yùn)行不穩(wěn)定的情況龙巨。如果是在移動(dòng)平臺(tái)上,就有可能會(huì)因?yàn)橐螺d的文件過大而使 App 的下載率降低熊响,導(dǎo)因卻是 App 里塞了很多用不到的代碼這種低級(jí)的問題旨别。

在設(shè)計(jì)時(shí)容易被忽略的重點(diǎn)

在 ISO 27001 的定義里,所謂的風(fēng)險(xiǎn)指的是威脅加上弱點(diǎn)的組合結(jié)果汗茄。沒有威脅就算全部都是弱點(diǎn)也無所謂秸弛,如同把一個(gè)人放到完全沒有病毐及細(xì)菌的環(huán)境中,即使免疫功能不正常也不會(huì)有致病的風(fēng)險(xiǎn)洪碳。反之递览,如果把一顆石頭放到充滿病毐及細(xì)菌的環(huán)境中,也不會(huì)有人擔(dān)心石頭有生病的疑慮瞳腌,所以沒有弱點(diǎn)就算有威脅也不用擔(dān)心绞铃。

在網(wǎng)絡(luò)世代中,設(shè)計(jì)系統(tǒng)如果不考慮安全議題嫂侍,是一個(gè)不及格的設(shè)計(jì)儿捧。然而很多時(shí)候有關(guān)安全的需求并不會(huì)被載入 SA 文件內(nèi),以致安全防護(hù)的設(shè)計(jì)在有心無心之下被排除在外挑宠。而把所有的 Class 都丟在同一個(gè)項(xiàng)目中菲盾,這種便宜行事的做法就是一個(gè)很不安全的策略、只有不在意信息安全才會(huì)選擇的方式各淀。

延續(xù)之前的內(nèi)容懒鉴,當(dāng)設(shè)備中所部署的程序中包含了許多不需要的部份,就會(huì)增加弱點(diǎn)出現(xiàn)的機(jī)會(huì)碎浇,即便這些程序片斷在正常的情況下并不運(yùn)作临谱。而網(wǎng)絡(luò)攻擊的威脅則不可能會(huì)消失、甚至手法不斷的翻新奴璃,二者結(jié)合就會(huì)大大地提高被入侵的風(fēng)險(xiǎn)值吴裤。

換個(gè)角度來說,設(shè)計(jì)與開發(fā)安全防護(hù)機(jī)制是需要成本的溺健,在沒有必要的情況下開發(fā)人員自然是多一事不如少一事,檢查寫得是愈少愈好钮蛛。畢竟在分工程度較高的團(tuán)隊(duì)中鞭缭,開發(fā)人員不一定會(huì)接觸到部署的相關(guān)規(guī)劃或執(zhí)行,自然不會(huì)對(duì)資安具備敏感度魏颓。再加上 SD 的文件中沒有特別指明防護(hù)要做到的層級(jí)岭辣,產(chǎn)出的結(jié)果一定是只有最低限度。一旦這些代碼被入侵者以不正當(dāng)?shù)氖址ㄟ\(yùn)行甸饱,就有可能形成很大的安全漏洞沦童。所以在部署的思維上應(yīng)該要做到精確的配置仑濒、只提供必要運(yùn)行的部份,以期減少安全上的風(fēng)險(xiǎn)偷遗。

在安全上墩瞳,被侵入是一個(gè)議題,信息的泄露則是另一個(gè)氏豌。假設(shè)在移動(dòng)平臺(tái)中所下載的程序中包含有 Server 端的邏輯喉酌,以目前移動(dòng)平臺(tái)對(duì)代碼的保護(hù)等級(jí)來說,無疑是送給駭客一份大禮泵喘。在這樣的情況之下泪电,就算移動(dòng)端的防護(hù)做得再好,也能夠依據(jù) App 中額外的 Server 端代碼來按圖索驥纪铺,找到破解的方法相速。

實(shí)體分割的原則

那該如何規(guī)劃以進(jìn)行實(shí)體分割?常見的三層式架構(gòu)是一個(gè)很好的切入點(diǎn)鲜锚,也就是把設(shè)計(jì)的內(nèi)容切分為 Presentation突诬、Business Logic、Data Access 三大區(qū)塊烹棉。主要是一般的部署策略中攒霹,硬件設(shè)備的配置也是以這樣的架構(gòu)做為雛型。所以當(dāng)數(shù)據(jù)傳遞的切割點(diǎn)以這些區(qū)塊的界線做為基準(zhǔn)時(shí)浆洗,在部署規(guī)劃有異動(dòng)時(shí)比較容易配合硬件架構(gòu)上的需求催束。

在最開始就把代碼以實(shí)體的方式分開,像是在 Visual Studio 里使用不同的 Project 并以 Solution 來封裝伏社,或是在 Android Studio 里在同一個(gè) Project 中分出多個(gè) Module抠刺。依據(jù)不同開發(fā)工具的特性,可以做到一部份的早期設(shè)計(jì)預(yù)警的效果摘昌。像是之前提到可見度的問題速妖,在分開后多少能降低開發(fā)人員在這方面的疑惑,減少其誤用的情況聪黎。同時(shí)也可以驗(yàn)證所設(shè)計(jì)的內(nèi)容罕容,在上線被分開部署后基本的調(diào)用過程是可以順利地運(yùn)作。如果是使用 Visual Studio 特定的版本稿饰,甚至提供了自動(dòng)化檢查的功能锦秒,負(fù)責(zé)設(shè)計(jì)的人員只要把相關(guān)的限制輸入好,就能在編譯時(shí)顯示警告喉镰,防止開發(fā)人員沒有按圖施工旅择,可以節(jié)省很多查驗(yàn)的工作。

預(yù)先做好切割還有另一項(xiàng)好處侣姆,可以提高 Class 的重用率生真、累積團(tuán)隊(duì)的技術(shù)資產(chǎn)沉噩、減少重工。因?yàn)樵诤罄m(xù)的開發(fā)工作中如果需要相同的設(shè)計(jì)柱蟀,直接引用已經(jīng)現(xiàn)有的獨(dú)立單元即可川蒙。如不是,則要在過往的程序項(xiàng)目中巡覽产弹、在一堆 Class 中做挑選派歌、復(fù)制的工作,而每一個(gè)新項(xiàng)目都要再重復(fù)一次這個(gè)循環(huán)痰哨。

當(dāng)然胶果,事情永遠(yuǎn)不可能單純到依照原則切割后,所有的 Class 就會(huì)自動(dòng)歸位斤斧,接下來要煩惱的是 Class 的分配問題早抠。譬如決定哪些是前一段提到可獨(dú)立于三層結(jié)構(gòu)之外的共用 Class、哪些負(fù)責(zé)顯示數(shù)據(jù)撬讽、哪些用于處理商業(yè)邏輯蕊连、哪些直接存取數(shù)據(jù)。定位明確的好處理游昼,曖昧不明甘苍、模棱兩可的則是會(huì)讓人燒腦。

以一個(gè)大家常用的 MVC Design Pattern 為例烘豌,View 毫無疑問地是要被放在 Presentation 層內(nèi)载庭,那 Controller 和 Model 應(yīng)該要放在 Presentation 還是 Business Logic?在這里賣個(gè)關(guān)子廊佩,留給各位看倌去思考囚聚,也歡迎留言一起討論。

分類原則的選擇

做完了實(shí)體的分割标锄,就下來就是怎么決定分類的原則顽铸。

就像一開始提到的,我傾向以依 Feature 為主料皇,不過這樣的說法并不精確谓松。還是那句話,這個(gè)世界還沒有單純到只用一種原則就可以搞定所有的事践剂。剛才也有提到共用的 Class 應(yīng)該要被獨(dú)立出來以便跨系統(tǒng)可以共用毒返,既然是可以跨系統(tǒng)代表是系統(tǒng)間共同的需求,或是因應(yīng)設(shè)計(jì)產(chǎn)生的慣例舷手。系統(tǒng)間共用的需求會(huì)出現(xiàn)在 SA 文件中,但是因應(yīng)設(shè)計(jì)產(chǎn)生的慣例在 SA 文件中不會(huì)有劲绪,如果要以 Feature 為主進(jìn)行分類男窟,這些 Class 被獨(dú)立出來之后怎么分類盆赤?

那看起來是依 Layer 比較保險(xiǎn)啰?不是歉眷!因?yàn)閷?shí)務(wù)上依 Feature 在擴(kuò)充結(jié)構(gòu)牺六、任務(wù)分配、版本控管汗捡、代碼巡覽上還是比較有優(yōu)勢(shì)淑际。例如:在需求變更時(shí),不同的變更項(xiàng)目可以被結(jié)構(gòu)給分離出來扇住,所以在發(fā)行版本時(shí)能夠更精確的選擇要異動(dòng)的項(xiàng)目清單春缕,并且把未完成的部份隔離在要發(fā)行的版本之外。

再舉一個(gè)例子艘蹋,想像一下锄贼,當(dāng)你的系統(tǒng)在分散式的架構(gòu)上,某個(gè)提供服務(wù)的設(shè)備超出負(fù)載女阀,在評(píng)估后決定要進(jìn)行分割程序打散到不同的硬件上以平衡負(fù)載宅荤。這時(shí)的切割方式是依照 Customer、Product浸策、Order 比較合理冯键?還是依照 Model、View庸汗、Controller 比較合理惫确?

所以最后的結(jié)論是:以 Feature 為分類主干、在細(xì)部中包含依 Layer 分類的混合結(jié)構(gòu)夫晌。當(dāng) Feature 的分類到了盡頭雕薪,則可以用 Layer 來接力分類∠恚或是在分類共用 Class 時(shí)所袁,于慣用的 Library、Utility凶掰、Support 名稱下燥爷,再以 Layer 做更細(xì)部的分類。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末懦窘,一起剝皮案震驚了整個(gè)濱河市前翎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌畅涂,老刑警劉巖港华,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異午衰,居然都是意外死亡立宜,警方通過查閱死者的電腦和手機(jī)冒萄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來橙数,“玉大人尊流,你說我怎么就攤上這事〉瓢铮” “怎么了崖技?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钟哥。 經(jīng)常有香客問我迎献,道長,這世上最難降的妖魔是什么瞪醋? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任忿晕,我火速辦了婚禮,結(jié)果婚禮上银受,老公的妹妹穿的比我還像新娘践盼。我一直安慰自己,他們只是感情好宾巍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布咕幻。 她就那樣靜靜地躺著,像睡著了一般顶霞。 火紅的嫁衣襯著肌膚如雪肄程。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天选浑,我揣著相機(jī)與錄音蓝厌,去河邊找鬼。 笑死古徒,一個(gè)胖子當(dāng)著我的面吹牛拓提,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播隧膘,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼代态,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了疹吃?” 一聲冷哼從身側(cè)響起蹦疑,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎萨驶,沒想到半個(gè)月后歉摧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年叁温,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豆挽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡券盅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出膛檀,到底是詐尸還是另有隱情锰镀,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布咖刃,位于F島的核電站泳炉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嚎杨。R本人自食惡果不足惜花鹅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枫浙。 院中可真熱鬧刨肃,春花似錦、人聲如沸箩帚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽紧帕。三九已至盔然,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間是嗜,已是汗流浹背愈案。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹅搪,地道東北人站绪。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像涩嚣,于是被迫代替她去往敵國和親崇众。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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