記得去年 11 月份,剛入職的時候,領導把我分配到一個翻新老項目的項目組中。設計模式
當初,剛進入公司仍是蠻激動的,看到這個有點年紀的老項目,打開編輯器,看了看代碼,我差點忍不住哭了。編輯器
內心暗想,「這是哪位離職的老前輩寫的代碼,這口鍋我真不想背」,功能模塊沒有任何註釋,業務邏輯從頭至尾寫下來的,沒有代碼規範,看着這一堆老代碼,我無從下手。ide
這時背後一我的,拍了拍我肩膀,我一會兒緩過神來,原來是項目組的負責人。函數
鹿呀,咱們這個老項目,在此基礎上,要增長一個功能,這個功能就交給你去作了,項目快到上線了,今天儘快完成吧。而後把大致功能和我說了一通。測試
沒辦法,只能硬着頭皮去搞,我找到了那個功能頁面的代碼,正開始屢屢業務邏輯,下面一個代碼結構讓我眼前一亮。設計
1if(type == 'fn1'){ // 功能1 2 let a = 1; 3 let arr = []; 4 // 具體功能實現 5 // ... 6 7}else if(type == 'fn2'){ // 功能2 8 // 具體功能實現 9 // ... 10 11}else if(type == 'fn3'){ // 功能3 12 // 具體功能實現 13 // ... 14 15}else if(type == 'fn4'){ // 功能4 16 // 具體功能實現 17 // ... 18 19}else if(type == 'fn5'){ // 功能5 20 // 具體功能實現 21 // ... 22 23}else if(type == 'fn6'){ // 功能6 24 // 具體功能實現 25 // ... 26 27}else if(type == 'fn7'){ // 功能7 28 // 具體功能實現 29 // ... 30 31}else if(type == 'fn8'){ // 功能8 32 // 具體功能實現 33 // ... 34 35}else{ 36 // 具體功能實現 37 // ... 38}
哎呀個人媽呀,這一長串,看的我有點暈,這不是人們傳說中的
if-else 調用俠客嗎?調試
並且我又仔細看看了看每一個 else if 內部功能代碼實現,基本每一個功能全部邏輯代碼都堆砌在 else-if 中。代碼規範
並且好像這些功能的實現並非一我的完成的,而是通過了好幾輪前輩的接手,每當增長一個需求,該項目開發者就增長一個 else-if,因此纔有了今天我所看到的結果。code
本來我也能夠輕鬆增長個 else-if 就完成任務的,但我這我的有強迫症,不想再當一個 if-else 俠客了,好吧,開始寫個人新功能。對象
寫完以後的代碼以下:
1function readNewFile(file){ 2 // 具體功能封裝 3 // ... 4} 5 6const modelObj = { 7 fn1(file){ // 功能1 8 // ... 9 }, 10 fn2(file){ // 功能2 11 // ... 12 }, 13 fn3(file){ // 功能3 14 // ... 15 }, 16 readNewFile(file){ // 功能4 17 // 新增長的功能 18 // ... 19 }, 20 21 // 其餘功能封裝 22 // ... 23} 24 25function main(type, file){ 26 modelObj[type](file) 27}
寫完以後,我把代碼提交給個人負責人看,看完以後,沒錯,大家看完可能也會問,你這不是沒事給本身找事幹嗎,明明能夠增長一個 else-if 完事,你卻額外增長了這麼多代碼?
沒錯,功能我實現了,代碼多出了幾乎一倍,反倒被要求從新改回原來的 else-if。鹿哥性格大家又不是不知道。我說,對不起,這是個人寫代碼習慣,正當我解釋爲何要這樣寫的時候,負責人說,行了,先這樣吧。
雖然內心有一萬句不爽,可是我仍是默默的轉身離開了。
小結
這就是我剛剛實習的時候,碰到的第一件比較棘手的事情,我很理解負責人的心情,畢竟項目快速上線要緊,可是我認爲給別人留條後路,就是給本身留條後路。
鹿哥,此話怎說,怎麼感受你話裏有話。並且你尚未說爲何你要這麼麻煩的去增長功能?
好吧,不賣關子了,其實這樣的寫法並非我本身發明的,而是設計模式中的策略模式,能夠說是老前輩在幾十年的項目中總結出來,至於爲何這麼寫,確定是有它的道理的。
咱們先分析一下,上方原始代碼的缺陷有哪些?
一、最明顯的缺陷就是每一個 else-if 中的代碼有一堆實現功能的邏輯。一旦 else-if 出現問題,整個 else-if 中的其餘功能全都不能用了。
二、若是增長一個功能,須要無限的疊加 else-if。
這兩個看起來並無什麼毛病呀?別急,聽我慢慢細說。
爲何把每一個功能抽離成函數?由於像這種老項目,已經被不少前輩寫過,項目很容易出現問題,一旦出現問題,很難定位代碼,咱們更不可能找到離職的員工詢問具體哪出錯誤了。
若是咱們單獨抽離成函數,當該函數內部出現問題的時候,咱們經過斷點調試,能夠直接定位問題出如今哪裏。而不像之前在if-else 海洋裏探索定位問題。
並且每一個函數單獨封裝起來,由於遵循設計模式原則之一,單一功能原則。每一個函數只能幹一件事,每一個功能都是獨立分離的,這樣盡最大可能實現功能函數之間的解耦。
有關第二點,爲何會設置一個對象映射,而不是繼續增長 else-if?
此次咱們增長一個功能,可能幾年以後,客戶需求有變,須要再增長一個功能,而增長功能的人換了,那麼這個增長功能的人,沒必要擔憂原來的功能邏輯實現,只須要在這個對象中增長一個函數,在函數內部增長一個功能實現就 OK 了。
並且總體看起來,代碼規範和總體的代碼結構很是的清晰,不止於一旦出現問題,在修改過程當中致使其餘地方出現問題,從而影響項目的開發進度。
作完以後,我直接把個人代碼扔給了咱們公司的測試小姐姐,小姐姐對我笑了笑,咳咳,後來.....
可想而知,測試小姐姐在測試的時候,不用再把整個 else-if 拿過來測試了,而是直接拿我寫的功能函數,只測試增長的功能就完成了。
回到最初那句話,給別人留條後路,就是給本身留條後路。我給測試小姐姐留了一條後路,後來就... (大家懂得)
最後
這件事情,讓我產生深入的感悟。若是能用哲學中老子的「道」去闡述的話,將複雜的問題轉化爲最簡單的哲學思想,而後直至事物的核心與本質。
老子同時將「道」稱爲「無」和「有」,「由於它沒有形象,因此是「無」;由於它真實存在,因此是「有」。
那麼實際開發項目中,項目最初的本質就是設計模式的運用,設計模式的核心思想就是「封裝變化」。就是變與不變,變化的是擴展,不變的是穩定。變與不變又可相互轉化。所謂有形化爲無形,有法化爲沒法。
正所謂,道可道,很是道,名可名,很是名。玄之又玄,衆妙之門也。