自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起聊聊如何寫出一手好代碼

開發(fā) 前端
本文主要從理論層面為大家介紹寫好代碼的需要哪些知識(shí)儲(chǔ)備,下一篇會(huì)從具體業(yè)務(wù)場(chǎng)景出發(fā),具體實(shí)操怎么結(jié)合這些理論知識(shí)來把代碼寫好。

無論是剛?cè)胄械男率诌€是已經(jīng)工作多年的老司機(jī),都希望自己可以寫一手好代碼,這樣在代碼CR的時(shí)候就可以悄悄驚艷所有人。特別是對(duì)于剛?cè)肼毜男峦瑢W(xué)來說,代碼寫得好可以幫助自己在新環(huán)境快速建立技術(shù)影響力。因?yàn)閷?duì)于從事IT互聯(lián)網(wǎng)研發(fā)工作的同學(xué)來說,技術(shù)能力是研發(fā)同學(xué)的立身之本,而寫代碼的能力又是技術(shù)能力的重要體現(xiàn)。但可惜的是理想很豐滿,現(xiàn)實(shí)很骨感。結(jié)合慕楓自己的經(jīng)驗(yàn)來看,我們?cè)诠ぷ髦衅鋵?shí)沒那么容易可以看到寫得很好的代碼。造成這種情況的原因也許很多,但是無論什么原因都不應(yīng)該妨礙我們對(duì)于寫好代碼的追求。今天慕楓就和大家探討下到底怎樣做才能寫出一手大家都認(rèn)為好的代碼?

哪些因素制約好代碼的產(chǎn)生?

我們首先來分析下到底哪些因素造成了現(xiàn)實(shí)工作中好代碼難以產(chǎn)出。因?yàn)橹挥懈闱宄诉@個(gè)問題才能對(duì)癥下藥,這樣在我們自己寫代碼的時(shí)候才能盡量避免這些問題影響我們寫好代碼。

假如讓我們說出哪些是爛代碼,我們也許會(huì)羅列出來代碼不易理解、沒有注釋、方法或者類詞不達(dá)意、分層不合理、不夠抽象、單個(gè)方法過長(zhǎng)、單個(gè)類過長(zhǎng)、代碼難以維護(hù)每次改動(dòng)都牽一發(fā)動(dòng)全身、重復(fù)代碼過多等等,這些都是我們?cè)趯?shí)際項(xiàng)目開發(fā)過長(zhǎng)中經(jīng)常遇到的代碼問題。那么到底是什么原因造成了現(xiàn)實(shí)項(xiàng)目中有這么多的代碼問題呢?慕楓認(rèn)為主要存在以下三方面的原因。

圖片圖片

1、項(xiàng)目倒排時(shí)間不夠

項(xiàng)目需求倒排導(dǎo)致沒有時(shí)間在寫代碼前好好進(jìn)行設(shè)計(jì),所以只能先快速滿足需求等后面有時(shí)間再優(yōu)化(大概率是沒有時(shí)間的)。這就造成技術(shù)同學(xué)在寫代碼的時(shí)候怎么快怎么寫,優(yōu)先把功能實(shí)現(xiàn)了再說,很多該考慮的細(xì)節(jié)就不會(huì)考慮那么多,該處理的異常沒有進(jìn)行處理,所以可能寫出來的代碼可以說是一次性代碼,只針對(duì)當(dāng)前的業(yè)務(wù)場(chǎng)景,基本沒什么擴(kuò)展性可言。

2、團(tuán)隊(duì)技術(shù)氛圍不足

團(tuán)隊(duì)內(nèi)技術(shù)氛圍不是很濃厚,本來你是想好好把代碼寫好的,但是發(fā)現(xiàn)大家都在短平快的寫代碼,而且沒有太多人關(guān)心代碼寫的好不好,只關(guān)心需求有沒有按時(shí)完成。在這樣的團(tuán)隊(duì)氛圍影響之下,自己寫出來的代碼也在慢慢地妥協(xié)。像在阿里這樣的一線互聯(lián)網(wǎng)公司,團(tuán)隊(duì)中的代碼文化還是很強(qiáng)的,很多技術(shù)團(tuán)隊(duì)在需求上線前必須要進(jìn)行代碼CR,CR不過的代碼不允許上線。因此好的團(tuán)隊(duì)技術(shù)氛圍會(huì)促使你不得不把代碼寫好,否則在代碼CR的時(shí)候就等著接受暴風(fēng)雨般的吐槽吧。

3、自身技術(shù)水平有限

第三個(gè)原因就是自身的技術(shù)水平有限,設(shè)計(jì)模式不知道該在什么樣的業(yè)務(wù)場(chǎng)景下使用,框架的高級(jí)用法沒有掌握,經(jīng)驗(yàn)不足導(dǎo)致異常情況經(jīng)??紤]不到。自己本身沒有把代碼寫好的追求,總想著能滿足需求代碼能跑就行。

以上大概是我們實(shí)際工作中導(dǎo)致我們不能產(chǎn)出好代碼最主要的三大原因,第一個(gè)原因我們基本無法改變,因?yàn)樵诨ヂ?lián)網(wǎng)行業(yè)競(jìng)爭(zhēng)本身就非常激烈,誰能先推出新業(yè)務(wù)優(yōu)化用戶體驗(yàn),誰就能占得市場(chǎng)先機(jī)。因此項(xiàng)目倒排必定是常有的事情,也是無法避免的事情。第二個(gè)原因,如果你自己是團(tuán)隊(duì)的TL,那么盡量在團(tuán)隊(duì)中去營(yíng)造代碼CR的文化,提升團(tuán)隊(duì)中的技術(shù)氛圍。因?yàn)榇a是技術(shù)團(tuán)隊(duì)的根本,所有的業(yè)務(wù)效果落地都需要通過代碼來實(shí)現(xiàn),因此好的代碼可以幫助團(tuán)隊(duì)減少Bug出現(xiàn)的概率、提升大家的代碼效率從而達(dá)到降低人力物力成本的目的。如果你不是團(tuán)隊(duì)的TL,同時(shí)團(tuán)隊(duì)中的技術(shù)氛圍也沒那么足,那么我們也不要放棄治療,先把自己負(fù)責(zé)的模塊的代碼寫好,一點(diǎn)點(diǎn)影響團(tuán)隊(duì),逐漸喚起大家對(duì)于好代碼的重視。

前兩個(gè)因素都屬于環(huán)境因素,也許我們不好改變,但是對(duì)于第三個(gè)因素,我覺得我們可以通過理論知識(shí)的學(xué)習(xí),不斷的代碼實(shí)踐以及思考總結(jié)是可以改變的,因此本文主要還是討論如何通過改變自己來把代碼寫好。

到底什么是好代碼?

要想寫出好的代碼,首先我們得知道什么樣的代碼才是好代碼。但是好這個(gè)字本身就具有較強(qiáng)的主觀性,正所謂一千個(gè)讀者心中就有一千個(gè)哈姆雷特。因此我們需要先統(tǒng)一一下好代碼的標(biāo)準(zhǔn),有了標(biāo)準(zhǔn)之后我們?cè)賮硖接懙降自趺醋霾拍軐懗龊么a。

我相信大家肯定聽說過代碼可讀性、代碼擴(kuò)展性、可維護(hù)性等詞匯來描述好代碼的特點(diǎn),實(shí)際上這些形容詞都是從不同方面對(duì)代碼進(jìn)行了闡述。但是在慕楓看來,在實(shí)際的項(xiàng)目開發(fā)中,可維護(hù)性以及高魯棒性是好代碼的兩個(gè)比較核心的衡量標(biāo)準(zhǔn)。因?yàn)闊o論是開發(fā)新需求還是修復(fù)Bug,都是在原有的平臺(tái)代碼中進(jìn)行修改,如果原來代碼的擴(kuò)展性比較強(qiáng),那么我們編碼的時(shí)候就就可以做到最小化修改,降低引入問題的風(fēng)險(xiǎn)。而魯棒性高的代碼在線上出現(xiàn)Bug的概率相對(duì)來說就第一點(diǎn),對(duì)于維護(hù)線上服務(wù)的穩(wěn)定性具有重要意義。

可維護(hù)性

我們都知道代碼開發(fā)并不是一個(gè)人的工作,通常涉及到很多人團(tuán)隊(duì)合作。因此慕楓認(rèn)為代碼的可維護(hù)性是好代碼的第一要義。而可維護(hù)性主要體現(xiàn)在代碼可讀容易理解以及修改方便容易擴(kuò)展這兩方面,下面分別進(jìn)行闡述說明。

代碼可讀

我們寫出來的代碼不僅僅要自己能看得懂自己寫的代碼,別人也應(yīng)該可以輕松看得懂你的代碼。在一線的互聯(lián)網(wǎng)大廠中工作內(nèi)容發(fā)生變化是常有的事情,如果別人接手我們的代碼或者我們接手別人的代碼時(shí),可讀性強(qiáng)的代碼無疑可以減少大家理解業(yè)務(wù)的時(shí)間成本。因?yàn)榇a是最直接的業(yè)務(wù)表現(xiàn),那些所謂的設(shè)計(jì)文檔要么過時(shí)要么寫的非常粗略,基本不太能指導(dǎo)我們熟悉業(yè)務(wù)。那么什么樣的代碼稱得上可讀性強(qiáng)呢?

命名準(zhǔn)確

無論是包的命名、類的命名、方法的命名還是變量的命名都能很準(zhǔn)確地表達(dá)業(yè)務(wù)含義,讓人可以看其名知其義。命名應(yīng)該和實(shí)際的代碼邏輯相匹配,否則不合適的命名只會(huì)讓人丈二和尚摸不著腦袋誤導(dǎo)看代碼的同學(xué)。以前看代碼的時(shí)候我看過以main作為類中的方法名稱,所以得看完這個(gè)方法的實(shí)現(xiàn)邏輯才能明白它到底干什么的,這對(duì)于后期維護(hù)的同學(xué)來說非常不友好。

代碼注釋

另外就是必要的注釋,有些同學(xué)非常自信覺得自己寫的代碼很好懂,根本不需要寫什么注釋。結(jié)果自己過了一兩個(gè)月再回頭看自己的代碼的時(shí)候,死活想不起來某段代碼為什么要這么寫。當(dāng)然我們不必每一行代碼都寫注釋,但是該注釋的地方就要寫注釋,特別是一些邏輯比較復(fù)雜,業(yè)務(wù)性比較強(qiáng)的地方,既方便自己以后排查問題也方便后面維護(hù)的同學(xué)理解業(yè)務(wù)。因此不要對(duì)自己寫的代碼過于自信,間隔時(shí)間一長(zhǎng)也許連你自己都未必記得代碼為什么這么寫。

結(jié)構(gòu)清晰

無論是服務(wù)的包結(jié)構(gòu)還是代碼結(jié)構(gòu)都體現(xiàn)了技術(shù)同學(xué)對(duì)于技術(shù)的理解,因此即便是不深入看代碼邏輯,通過包結(jié)構(gòu)的劃分、模塊的劃分類結(jié)構(gòu)的設(shè)計(jì)已經(jīng)基本可以判斷出來項(xiàng)目的代碼質(zhì)量了。我們?cè)谶M(jìn)行包結(jié)構(gòu)設(shè)計(jì)的時(shí)候可以遵循依賴倒置的原則,讓非核心層依賴核心層。

圖片圖片


可擴(kuò)展性

隨著業(yè)務(wù)需求的不斷變化,技術(shù)同學(xué)免不了在原有的代碼邏輯中進(jìn)行修改。因此項(xiàng)目代碼的可擴(kuò)展性直接影響著后期維護(hù)的成本。如果改一個(gè)小需求就需要對(duì)原有的代碼大動(dòng)干戈,修改的地方越多引入Bug的風(fēng)險(xiǎn)就會(huì)越大。我們都知道線上的故障有七八成都是由于變更引起的,因此可擴(kuò)展性強(qiáng)的代碼可以有效控制變更的范圍。

高魯棒性

當(dāng)我們說到代碼魯棒性高的時(shí)候,實(shí)際就是說代碼比較健壯,能夠應(yīng)對(duì)各種輸入,即便出現(xiàn)異常也會(huì)有對(duì)應(yīng)的異常處理機(jī)制進(jìn)行響應(yīng)而不至于直接崩潰。而項(xiàng)目開發(fā)不是一個(gè)人的工作,通常都是團(tuán)隊(duì)合作,因此我們寫的代碼無時(shí)無刻不在和別人的代碼進(jìn)行交互,所以我們負(fù)責(zé)的代碼模塊總是在處理可能正??赡墚惓5妮斎搿H绻荒軐?duì)可能出現(xiàn)的異常輸入進(jìn)行妥善的防御性處理,那么可能就會(huì)造成Bug的產(chǎn)生,嚴(yán)重情況下甚至?xí)绊懴到y(tǒng)正常運(yùn)行。因此好的代碼除了方便擴(kuò)展方便維護(hù)之外,它必定也是高魯棒性的,否則如果每天Bug滿天飛,哪有時(shí)間和精力去琢磨代碼的可擴(kuò)展性,大部分精力都用來修復(fù)Bug,長(zhǎng)此以往自己也會(huì)感覺身心俱疲,總是感覺自己沒什么成長(zhǎng)。

如何寫出好代碼?

強(qiáng)烈內(nèi)在驅(qū)動(dòng)

為什么我把強(qiáng)烈的內(nèi)在驅(qū)動(dòng)擺在首要位置,主要是因?yàn)槲矣X得程序員只有有了想把代碼寫好的愿望,才能真正驅(qū)動(dòng)自己寫出來好代碼。否則即便掌握了各種設(shè)計(jì)原則以及優(yōu)化技巧,但是自己沒有寫好代碼的內(nèi)在驅(qū)動(dòng),總是覺得程序又不是不能用,或者覺得代碼和自己有一個(gè)能跑就行,亦或是抱著后面有時(shí)間再優(yōu)化的態(tài)度(基本是沒時(shí)間)是不可能寫好代碼的。因此首先我們得有寫好代碼的內(nèi)在驅(qū)動(dòng)和愿望,我們才能有把代碼寫好的可能。不過話又說回來,內(nèi)在驅(qū)動(dòng)是基礎(chǔ),全是感情沒有技巧肯定也不行。

沉淀業(yè)務(wù)模型

談完了內(nèi)在驅(qū)動(dòng)這個(gè)感情,我們就要來看看要掌握哪些技巧才能幫助我們寫出來好代碼,首當(dāng)其沖的就是業(yè)務(wù)領(lǐng)域模型,因?yàn)樗穷I(lǐng)域業(yè)務(wù)在工程代碼中的落地也是整個(gè)服務(wù)的核心,不過遺憾的是很多同學(xué)并沒有意識(shí)到它的重要性,甚至經(jīng)常會(huì)把數(shù)據(jù)模型和業(yè)務(wù)模型相混淆。而我自己在在團(tuán)隊(duì)中落地DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的時(shí)候,被技術(shù)同學(xué)問過比較多的問題就是數(shù)據(jù)庫表對(duì)應(yīng)的數(shù)據(jù)實(shí)體滿足不了業(yè)務(wù)需要嗎?為什么還需要業(yè)務(wù)領(lǐng)域模型?那么想要回答這些問題,我們得先搞清楚到底什么是領(lǐng)域模型,它到底能給技術(shù)團(tuán)隊(duì)帶來什么。

從本質(zhì)上來說領(lǐng)域模型就是我們對(duì)于本行業(yè)業(yè)務(wù)領(lǐng)域的認(rèn)知,體現(xiàn)了你對(duì)行業(yè)認(rèn)知的沉淀以及外化表現(xiàn)。那么怎么體現(xiàn)你對(duì)行業(yè)領(lǐng)域業(yè)務(wù)認(rèn)知的深度呢?領(lǐng)域模型就是很好的驗(yàn)證手段,對(duì)行業(yè)認(rèn)知越深刻的同學(xué)構(gòu)建的領(lǐng)域模型越能夠刻畫現(xiàn)實(shí)中的業(yè)務(wù)場(chǎng)景,我們也可以認(rèn)為領(lǐng)域模型是現(xiàn)實(shí)世界業(yè)務(wù)場(chǎng)景到代碼世界的映射,同時(shí)它也是公司重要的業(yè)務(wù)資產(chǎn)。那么每個(gè)行業(yè)的業(yè)務(wù)認(rèn)知又是從哪里來的呢?實(shí)際上就從實(shí)際的業(yè)務(wù)場(chǎng)景中抽象出來的。所以領(lǐng)域模型的建立通常都是伴隨著業(yè)務(wù)需求的出現(xiàn)。因此領(lǐng)域模型是核心,包含了業(yè)務(wù)概念以及概念之間的關(guān)系,它可以幫助團(tuán)隊(duì)統(tǒng)一認(rèn)識(shí)以及指導(dǎo)設(shè)計(jì)。

圖片圖片

但是領(lǐng)域建模具有一定的門檻,其中包含了很多難以理解的概念,這也造成了在很多技術(shù)團(tuán)隊(duì)中難以落地。但是在阿里等國內(nèi)一線互聯(lián)網(wǎng)公司卻有著廣泛的應(yīng)用,因?yàn)镈DD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)可以指導(dǎo)我們應(yīng)對(duì)復(fù)雜系統(tǒng)的設(shè)計(jì)開發(fā),控制系統(tǒng)復(fù)雜度,幫助我們劃分業(yè)務(wù)域,將業(yè)務(wù)模型域?qū)崿F(xiàn)細(xì)節(jié)相分離。所以慕楓覺得讓大家認(rèn)識(shí)到DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)以及領(lǐng)域模型的的重要性比如何玩轉(zhuǎn)DDD本身更加重要。

圖片圖片

另外在這里不得不提一下數(shù)據(jù)模型和領(lǐng)域模型的區(qū)別,在實(shí)際的工作中我發(fā)現(xiàn)很多同學(xué)都容易將這兩者混淆。領(lǐng)域模型關(guān)注的是業(yè)務(wù)場(chǎng)景下的領(lǐng)域知識(shí),是業(yè)務(wù)需求中概念以及概念之間的關(guān)系,它的存在就是顯示的精確的表達(dá)業(yè)務(wù)語義。而數(shù)據(jù)模型關(guān)注的是業(yè)務(wù)數(shù)據(jù)如何存儲(chǔ),如何擴(kuò)展以及如何操作性能更高。因此他們關(guān)注的層面不同,領(lǐng)域模型關(guān)注業(yè)務(wù),數(shù)據(jù)模型關(guān)心實(shí)現(xiàn)。

這里可以舉個(gè)例子給大家說明一下,假設(shè)有這樣的業(yè)務(wù)場(chǎng)景,告警規(guī)則中存在一個(gè)規(guī)則范圍的概念,主要可以給出不同的告警取值判斷的范圍,比如某個(gè)接口調(diào)用次數(shù)失敗的最大值,或者設(shè)備在線數(shù)量不能低于某個(gè)最小值等等,因此有了如下簡(jiǎn)化版本的領(lǐng)域模型。

圖片圖片

那么在實(shí)際實(shí)現(xiàn)落地的時(shí)候,就很自然想到將AlarmRule以及RuleRange分別用一個(gè)表進(jìn)行進(jìn)行存儲(chǔ)。這其實(shí)就是把領(lǐng)域模型和數(shù)據(jù)模型混淆的典型例子,實(shí)際上我們沒有必要搞兩張表來存儲(chǔ),一張表其實(shí)就夠了,主要有以下兩個(gè)原因:

1、寫代碼的時(shí)候我們維護(hù)一張表肯定比維護(hù)兩張表操作起來更加方便;

2、另外萬一后面ruleRange有新的變化,增減了新的判斷條件,我們還得要修改rule_ranged字段,不利于后期的擴(kuò)展。


圖片圖片

因此我們用一張表來就進(jìn)行存儲(chǔ)就好了,多一個(gè)json類型的字段,專門存儲(chǔ)閾值判斷范圍。只不過在領(lǐng)域模型中我們需要把c_rule_range定義為一個(gè)對(duì)象,這樣在代碼層面操作起來比較方便。

圖片圖片

牢記設(shè)計(jì)原則

無論設(shè)計(jì)原則還是設(shè)計(jì)模式,都是先驅(qū)們?cè)谝酝罅寇浖O(shè)計(jì)開發(fā)實(shí)踐中總結(jié)出來的寶貴經(jīng)驗(yàn),因此我們?cè)陧?xiàng)目開發(fā)中完全可以站在巨人的肩膀上利用這些設(shè)計(jì)原則指導(dǎo)我們進(jìn)行編碼。當(dāng)然如果我們想熟練使用這些設(shè)計(jì)原則,就必須先要理解他們,搞清楚這些設(shè)計(jì)原則到底是為了解決什么問題而產(chǎn)生的。

我們不妨仔細(xì)想一想,平日時(shí)間里技術(shù)同學(xué)的開發(fā)工作基本上都是在已有的服務(wù)中進(jìn)行新需求開發(fā)或者在原有的邏輯中修修改改。因此如果因?yàn)橐粋€(gè)需求需要修改原有代碼邏輯,我們總是希望修改的地方越少越好,否則如果修改的地方多了,那么引入的Bug風(fēng)險(xiǎn)就會(huì)越大。即便是項(xiàng)目需要進(jìn)行重構(gòu)的情況,那我們也希望重構(gòu)后的服務(wù)或者組件可以滿足高內(nèi)聚低耦合的大要求,這樣在未來進(jìn)行需求開發(fā)的時(shí)候可以更加方便的進(jìn)行修改。這也是我們希望我們開發(fā)的代碼高內(nèi)聚低耦合的原因。可以看得出來,設(shè)計(jì)原則的核心思想就是幫助技術(shù)人員開發(fā)的軟件平臺(tái)能夠更好地應(yīng)對(duì)各種各樣的需求變化,從而最終達(dá)到降低維護(hù)成本,提高工作效率的目的。

當(dāng)我們說到設(shè)計(jì)原則的時(shí)候,通常都會(huì)想到SOLID五大原則,這里所說的設(shè)計(jì)原則主要包括SOLID原則、迪米特法則。

單一職責(zé)原則

對(duì)于一個(gè)方法、類或者模塊來說,它的職責(zé)應(yīng)該是單一的,方法、類或者模塊應(yīng)該只負(fù)責(zé)處理一個(gè)業(yè)務(wù)。這個(gè)原則應(yīng)該很好理解,當(dāng)我們?cè)趯懘a的時(shí)候,無論是方法、類以及模塊都應(yīng)該從功能或者業(yè)務(wù)的角度考慮將無關(guān)的邏輯抽離出去。為什么這么做呢?主要還是為了能夠?qū)崿F(xiàn)代碼業(yè)務(wù)功能的原子化操作,這樣即便未來進(jìn)行修改的時(shí)候影響的范圍也會(huì)變得有限。如果我們不遵守單一職責(zé)原則,那么在修改代碼邏輯的時(shí)候很可能影響了其他業(yè)務(wù)的邏輯,造成修改影響范圍不可控的情況。

You want to isolate your modules from the complexities of the organization as a whole, and design your systems such that each module is responsible (responds to) the needs of just that one business function.

不過需要說明的是,這里的所說的單一職責(zé)是針對(duì)當(dāng)前的業(yè)務(wù)場(chǎng)景來說的,也許隨著業(yè)務(wù)的發(fā)展和場(chǎng)景的擴(kuò)充,原來滿足單一職責(zé)的方法、類或者模塊可能現(xiàn)在就不滿足了需要進(jìn)一步的拆分細(xì)化。

開閉原則

慕楓認(rèn)為開閉原則與其說它是一種設(shè)計(jì)原則,不如說它是一種軟件設(shè)計(jì)指導(dǎo)思想。無論我們編寫框架代碼還是業(yè)務(wù)代碼都可以在開閉原則這樣的核心思想指導(dǎo)下進(jìn)行設(shè)計(jì)。

Software entities (modules, classes, functions, etc.) should be open for extension , but closed for modification。

所謂開閉原則指的就是我們開發(fā)的框架、模塊以及類等軟件實(shí)體應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。這個(gè)原則看上去很容易理解,但是在進(jìn)行項(xiàng)目實(shí)際落地的時(shí)候卻不是一件容易的事情。因?yàn)閷?duì)于擴(kuò)展以及修改并沒有明確的定義,到底什么樣的代碼才是擴(kuò)展,什么樣的代碼才是修改?這些問題不搞清楚的話,我們很難把開閉原則落地到實(shí)際的項(xiàng)目開發(fā)中。

結(jié)合自己的開發(fā)經(jīng)驗(yàn)可以這么理解,假設(shè)我們?cè)陧?xiàng)目中開發(fā)一個(gè)功能的時(shí)候,如果能做到不修改已有代碼邏輯,而是在原有代碼結(jié)構(gòu)中擴(kuò)展新的模塊、類或者方法的話,那么我們認(rèn)為代碼是?開閉原則的。當(dāng)然這也不是絕對(duì)的,比如假設(shè)你修改一個(gè)原有邏輯中的判斷條件的閾值,那只能在原有代碼邏輯中進(jìn)行修改??偛荒芤?yàn)橐獫M足這個(gè)原則非要搞出來。所以我覺得我們不必要教條的去追求滿足開閉原則,而是從大方向上以及整體上考慮滿足開閉原則。

里氏替換原則

在面向?qū)ο笏枷霕?gòu)建的程序中,子類對(duì)象可以替換程序中任何地方出現(xiàn)的父類對(duì)象,同時(shí)還能保證程序的邏輯不變以及正確性不變,這就是里氏替換原則的字面理解。不知道大家有沒有發(fā)現(xiàn),這個(gè)里氏替換原則看上去和Java中的多態(tài)一樣一樣的。實(shí)際上他們還是有區(qū)別的,多態(tài)是面向?qū)ο缶幊痰奶匦?,是重要的代碼實(shí)現(xiàn)思路。而里氏替換原則是一種設(shè)計(jì)原則,約定子類不能破壞父類定義好的邏輯以及異常處理。

比如在倉儲(chǔ)業(yè)務(wù)域中,父類中有對(duì)揀貨任務(wù)進(jìn)行排序的sortPickingTaskByTime()方法,它是按照任務(wù)創(chuàng)建的時(shí)間對(duì)到來的揀貨任務(wù)進(jìn)行排序,那么我們?cè)谧宇悓?shí)現(xiàn)的時(shí)候如果在sortPickingTaskByTime()方法內(nèi)部按照揀貨任務(wù)涉及的商品品類進(jìn)行排序,那么明顯是不符合里氏替換原則的,但是從多態(tài)的角度來說或者從語法的角度來說卻沒有問題。

里氏替換原則的核心思想就是按照約定辦事,父類約定好了的行為,子類實(shí)現(xiàn)需要嚴(yán)格遵守。那么里氏替換原則對(duì)于實(shí)際編碼有什么指導(dǎo)意義呢?比如上文所說的sortPickingTaskByTime()排序方法,如果父類中的算法實(shí)現(xiàn)效率不高,我們可以在子類中進(jìn)行優(yōu)化,有了里氏替換原則就可以通過子類改進(jìn)當(dāng)前已有的實(shí)現(xiàn)。另外父類中的方法定義就是契約,可以指導(dǎo)我們后面的編碼。

接口隔離原則

所謂接口隔離說的是接口調(diào)用方不應(yīng)該被迫依賴它不需要的接口。怎么理解這句話呢?按照慕楓自己的理解,接口調(diào)用方只關(guān)心和自己業(yè)務(wù)相關(guān)的接口,其他不相關(guān)的接口應(yīng)該隔離到其他接口中。

Clients should not be forced to depend upon interfaces that they do not use。

從擴(kuò)展能力層面來看,我們定義接口的時(shí)候按照原子能力進(jìn)行定義,避免了定義一個(gè)大而全的接口,這樣在進(jìn)行擴(kuò)展的時(shí)候就可以按照具體的原子能力來進(jìn)行,這樣無論是靈活性還是通用性上面都會(huì)更加滿足需求。

從實(shí)現(xiàn)上來說,如果實(shí)現(xiàn)方僅僅需要實(shí)現(xiàn)它以來的接口功能就好,它不需要的接口功能就不需要實(shí)現(xiàn),這樣也會(huì)大大降低代碼實(shí)現(xiàn)量。當(dāng)我們擴(kuò)展或者修改代碼的時(shí)候能夠做到最小化的修改。

依賴倒置原則                                                                                       依賴倒置原則不太容易理解,但是我們?cè)趯?shí)際的項(xiàng)目開發(fā)中卻每一天都在使用,只是我們可能沒太在意罷了。                  

High-level modules shouldn't depend on low-level modules. Both modules shoud depend on abstractions.In addition,abstractions shouldn't depend on details.Details depend on abstractions.

按照字面意思理解,高層級(jí)模塊不應(yīng)該依賴低層級(jí)模塊,同時(shí)兩者都應(yīng)該依賴于抽象。另外抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。用大白話來說主要是兩個(gè)核心點(diǎn),一是面向接口編程,另一個(gè)是基礎(chǔ)層依賴核心層。

面向接口編程這個(gè)應(yīng)該很好理解,因?yàn)榻涌诙x了清晰的協(xié)議規(guī)范,研發(fā)同學(xué)可以基于接口進(jìn)行開發(fā)。

圖片圖片

                                                                     

迪米特法則

迪米特法則看名字是一點(diǎn)不知道它是干什么的,簡(jiǎn)單來說就是類和類之間能不要有關(guān)系就不要有關(guān)系,實(shí)在沒辦法必須要有關(guān)系的那也盡量只依賴必要的接口。這樣說起來感覺還是比較抽象。看下面的圖就明白了,左邊的各個(gè)模塊拆分比較獨(dú)立,符合單一職責(zé)原則,同時(shí)模塊間只依賴它所需要的模塊,而下圖右邊的模塊拆分不夠獨(dú)立,A模塊本來只需要依賴F模塊,但是FG模塊顆粒度較大,導(dǎo)致不得不依賴G模塊的接口,顯然這是不符合迪米特法則的。

圖片圖片

當(dāng)我們有了寫出來的代碼能夠?qū)崿F(xiàn)高內(nèi)聚低耦合、易擴(kuò)展以及易維護(hù)愿景之后,那就要好好學(xué)習(xí)一些代碼實(shí)現(xiàn)的設(shè)計(jì)原則,這些設(shè)計(jì)原則在戰(zhàn)略層面可以指導(dǎo)我們擴(kuò)展性強(qiáng)的代碼應(yīng)該往哪些方向進(jìn)行設(shè)計(jì)考慮。而有了指導(dǎo)思想之后,結(jié)合不同場(chǎng)景下的設(shè)計(jì)模式就自然催生出來我們想要的結(jié)果。

圖片圖片

運(yùn)用設(shè)計(jì)模式

設(shè)計(jì)模式是先驅(qū)們?cè)趯?shí)踐的基礎(chǔ)上總結(jié)出來可以落地的代碼實(shí)現(xiàn)模板,針對(duì)一些業(yè)務(wù)場(chǎng)景提供代碼級(jí)解決方案。我們根據(jù)各個(gè)設(shè)計(jì)模式的能力特點(diǎn)可以將23種設(shè)計(jì)模式分類為創(chuàng)建型模式、結(jié)構(gòu)型模式以及行為型模式。這里不再對(duì)設(shè)計(jì)模式進(jìn)行展開說明,后面有時(shí)間可以寫系列文章專門進(jìn)行介紹。不過我們需要清楚的是這23種設(shè)計(jì)模式就是程序員寫代碼打天下的招式,而提升代碼擴(kuò)展性才是最終目的。

圖片圖片

面向失敗編碼

代碼中的異常處理往往最能體現(xiàn)技術(shù)同學(xué)的編碼功力。完成一個(gè)需求并不難,但是能夠考慮到各種異常情況,在異常發(fā)生的時(shí)候依然可以得到預(yù)想輸出的代碼,卻不是每個(gè)程序員都能寫出來的。  因此無論是寫代碼還是系統(tǒng)設(shè)計(jì),都要有面向失敗進(jìn)行設(shè)計(jì)的意識(shí),每一個(gè)業(yè)務(wù)流程都要考慮如果失敗了應(yīng)該怎么辦,盡可能考慮周全可能會(huì)出現(xiàn)的意外情況,同時(shí)針對(duì)這些意外情況設(shè)計(jì)相應(yīng)的兜底措施,以實(shí)現(xiàn)防御性編碼。

這里假設(shè)有這樣的業(yè)務(wù)場(chǎng)景,當(dāng)我們的業(yè)務(wù)中有調(diào)用外部服務(wù)接口的邏輯,那么我們?cè)诰帉戇@部分代碼的時(shí)候就需要考慮面向失敗進(jìn)行編碼。因?yàn)檎{(diào)用外部接口有可能成功,有可能失敗。如果接口調(diào)用成功自然沒什么好說的,繼續(xù)執(zhí)行后續(xù)的業(yè)務(wù)邏輯就好。但是如果調(diào)用失敗了怎么辦,是直接將調(diào)用異常返回還是進(jìn)行重試,如果重試還是失敗應(yīng)該怎么辦,需不需要設(shè)計(jì)下重試的策略,比如連續(xù)重試三次都失敗的話,后續(xù)間隔固定時(shí)間再進(jìn)行重試等等。當(dāng)然我們并不需要在每個(gè)這樣的業(yè)務(wù)流程中這么做,在一些比較核心的業(yè)務(wù)鏈路中不能出錯(cuò)的流程中要有兜底措施。

圖片圖片

總結(jié)

本文主要從理論層面為大家介紹寫好代碼的需要哪些知識(shí)儲(chǔ)備,下一篇會(huì)從具體業(yè)務(wù)場(chǎng)景出發(fā),具體實(shí)操怎么結(jié)合這些理論知識(shí)來把代碼寫好。不過我們必須認(rèn)識(shí)到好代碼是需要不斷打磨的,并非一朝一夕就能練就,總是需要在不斷的實(shí)踐,不斷的思考,不斷的體會(huì)以及不斷的沉淀中實(shí)現(xiàn)代碼能力的提升。左手設(shè)計(jì)原則,右手設(shè)計(jì)模式,心中領(lǐng)域模型再加上強(qiáng)烈的內(nèi)在驅(qū)動(dòng),我相信我們有信心一定可以寫出一手好代碼。

責(zé)任編輯:武曉燕 來源: 慕楓技術(shù)筆記
相關(guān)推薦

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-09-10 21:42:31

2023-06-30 08:18:51

敏捷開發(fā)模式

2021-08-27 07:06:10

IOJava抽象

2024-02-20 21:34:16

循環(huán)GolangGo

2024-09-30 09:33:31

2024-11-27 16:07:45

2023-04-03 00:09:13

2024-09-09 00:00:00

編寫技術(shù)文檔

2023-07-18 07:56:20

2023-03-29 08:26:06

2022-02-23 08:41:58

NATIPv4IPv6

2022-09-22 08:06:29

計(jì)算機(jī)平板微信

2024-11-28 09:57:50

C#事件發(fā)布器

2022-10-08 00:00:05

SQL機(jī)制結(jié)構(gòu)

2024-07-26 09:47:28

2023-03-26 23:47:32

Go內(nèi)存模型

2023-07-24 09:41:08

自動(dòng)駕駛技術(shù)交通
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)