或許有些東西說(shuō)的比較主觀,有些細(xì)節(jié)點(diǎn)說(shuō)的不到位,但我覺(jué)得當(dāng)你真正發(fā)現(xiàn)并領(lǐng)悟所有的設(shè)計(jì)架構(gòu)都是圍繞業(yè)務(wù)服務(wù)和后期維護(hù)考慮時(shí),過(guò)度設(shè)計(jì)的問(wèn)題大體上就解決了。
引言
設(shè)計(jì)模式被認(rèn)為是軟件設(shè)計(jì)的“規(guī)范”,但是在互聯(lián)網(wǎng)快速發(fā)展的過(guò)程中,也暴露了一些問(wèn)題。相比過(guò)程式代碼的簡(jiǎn)單與易于修改,設(shè)計(jì)模式常常導(dǎo)致代碼復(fù)雜,增加理解與修改的成本,我們稱之為 “過(guò)度設(shè)計(jì)”。
(資料圖片僅供參考)
過(guò)度設(shè)計(jì)是認(rèn)知提升過(guò)程中的必經(jīng)階段,用什么語(yǔ)言都一樣。一般情況下,我們跟著公司內(nèi)部的開(kāi)發(fā)規(guī)范走,就能在寫(xiě)代碼的時(shí)候避免大部分坑點(diǎn),減少代碼故障和設(shè)計(jì)缺陷,但這也無(wú)法完全解決過(guò)度設(shè)計(jì)的問(wèn)題,那么過(guò)度設(shè)計(jì)是怎么產(chǎn)生的,又需要怎么減少呢?
本文將探索以下問(wèn)題:
為什么要做代碼設(shè)計(jì)設(shè)計(jì)模式是如何衍生出來(lái)的過(guò)度設(shè)計(jì)的的常見(jiàn)形式如何避免過(guò)度設(shè)計(jì)1.為什么要做代碼設(shè)計(jì)
我認(rèn)為做代碼設(shè)計(jì)的根本原因只有一個(gè):提高代碼質(zhì)量;
而代碼質(zhì)量的提升怎么體現(xiàn)出來(lái)呢??jī)蓚€(gè)方面:1、讓代碼讀起來(lái)更容易;2、讓代碼寫(xiě)起來(lái)更簡(jiǎn)便。
1.1 讓代碼讀起來(lái)更容易
首先,對(duì)于一個(gè)程序員來(lái)說(shuō),我們既要開(kāi)發(fā)自己的項(xiàng)目,也會(huì)維護(hù)別人交接過(guò)來(lái)的項(xiàng)目。我們接手的代碼風(fēng)格各式各樣,理解成本也各不相同。
不否認(rèn)一些同學(xué)技術(shù)能力非常出眾,理解能力超群,什么樣的代碼都能讀懂,并能很快的在其基礎(chǔ)上進(jìn)行優(yōu)化、開(kāi)發(fā)、重構(gòu)。但對(duì)于絕大多數(shù)心態(tài)平和的同學(xué)而言,接手一個(gè) 設(shè)計(jì)凌亂,無(wú)標(biāo)準(zhǔn)開(kāi)發(fā)規(guī)范 的項(xiàng)目絕對(duì)能讓其心態(tài)崩潰甚至開(kāi)發(fā)時(shí)滿嘴臟話。我們開(kāi)發(fā)時(shí)遵守的“編碼規(guī)范”、“設(shè)計(jì)規(guī)范”,無(wú)一不是在為了讓項(xiàng)目更好理解,更好維護(hù)。
舉幾個(gè)例子:編碼的分層、分模塊,對(duì)象和接口設(shè)計(jì)時(shí)的單一職責(zé)原則、開(kāi)閉原則、策略模式等,都能讓我們的項(xiàng)目更有層級(jí),更好理解其結(jié)構(gòu),讓代碼讀起來(lái)更容易。
1.2 讓代碼寫(xiě)起來(lái)更簡(jiǎn)單
說(shuō)到讓代碼寫(xiě)起來(lái)更簡(jiǎn)單,就不得不說(shuō)到代碼的復(fù)用。如果代碼不復(fù)用,每增加一個(gè)需求就只能往上堆代碼,寫(xiě)的代碼越來(lái)越多,代碼風(fēng)格與功能就不會(huì)呈收斂態(tài)。
那么怎么能使代碼更簡(jiǎn)單呢?
盡量相同的功能不寫(xiě)第二遍,抽對(duì)象相同屬性走繼承、抽相同方法做工具類、抽象類;按模塊抽、根據(jù)路由條件抽、橫著抽、豎著抽,總之代碼復(fù)用性越高,寫(xiě)的代碼就越少。但我們又不能不按條理抽,因?yàn)檫@樣會(huì)影響代碼的可讀性也會(huì)使依賴變得復(fù)雜,這時(shí)候設(shè)計(jì)模式就登場(chǎng)了,先輩們經(jīng)過(guò)多年的代碼設(shè)計(jì)經(jīng)驗(yàn)總結(jié)了一些常用代碼的寫(xiě)法,用于解決 不同場(chǎng)景下如何能將代碼在有條理的條件下寫(xiě)的更“偷懶” 的問(wèn)題。(這里只是舉例,并不是說(shuō)這些模式就是全部的,也不代表這些就是最好的)。
創(chuàng)建型模式:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。結(jié)構(gòu)型模式:適配器模式、代理模式、橋接模式、裝飾器模式、外觀模式、享元模式、組合模式。行為型模式:策略模式、模板方法模式、觀察者模式、迭代子模式、責(zé)任鏈模式、命令模式、備忘錄模式、狀態(tài)模式、訪問(wèn)者模式、中介者模式、解釋器模式。
學(xué)習(xí)這些東西能讓我們的代碼復(fù)用性更高,擴(kuò)展起來(lái)更容易,也會(huì)讓我們代碼看起來(lái)高端、大氣上檔次。
簡(jiǎn)單介紹幾種設(shè)計(jì)模式
工廠模式能讓我們更簡(jiǎn)單地創(chuàng)建基礎(chǔ)相同而局部不同的相似對(duì)象;適配器模式能讓我們?cè)趯?shí)現(xiàn)接口時(shí)更簡(jiǎn)單地只實(shí)現(xiàn)特異性方法;策略模式則能夠讓我們調(diào)用接口時(shí)根據(jù)不同的條件路由到不同的實(shí)現(xiàn)策略上去。換個(gè)角度看到設(shè)計(jì)模式
讓我們換個(gè)角度來(lái)看上面這些設(shè)計(jì)模式,如果我們將接口的實(shí)現(xiàn)方法當(dāng)做對(duì)象類的屬性,
適配器模式是否就成了一個(gè)適用于 class 類的工廠模式;工廠模式通過(guò)不同的屬性參數(shù)創(chuàng)建不同的對(duì)象;
適配器模式通過(guò)不同的場(chǎng)景創(chuàng)建不同的接口實(shí)現(xiàn)類,甚至更向上抽象一層,策略模式通過(guò)不同的業(yè)務(wù)條件路由到不同的接口實(shí)現(xiàn)時(shí)也有些同樣的味道。
我想說(shuō)的是不同的設(shè)計(jì)好多時(shí)候他們的基本思考方式是相通的,它們只是一些問(wèn)題的常用解決方法模板,并不是各不相同的死定義。
2.設(shè)計(jì)模式是如何衍生出來(lái)的
上面說(shuō)了那么多因?yàn)樗裕蠹铱赡芸次淖挚吹念^痛,這里我先舉例來(lái)說(shuō)明下常規(guī)代碼接口設(shè)計(jì)的發(fā)展形式:
產(chǎn)品說(shuō)我要做個(gè)天體系統(tǒng),先來(lái)個(gè)月亮
需求一:要有功能:創(chuàng)建個(gè)月亮(新產(chǎn)品,產(chǎn)品功能可能給不明確,方向也不明確,先簡(jiǎn)單實(shí)現(xiàn)其功能)
一月后,再來(lái)個(gè)地球
需求二:要有功能創(chuàng)建一個(gè)月亮,一個(gè)地球(有兩個(gè)星球了,后續(xù)可能會(huì)有多個(gè),抽象星球父對(duì)象,將相同的東西放父類中)
再一月后,要上星球管理系統(tǒng)了
需求 3:星球創(chuàng)建的時(shí)候要加過(guò)程,創(chuàng)建地球的時(shí)候要順便在星球上造山川、河流,還都要通知到星球管理局(針對(duì)不同星球有差異化需求了,考慮到現(xiàn)在星球還只有兩種,段時(shí)間內(nèi)也不會(huì)增加特別多,結(jié)合開(kāi)發(fā)時(shí)間,將星球類當(dāng)做適配器來(lái)用,同時(shí)使用模板方法模式將特異性方法抽取成公共方法)
再一年后,要豐富星系了
需求 4:一次創(chuàng)建一個(gè)星球,要支持太陽(yáng)系的 8 種行星,并且之后會(huì)擴(kuò)展為無(wú)數(shù)種星球,除了地球外初始化的數(shù)據(jù)和月亮一樣(由于星球數(shù)大量擴(kuò)張,再用 java 類來(lái)定義星球需要大量創(chuàng)建 java 類,而且之后要支持無(wú)數(shù)種星球,現(xiàn)有模式要被打破了,但現(xiàn)階段稍微改改還能平滑過(guò)度,結(jié)合星球擁有的公共屬性方法,將其合為一個(gè)類,先對(duì)地球做特殊處理,等要無(wú)限支持的時(shí)候,做成數(shù)據(jù)庫(kù)配置或者配置中心配置實(shí)現(xiàn))
再一月后:完善產(chǎn)品,支持無(wú)限種星球
需求 5:需要支持無(wú)限種星球了,可以創(chuàng)建的星球需要由運(yùn)營(yíng)去配置,而且創(chuàng)建后需要按照順序分別執(zhí)行不同的動(dòng)作,現(xiàn)定義 3 種動(dòng)作,將來(lái)還可能支持更多種動(dòng)作,動(dòng)作 1:初始化初始化物體,具體是什么可以由運(yùn)營(yíng)配置;動(dòng)作 2:通知星球管理局;動(dòng)作 3:遭到撞擊,毀滅;(到處都要支持配置,開(kāi)放度太高,由于每種星球的差異化需求,之前的星球模型的模板方法明顯已經(jīng)不支持現(xiàn)有的場(chǎng)景了,需要用一種可以通過(guò)配置來(lái)執(zhí)行方法的模型,這里 DemoService 類在一張圖里截不完了,和場(chǎng)景 4 的完全一樣,就先省去吧)
上述過(guò)程是一個(gè)功能從簡(jiǎn)單到復(fù)雜,然后使用的設(shè)計(jì)模式也逐漸改變,最終適用于業(yè)務(wù)發(fā)展的一種過(guò)程,如果在需求 1 的時(shí)候直接就上需求 5 的責(zé)任鏈模式,那么這個(gè)就屬于設(shè)計(jì)過(guò)度了。
關(guān)于設(shè)計(jì)過(guò)度不同同學(xué)往往有不同的容忍度,有時(shí)候在某種情況下也可能會(huì)成為有前瞻性的設(shè)計(jì),關(guān)于這塊有時(shí)候還是不好評(píng)判的。
3.過(guò)度設(shè)計(jì)的的常見(jiàn)形式
什么叫過(guò)度設(shè)計(jì)?
只要團(tuán)隊(duì)里內(nèi)沒(méi)有足夠能力把控未來(lái)三年的架構(gòu)發(fā)展,便只需要把代碼重構(gòu)到恰好滿足當(dāng)下的最佳狀態(tài),那么我們?cè)陂_(kāi)發(fā)的時(shí)候總是要考慮一下未來(lái)的需求到底會(huì)往哪個(gè)方向走。你蒙中了,就叫正交分解。你沒(méi)蒙中,就叫過(guò)度設(shè)計(jì)。
過(guò)度設(shè)計(jì)的場(chǎng)景很多,這里列舉下常見(jiàn)的幾種情況:
有時(shí)相同的功能使用不同的設(shè)計(jì)模式都可以實(shí)現(xiàn),設(shè)計(jì)模式的引入常常導(dǎo)致代碼復(fù)雜,增加理解與修改的成本,我們作為開(kāi)發(fā)者必須要把控理解成本、代碼實(shí)現(xiàn)復(fù)雜度、減少的代碼量,代碼擴(kuò)展性之間的平衡,一旦思考不到位、理解不到位,打破了其中的平衡,過(guò)度設(shè)計(jì)就產(chǎn)生了。
而我們?cè)谌粘W(xué)習(xí)和開(kāi)發(fā)中,甚至在發(fā)或者技術(shù)方案評(píng)審的時(shí)候也不可能開(kāi)對(duì)技術(shù)、業(yè)務(wù)全部理解到位,即使對(duì)自己負(fù)責(zé)的項(xiàng)目理解到位了也沒(méi)有條件對(duì)跨項(xiàng)目協(xié)作中的直接或間接依賴項(xiàng)目的來(lái)龍去脈完全清楚,這時(shí)候當(dāng)你想搞個(gè)“高級(jí)”東西的時(shí)候,就很難把控會(huì)不會(huì)搞出過(guò)度設(shè)計(jì),這也就是我說(shuō)的過(guò)度設(shè)計(jì)是認(rèn)知提升過(guò)程中的必經(jīng)階段。
4.如何避免過(guò)度設(shè)計(jì)
上面說(shuō)了過(guò)度設(shè)計(jì)的來(lái)龍去脈和很難避免性,那么如何能最大限度的避免過(guò)度設(shè)計(jì)呢?
根據(jù)我過(guò)往經(jīng)驗(yàn)大概從這幾個(gè)方面著手:
按照公司的編碼規(guī)范寫(xiě)代碼、遵守公司內(nèi)的約定是很重要的事情,如果公司內(nèi)部沒(méi)有自己的編碼規(guī)范,還可以參考業(yè)內(nèi)認(rèn)可的編碼規(guī)范(這些都是公司前輩們總結(jié)的最適用于自己公司的經(jīng)驗(yàn))熟悉設(shè)計(jì)模式,對(duì)于不熟悉的設(shè)計(jì)模式寧愿不用也不瞎用,保持代碼簡(jiǎn)單易懂(不做一知半解,不炫技)充分理解需求并有一定前瞻能力,根據(jù)業(yè)務(wù)場(chǎng)景復(fù)雜度選擇自己熟悉的設(shè)計(jì)模式(一切拋開(kāi)場(chǎng)景的設(shè)計(jì)都是攪屎棍)編碼時(shí)有點(diǎn)潔癖,習(xí)慣抽取和改動(dòng)不合理的代碼,對(duì)代碼質(zhì)量有追求(要認(rèn)真哦,出了 bug 是要背的,沒(méi)把握的話可以暫時(shí)不改,但要打上標(biāo)記后續(xù)一點(diǎn)點(diǎn)改)小步快跑,簡(jiǎn)單點(diǎn)可能也挺好:不要一開(kāi)始就想著做出完美的方案,很多時(shí)候優(yōu)秀的方案不是設(shè)計(jì)出來(lái)的,而是逐漸演變出來(lái)的,一點(diǎn)點(diǎn)優(yōu)化已有的設(shè)計(jì)方案比一開(kāi)始就設(shè)計(jì)出一個(gè)完美的方案容易得多。5.總結(jié)
上面或許有些東西說(shuō)的比較主觀,有些細(xì)節(jié)點(diǎn)說(shuō)的不到位,但我覺(jué)得當(dāng)你真正發(fā)現(xiàn)并領(lǐng)悟所有的設(shè)計(jì)架構(gòu)都是圍繞業(yè)務(wù)服務(wù)和后期維護(hù)考慮時(shí),過(guò)度設(shè)計(jì)的問(wèn)題大體上就解決了。
以上是我對(duì)于過(guò)度設(shè)計(jì)的理解,隨著我工作年限的增加說(shuō)不定過(guò)兩年我會(huì)再有其他感悟,到時(shí)候再分享給大家。
關(guān)鍵詞:
責(zé)任編輯:Rex_09