在軟件開(kāi)發(fā)中,我們常常為溝通效率低下而頭疼。
接手維護(hù)項(xiàng)目時(shí),面對(duì)低質(zhì)量代碼,不得不一次又一次地與前任開(kāi)發(fā)者溝通;
團(tuán)隊(duì)內(nèi)部,模塊分散,編程風(fēng)格各異,使用對(duì)方服務(wù)時(shí)需要反復(fù)確認(rèn);
跨團(tuán)隊(duì)合作,技術(shù)棧不同,更需要花費(fèi)大量時(shí)間統(tǒng)一標(biāo)準(zhǔn)……
這些問(wèn)題的根源在于代碼本身帶來(lái)的學(xué)習(xí)成本和溝通成本。每一份代碼都像是一本需要重新學(xué)習(xí)的書(shū)籍,需要反復(fù)研究和溝通才能理解。
然而,為什么學(xué)習(xí)了 Spring 框架后,我們與他人交流相關(guān)問(wèn)題時(shí)效率會(huì)顯著提高?
答案在于 Spring Boot 框架應(yīng)用了一個(gè)簡(jiǎn)單卻強(qiáng)大的原則:慣例優(yōu)于配置(Convention over Configuration,CoC)。
這個(gè)原則幫助編程者提前建立起隱形的公共知識(shí)體系,當(dāng)一方提及某個(gè)知識(shí)點(diǎn)時(shí),另一方早已心領(lǐng)神會(huì),無(wú)需反復(fù)解釋,溝通效率自然水到渠成。
一、慣例原則:用“共同語(yǔ)言”編程
慣例原則起源于 Ruby On Rails 框架,其核心理念是將編程中公認(rèn)的配置方式和約定信息作為內(nèi)部默認(rèn)規(guī)則。例如MyBatis 的映射文件通常命名為 xxxMapper.xml。
由于是默認(rèn)統(tǒng)一的規(guī)則,大多數(shù)開(kāi)發(fā)者都會(huì)優(yōu)先采用,久而久之,便對(duì)規(guī)則形成統(tǒng)一認(rèn)知,溝通時(shí)自然減少了重復(fù)理解和溝通的時(shí)間。
我們可以將慣例原則理解為一種約束,在特定框架(知識(shí)體系)下,根據(jù)這些約束制定默認(rèn)規(guī)則,框架便能基于這些規(guī)則實(shí)現(xiàn)統(tǒng)一操作。
例如,Spring 框架中,使用 @Autowired 注解自動(dòng)注入 Java Bean,框架通過(guò)解析注解自動(dòng)尋找對(duì)應(yīng)的 Bean。
因此,慣例原則也被稱為“按約定編程”。
與契約原則(DBC)強(qiáng)調(diào)的“按統(tǒng)一協(xié)議/標(biāo)準(zhǔn)協(xié)作”不同,慣例原則更注重隱性知識(shí)的共享。
例如,使用 Maven 管理工程結(jié)構(gòu),其實(shí)是預(yù)設(shè)了維護(hù)者已經(jīng)了解 Maven 相關(guān)的慣例約定。
二、慣例原則解決的問(wèn)題
以常見(jiàn)的 Maven 自動(dòng)生成的 Java 工程結(jié)構(gòu)為例,這個(gè)目錄結(jié)構(gòu)對(duì) Java 程序員來(lái)說(shuō)不言自明,這就是一種公認(rèn)的慣例。
慣例原則主要解決了編程中對(duì)共同隱性知識(shí)的學(xué)習(xí)問(wèn)題,通過(guò)統(tǒng)一的默認(rèn)規(guī)則,建立起溝通的橋梁。
當(dāng)然,我們可以不使用慣例,但代價(jià)是花費(fèi)大量時(shí)間解釋和說(shuō)明新規(guī)則,并確保消除其他人的誤解。
除此之外,慣例原則還間接帶來(lái)了以下好處:
● 形成編程圈的專業(yè)行話
在編程領(lǐng)域,使用慣例就像使用專業(yè)術(shù)語(yǔ),無(wú)需額外解釋, everyone gets it.
● 減少?zèng)Q策次數(shù),降低認(rèn)知負(fù)擔(dān)
慣例幫助開(kāi)發(fā)者快速做出選擇,避免在眾多技術(shù)方案中猶豫不決,從而專注于解決實(shí)際問(wèn)題。
三、慣例原則的副作用
使用慣例原則能帶來(lái)良好的可維護(hù)性和溝通效率,但也要警惕其潛在的副作用:
● 靈活性降低
過(guò)于定制化的默認(rèn)規(guī)則,雖然統(tǒng)一了認(rèn)知,但也限制了靈活性。例如,統(tǒng)一使用 ApiResponseResult 類處理 JSON 返回格式,如果需要修改數(shù)據(jù)格式,可能需要改動(dòng)大量代碼。
● 自定義慣例的風(fēng)險(xiǎn)
自定義慣例需要團(tuán)隊(duì)內(nèi)部反復(fù)確認(rèn),否則可能導(dǎo)致嚴(yán)重問(wèn)題。例如,數(shù)據(jù)庫(kù) YN 字段默認(rèn)值不統(tǒng)一,可能導(dǎo)致數(shù)據(jù)遷移時(shí)出現(xiàn)錯(cuò)誤。
● 參考變強(qiáng)制
慣例原則可能演變成強(qiáng)制標(biāo)準(zhǔn),導(dǎo)致設(shè)計(jì)僵化。例如,數(shù)據(jù)類只能寫 get、set 方法,或者代碼只寫在一個(gè)層級(jí)。
● 不同框架慣例不可復(fù)用
不同知識(shí)體系下的慣例不同,不可混淆使用。例如,C++ 和 Java 的開(kāi)發(fā)慣例就存在差異。
四、如何正確使用慣例原則
為了避免慣例原則的副作用,我們需要掌握以下技巧:
● 遵循大多數(shù)人的慣例
選擇業(yè)界公認(rèn)的慣例,例如 Java 的駝峰命名、MySQL 數(shù)據(jù)庫(kù)字段的下劃線分割等,確保理解一致性,減少溝通成本。
● 明確慣例的適用范圍
不同的慣例適用于不同的編程語(yǔ)言、場(chǎng)景和行業(yè),需要根據(jù)實(shí)際情況選擇使用。
● 自定義慣例需團(tuán)隊(duì)確認(rèn)
自定義慣例時(shí),確保團(tuán)隊(duì)內(nèi)每個(gè)人都知曉并理解,并在實(shí)際編碼中與調(diào)用方反復(fù)確認(rèn)。
● 平衡慣例與靈活性
不要過(guò)度使用慣例,在需要靈活性的情況下,可以選擇配置或代碼實(shí)現(xiàn)。
● 避免強(qiáng)制他人使用慣例
慣例應(yīng)該是一種自由選擇,而不是強(qiáng)制要求,避免破壞他人的編程習(xí)慣,降低開(kāi)發(fā)效率。
總之,慣例優(yōu)于配置原則就像軟件開(kāi)發(fā)中的隱形橋梁,幫助我們跨越溝通的鴻溝,提升開(kāi)發(fā)效率。
但也要警惕其潛在的副作用,靈活運(yùn)用,才能最大限度地發(fā)揮其優(yōu)勢(shì),構(gòu)建高效、可維護(hù)的優(yōu)質(zhì)軟件。