背景
上周開(kāi)發(fā)了一個(gè)需求,發(fā)現(xiàn)一個(gè)歷史功能,從產(chǎn)品和技術(shù)代碼的角度看,將簡(jiǎn)單的事情變得復(fù)雜。這一經(jīng)歷再次深化了我對(duì)一個(gè)核心理念的認(rèn)識(shí):簡(jiǎn)化復(fù)雜性是產(chǎn)品設(shè)計(jì)和軟件開(kāi)發(fā)中永恒的挑戰(zhàn)。我們必須不斷努力,將復(fù)雜的邏輯轉(zhuǎn)化為直觀、易用的用戶功能,并將冗長(zhǎng)、難以維護(hù)的代碼結(jié)構(gòu)變?yōu)楹?jiǎn)潔、效率高的形式。
在《人月神話》中作者提到,軟件開(kāi)發(fā)的復(fù)雜度可以劃分為本質(zhì)復(fù)雜度和偶然復(fù)雜度。本質(zhì)復(fù)雜度它是一個(gè)客觀的東西,跟你用的工具、經(jīng)驗(yàn)或解決渠道都沒(méi)有任何關(guān)系。而偶然復(fù)雜度是因?yàn)槲覀冊(cè)谔幚砣蝿?wù)的時(shí)候選錯(cuò)了方向,或者使用了錯(cuò)誤的方法。
作為工程師,我們的追求不僅僅局限于代碼的編寫(xiě)。更深層次的,我們探索的是如何對(duì)抗軟件本身產(chǎn)生的復(fù)雜度,如何將繁雜的需求轉(zhuǎn)化為簡(jiǎn)潔、優(yōu)雅的解決方案。
不單單是程序員,任何化繁為簡(jiǎn)的能力才是一個(gè)人功力深厚的體現(xiàn),沒(méi)有之一。越簡(jiǎn)單,越接近本質(zhì)。這個(gè)“簡(jiǎn)單”指的是整體的簡(jiǎn)單,而不是通過(guò)局部的復(fù)雜讓另一個(gè)局部簡(jiǎn)單。
附:需求案例復(fù)雜點(diǎn) 1)業(yè)務(wù)產(chǎn)品設(shè)計(jì)方面:Promise 業(yè)務(wù)類(lèi)型(比如生鮮時(shí)效、航空時(shí)效、普通中小件時(shí)效等)與單據(jù)類(lèi)型、作業(yè)類(lèi)型之間存在一系列復(fù)雜的轉(zhuǎn)換關(guān)系。但這幾個(gè)類(lèi)型本質(zhì)是一樣的,沒(méi)必要轉(zhuǎn)換,術(shù)語(yǔ)統(tǒng)一,對(duì)業(yè)務(wù)使用來(lái)說(shuō)也簡(jiǎn)單。 2)技術(shù)代碼方面(組內(nèi)同學(xué)CodeReview發(fā)現(xiàn)的):代碼方法“副作用”(side effect),即方法除了返回值之外,還通過(guò)修改某些外部狀態(tài)或?qū)ο髞?lái)傳遞信息。比如filterBusinessType方法的主要作用是返回一個(gè)int類(lèi)型的值,但它也修改了入?yún)⒌膔esponse對(duì)象作為一個(gè)副作用,外部鏈路會(huì)使用reponse對(duì)象屬性值。并且代碼內(nèi)部調(diào)用鏈路復(fù)雜,對(duì)于新人來(lái)說(shuō)成本較高。為了確保清晰理解這些關(guān)系,并有效地進(jìn)行代碼維護(hù),特意對(duì)這些關(guān)系及代碼鏈路進(jìn)行了詳細(xì)的梳理。
一、為什么要簡(jiǎn)單?
為什么我們要追求簡(jiǎn)單性?不應(yīng)該是復(fù)雜,才能顯得技術(shù)牛嗎?
對(duì)應(yīng)簡(jiǎn)單,各有個(gè)的說(shuō)法,個(gè)人理解如下:所見(jiàn)即所得
1.比如你架構(gòu)圖別人一看就明白這是干什么的,系統(tǒng)之間如何交互,模板之間如何交互。
2.比如定義API 別人一看文檔就明白功能職責(zé),請(qǐng)求入?yún)?,出參含義,有基本的計(jì)算機(jī)知識(shí)人都能看明白,這叫所見(jiàn)即所得。
3.比如新人在1周左右就能快速更改代碼,而不是要記住代碼各種注意事項(xiàng),盡可能減少用戶的學(xué)習(xí)曲線和理解成本
接下來(lái)從本次需求的復(fù)雜案例著手,引入自己的一些思考
二、案例詳細(xì)
1)產(chǎn)品設(shè)計(jì)
1.1)現(xiàn)狀
Promise業(yè)務(wù)類(lèi)型 > 單據(jù)類(lèi)型 > 作業(yè)類(lèi)型 各種轉(zhuǎn)換關(guān)系
1.業(yè)務(wù)類(lèi)型 轉(zhuǎn)換單據(jù)類(lèi)型(1 VS 1)
2.單據(jù)類(lèi)型 轉(zhuǎn)換為 作業(yè)類(lèi)型:根據(jù)單據(jù)類(lèi)型找到 倉(cāng)、干支線、本地 作業(yè)類(lèi)型
3.倉(cāng)&干支線&本地 作業(yè)類(lèi)型:
1.2)思考點(diǎn)
1.一對(duì)一映射的簡(jiǎn)化
“業(yè)務(wù)類(lèi)型&單據(jù)類(lèi)型 其實(shí)是1V1映射”,這表明系統(tǒng)當(dāng)初設(shè)計(jì)時(shí)考慮了業(yè)務(wù)類(lèi)型和單據(jù)類(lèi)型之間的直接關(guān)聯(lián)。如果這種一對(duì)一的關(guān)系確實(shí)存在,那么單據(jù)類(lèi)型可能是一個(gè)冗余的概念,因?yàn)槊總€(gè)業(yè)務(wù)類(lèi)型已經(jīng)隱含了單據(jù)類(lèi)型的信息。簡(jiǎn)化模型,去除冗余的單據(jù)類(lèi)型,可以減少系統(tǒng)的復(fù)雜性,并可能簡(jiǎn)化數(shù)據(jù)庫(kù)設(shè)計(jì)和代碼實(shí)現(xiàn)。
1.概念統(tǒng)一
“作業(yè)類(lèi)型本質(zhì)還是業(yè)務(wù)類(lèi)型”,這意味著在不同的上下文中可能使用了不同的術(shù)語(yǔ)來(lái)描述相同的概念。在編碼和產(chǎn)品設(shè)計(jì)中,使用統(tǒng)一的術(shù)語(yǔ)可以減少混淆,提高團(tuán)隊(duì)成員之間的溝通效率,并使得新成員更容易理解系統(tǒng)。
1.維度劃分
將業(yè)務(wù)類(lèi)型進(jìn)一步細(xì)分為“倉(cāng)、干支線、本地維度”,這表明系統(tǒng)有不同的操作維度或者分類(lèi)標(biāo)準(zhǔn)。這種維度劃分有助于在不同層面上組織和處理業(yè)務(wù)邏輯。
2)代碼問(wèn)題
2.1)內(nèi)部鏈路太長(zhǎng)
業(yè)務(wù)類(lèi)型邏輯入口之一:getBusinessTypeInfoForAll > getBusinessTypeInfo > getOrderCategoryNew > obtainOrderCategoryByCode > filterBusinessType
??
在我們的代碼庫(kù)中,上面關(guān)鍵的五個(gè)方法被多個(gè)調(diào)用入口所使用,這種情況使得管理這些入口變得極為棘手。由于調(diào)用點(diǎn)的廣泛分布,理解代碼的影響范圍變得復(fù)雜,難以一目了然地掌握。此外,這種做法也顯露出我們的代碼缺乏清晰的分層架構(gòu)。這一原則的缺失,不僅使得現(xiàn)有代碼難以維護(hù),也給未來(lái)的功能擴(kuò)展和迭代帶來(lái)了不必要的復(fù)雜性和風(fēng)險(xiǎn)。
2.2)副作用
在Java 編程語(yǔ)言中,術(shù)語(yǔ)“副作用”(side effects) 指的是一個(gè)函數(shù)或表達(dá)式在計(jì)算結(jié)果以外對(duì)程序狀態(tài)(如修改全局變量、改變輸入參數(shù)的值、進(jìn)行I/O 操作等)產(chǎn)生的影響。
?
如下filterBusinessType方法的主要作用是返回一個(gè)業(yè)務(wù)類(lèi)型int類(lèi)型的值,但它也修改了傳入的response對(duì)象的A值作為一個(gè)副作用。在外面鏈路使用了A屬性值做邏輯判斷
?
副作用問(wèn)題:在filterBusinessType方法中如果是在response之前return了數(shù)據(jù),從方法角度看不出問(wèn)題,但整個(gè)鏈路會(huì)出現(xiàn)問(wèn)題。
?錯(cuò)誤寫(xiě)法
public int filterBusinessType( Request request,Response response) { if(...){ return ... } boolean flag = isXXX(request, response); }
?正確寫(xiě)法
public int filterBusinessType( Request request,Response response) { /** * 切記:return必須在下面這行代碼(isXXX方法)后面,因?yàn)橥饷鏁?huì)使用response.A()來(lái)判斷邏輯 * 你可以理解本filterBusinessType方法會(huì)返回業(yè)務(wù)類(lèi)型,同時(shí)如果isXXX方法會(huì)修改response.setA()屬性 */ boolean flag = isXXX(request, response); if(...){ return ... } }
2.3)思考點(diǎn)
思考點(diǎn)1:代碼鏈路太長(zhǎng)
內(nèi)部代碼鏈路太長(zhǎng)是一個(gè)常見(jiàn)的維護(hù)問(wèn)題,通常源于缺乏良好的模塊化和抽象設(shè)計(jì)。以下是一些思考點(diǎn):
1.避免過(guò)度抽象:雖然抽象可以幫助簡(jiǎn)化代碼,但過(guò)度抽象反而可能會(huì)增加復(fù)雜性。確保你的抽象層次是合理的,并且每個(gè)抽象都有明確的目的和價(jià)值。
2.分層架構(gòu):將代碼按照邏輯和職責(zé)分成不同的層次,每一層只對(duì)其下一層有依賴性,而不需要知道更深層次的實(shí)現(xiàn)細(xì)節(jié)。這樣可以減少代碼之間的耦合度,簡(jiǎn)化內(nèi)部鏈路。
3.合并重復(fù)代碼:如果發(fā)現(xiàn)多個(gè)方法都在執(zhí)行類(lèi)似的操作,嘗試合并這些重復(fù)的代碼段,創(chuàng)建一個(gè)通用的方法來(lái)處理它們。這樣可以減少代碼的總量,提高代碼的可讀性和可維護(hù)性。
4.團(tuán)隊(duì)共識(shí)和標(biāo)準(zhǔn):與團(tuán)隊(duì)成員討論并達(dá)成共識(shí),制定一些編碼標(biāo)準(zhǔn)和最佳實(shí)踐,以便在日常開(kāi)發(fā)中就能夠遵循簡(jiǎn)潔性原則,避免產(chǎn)生新的長(zhǎng)鏈路。
思考點(diǎn)2:副作用
1)注意事項(xiàng)
1.將副作用明確化:如果一個(gè)方法有副作用,應(yīng)該在方法的名稱、文檔或使用方式中明確指出。這樣可以幫助其他開(kāi)發(fā)者更好地理解該方法的行為。
2.避免使用靜態(tài)變量:靜態(tài)變量可以被多個(gè)線程或方法共享,容易引起副作用問(wèn)題。除非有明確的理由,否則應(yīng)盡量避免使用靜態(tài)變量。
3.完全消除副作用可能是不現(xiàn)實(shí)的,尤其是在需要與外部交互的應(yīng)用程序中。關(guān)鍵是要理解副作用的存在,并采取合適的策略來(lái)管理和控制它們。
2)Java的設(shè)計(jì)約定鼓勵(lì)我們遵循以下原則:
1.單一責(zé)任原則:每個(gè)方法或類(lèi)都應(yīng)該有單一的責(zé)任或功能。
2.最小驚奇原則:方法的行為應(yīng)該符合預(yù)期,避免出現(xiàn)意外的副作用。
在這個(gè)例子中,filterBusinessType方法既返回一個(gè)整數(shù)結(jié)果,又更新了response對(duì)象,這違反了單一責(zé)任原則和最小驚奇原則。因?yàn)檎{(diào)用者可能會(huì)預(yù)期這個(gè)方法只會(huì)過(guò)濾業(yè)務(wù)類(lèi)型,而不清楚它還會(huì)修改response對(duì)象。
3)如何規(guī)避這種現(xiàn)象
為了避免這種情況,可以采用以下幾種策略:
1.分離關(guān)注點(diǎn): 可以將獲取業(yè)務(wù)類(lèi)型和響應(yīng)設(shè)置分離成兩個(gè)不同的方法。這樣,調(diào)用者就可以清晰地看到每個(gè)方法的職責(zé)。
public int filterBusinessType(String logPrefix, Request request) { // 過(guò)濾邏輯... int businessType=...; return businessType; } public void setResponseData(int filterResult, Response response) { // 根據(jù)過(guò)濾結(jié)果設(shè)置響應(yīng)數(shù)據(jù)... response.setFilteredData(...); }
1.返回復(fù)合對(duì)象(上下文context): 如果業(yè)務(wù)類(lèi)型結(jié)果和響應(yīng)數(shù)據(jù)是緊密相關(guān)的,可以考慮創(chuàng)建一個(gè)包含這兩個(gè)信息的復(fù)合對(duì)象,并將其作為方法的返回值。
public FilterResultAndResponse filterBusinessType(Request request) { // 過(guò)濾邏輯... int result=...; Response response=new Response(); response.setFilteredData(...); return new FilterResultAndResponse(result, response); } class FilterResultAndResponse { private int filterResult; private Response response; public FilterResultAndResponse(int filterResult, Response response) { this.filterResult = filterResult; this.response = response; } // Getters and setters for filterResult and response }
總的來(lái)說(shuō),副作用有時(shí)候是不可避免的,但我們可以通過(guò)以上方法來(lái)規(guī)避和管理它們,寫(xiě)出更可靠、更易于維護(hù)的代碼。
三、案例解決方案
回到本文開(kāi)頭說(shuō)的產(chǎn)品和技術(shù)復(fù)雜性案例,考慮到產(chǎn)品和技術(shù)影響promise時(shí)效內(nèi)核最底層邏輯范圍。我是采取保守的策略:維持現(xiàn)狀不變。這是因?yàn)閷?duì)核心邏輯進(jìn)行改動(dòng)會(huì)帶來(lái)廣泛的影響和較高的風(fēng)險(xiǎn),可能會(huì)牽扯到整個(gè)系統(tǒng)的穩(wěn)定性和一致性。然而,這并不意味著我們放任復(fù)雜性存在。相反,我做了以下兩點(diǎn)改進(jìn)措施:
1.增加注釋和注意事項(xiàng):在代碼中添加詳細(xì)的注釋和注意事項(xiàng),幫助團(tuán)隊(duì)其他開(kāi)發(fā)者理解這部分代碼的工作原理和潛在風(fēng)險(xiǎn)。這樣可以降低新成員上手的難度,并且減少在維護(hù)或擴(kuò)展時(shí)出現(xiàn)錯(cuò)誤的可能性。
2.團(tuán)隊(duì)分享和知識(shí)傳遞:我將分享這個(gè)案例和相應(yīng)的經(jīng)驗(yàn)教訓(xùn),向團(tuán)隊(duì)成員解釋為什么在這個(gè)特定情況下我們選擇了保持現(xiàn)狀不變,以及如何在未來(lái)的需求、架構(gòu)設(shè)計(jì)和代碼編寫(xiě)中更好地管理復(fù)雜性和副作用。通過(guò)這種方式,我們可以共同學(xué)習(xí)和成長(zhǎng),避免在類(lèi)似情況下重蹈覆轍。
這兩種方法雖然不能立即簡(jiǎn)化復(fù)雜性,但它們可以提高代碼的可讀性和可維護(hù)性,減少長(zhǎng)期的技術(shù)債務(wù)。同時(shí),團(tuán)隊(duì)分享也能促進(jìn)知識(shí)共享和團(tuán)隊(duì)協(xié)作,讓大家知道什么是正確的做法,幫助我們?cè)诿鎸?duì)類(lèi)似挑戰(zhàn)時(shí)做出更明智的決策。
四、如何做到簡(jiǎn)單--思考點(diǎn)
KISS 原則是指在設(shè)計(jì)當(dāng)中應(yīng)當(dāng)注重簡(jiǎn)約的原則??偨Y(jié)工程專業(yè)人員在設(shè)計(jì)過(guò)程中的經(jīng)驗(yàn),大多數(shù)系統(tǒng)的設(shè)計(jì)應(yīng)保持簡(jiǎn)潔和單純,而不摻入非必要的復(fù)雜性,這樣的系統(tǒng)運(yùn)作成效會(huì)取得最優(yōu);因此簡(jiǎn)單性應(yīng)該是設(shè)計(jì)中的關(guān)鍵目標(biāo),盡量避免不必要的復(fù)雜性。
1)產(chǎn)品設(shè)計(jì)
作為技術(shù)從業(yè)者,我們常常需要從用戶(無(wú)論是面向C端消費(fèi)者還是面向企業(yè)內(nèi)部的產(chǎn)品)的視角出發(fā),來(lái)探討產(chǎn)品設(shè)計(jì)中的簡(jiǎn)潔性原則。以下是我的一些觀點(diǎn),說(shuō)的并不一定對(duì),但愿能為您提供一些啟發(fā)。
以用戶為中心
?深入理解用戶需求:深刻洞察用戶的核心需求和痛點(diǎn),用客觀數(shù)據(jù)驅(qū)動(dòng)決策,而不是單憑個(gè)人直覺(jué)。
?簡(jiǎn)化用戶旅程:力求打造一個(gè)直觀的用戶旅程,盡量減輕用戶的決策壓力和學(xué)習(xí)負(fù)擔(dān)。一個(gè)優(yōu)秀的界面應(yīng)該是清晰、易懂的,使用戶能夠毫不費(fèi)力地完成所需任務(wù)。
減法設(shè)計(jì)
?在設(shè)計(jì)每一個(gè)功能環(huán)節(jié)時(shí),我們需要反復(fù)自問(wèn):這個(gè)功能是否真正必要?如果它的缺失不會(huì)損害用戶體驗(yàn),那它很可能是多余的。
直觀交互
?設(shè)計(jì)時(shí)應(yīng)確保控件和操作邏輯能夠自然地映射其功能,使用戶能夠直覺(jué)地理解產(chǎn)品的使用方法。
持續(xù)迭代
?不斷地收集用戶畫(huà)像和分析用戶反饋,將其作為產(chǎn)品設(shè)計(jì)迭代的重要依據(jù),以此不斷地精進(jìn)和完善產(chǎn)品。
案例: 1、Alfred:這個(gè)我覺(jué)得根本無(wú)需介紹,神器,使用 macOS 的同學(xué)應(yīng)該都知道。一句話來(lái)說(shuō)就是,Alfred 是 macOS 上神級(jí)的效率應(yīng)用,能夠在實(shí)際操作中大幅提升工作效率。
2、1Password:使用 1Password 生成并管理密碼后,就再也不用費(fèi)心思去想密碼的事情了,只需要記住 1Password 主密碼就萬(wàn)事大吉。 原先你需要4步驟:比如1)打開(kāi)瀏覽器 2)輸入網(wǎng)站(或者打開(kāi)收藏夾) 3)打開(kāi)網(wǎng)站輸入用戶名密碼 4)點(diǎn)擊登錄 使用1Password只需要 一步到位,自動(dòng)打開(kāi)瀏覽器登錄相關(guān)頁(yè)面
2)架構(gòu)設(shè)計(jì)
不要跟風(fēng)選擇所謂高大上的技術(shù),適合的才是最重要的。夠用+1即可。什么意思呢,就是系統(tǒng)目前夠用再往前走一步就可以了。至于這一步是什么?可能需要你在實(shí)踐過(guò)程中,慢慢找到你認(rèn)為比較合適。很多時(shí)候,我們系統(tǒng)架構(gòu)引入一個(gè)新框架或者新技術(shù),它本身帶來(lái)的復(fù)雜性其實(shí)比你這個(gè)問(wèn)題還要復(fù)雜。
簡(jiǎn)化架構(gòu)也是提高技術(shù)穩(wěn)定性的重要步驟。一個(gè)復(fù)雜的架構(gòu)可能會(huì)導(dǎo)致系統(tǒng)的各個(gè)部分難以協(xié)同工作,從而影響系統(tǒng)的穩(wěn)定性。因此,我們應(yīng)該盡量采用簡(jiǎn)單的架構(gòu)設(shè)計(jì),使得各個(gè)部分可以更容易地協(xié)同工作。
案例:業(yè)務(wù)架構(gòu)簡(jiǎn)單化-小件日歷天數(shù)30天擴(kuò)充到90天 復(fù)雜解法: 1)目前是根據(jù)業(yè)務(wù)的時(shí)效配置預(yù)計(jì)算好30天日歷,依賴N個(gè)配置(倉(cāng)-干支線-本地緩存等),在現(xiàn)有基礎(chǔ)上,預(yù)計(jì)算90天日歷。 2)缺點(diǎn):牽扯數(shù)據(jù)預(yù)計(jì)算N個(gè)地方改造,并且增加了數(shù)據(jù)量的存儲(chǔ)。改造排期長(zhǎng)并且數(shù)據(jù)存儲(chǔ)成本高 簡(jiǎn)單解法: 1)還是保持現(xiàn)有30天日歷的算法。第31天以后的日歷按照最后一天日歷進(jìn)行復(fù)制。如果日歷計(jì)算命中集約地址(比如3天1送),過(guò)濾對(duì)應(yīng)日歷即可。 2)優(yōu)點(diǎn):代碼改造工作量小,數(shù)據(jù)存儲(chǔ)成本保持不變
?
案例2:技術(shù)架構(gòu)簡(jiǎn)單化-避免過(guò)度使用技術(shù)棧 以緩存(本地、分布式緩存)為例,它的引入確實(shí)能顯著提高系統(tǒng)的響應(yīng)速度和效率。然而,這同時(shí)也帶來(lái)了新的挑戰(zhàn),如數(shù)據(jù)一致性問(wèn)題和緩存策略的選擇。
??
1)數(shù)據(jù)一致性問(wèn)題可能導(dǎo)致用戶獲取到舊的或不正確的信息。 2)而緩存策略的選擇則需要在系統(tǒng)資源利用和數(shù)據(jù)時(shí)效性之間找到平衡點(diǎn)。 為了解決這些問(wèn)題,我們可能需要引入更復(fù)雜的緩存失效策略, 1)如基于時(shí)間的失效、事件驅(qū)動(dòng)的失效機(jī)制, 這些策略的引入和管理本身就增加了系統(tǒng)的復(fù)雜性,因此在設(shè)計(jì)緩存解決方案時(shí),我們需要仔細(xì)權(quán)衡其帶來(lái)的效率提升和潛在的復(fù)雜性增加,以找到最適合當(dāng)前系統(tǒng)需求的平衡點(diǎn)。
3)最小API
對(duì)外 API 的設(shè)計(jì)決定了系統(tǒng)的可擴(kuò)展性和兼容性。一個(gè)清晰、簡(jiǎn)潔且易于理解的 API 設(shè)計(jì)可以減少各種交互問(wèn)題。編寫(xiě)一個(gè)明確的、最小的API是管理軟件系統(tǒng)簡(jiǎn)單性的必要條件,我們向API消費(fèi)者提供的方法和參數(shù)越少,這些API就越容易理解,就有更多的時(shí)間去完善這些方法,
將復(fù)雜的API設(shè)計(jì)簡(jiǎn)化為更易用、更直觀的形式,以便用戶能夠更容易地理解和使用。
1.使用標(biāo)準(zhǔn)格式:遵循一致的命名約定、數(shù)據(jù)格式和錯(cuò)誤處理機(jī)制。這將使API更加一致和易于使用。
2.API功能單一職責(zé)原則:在API設(shè)計(jì)中,單一職責(zé)原則也非常重要。如果一個(gè)API具有多個(gè)職責(zé),那么它將變得復(fù)雜且難以維護(hù)。因此,建議將API拆分為多個(gè)簡(jiǎn)單的API,每個(gè)API只負(fù)責(zé)一個(gè)特定的職責(zé)。明確其功能和用途。這將有助于確保API具有清晰的職責(zé)劃分,避免不必要的復(fù)雜性。
3.簡(jiǎn)化參數(shù):盡量避免使用過(guò)多的參數(shù),而是使用簡(jiǎn)單、易于理解的參數(shù)。如果必須使用多個(gè)參數(shù),請(qǐng)確保它們之間有明確的關(guān)系。
4.提供簡(jiǎn)潔的文檔:編寫(xiě)簡(jiǎn)潔明了的API文檔,解釋每個(gè)端點(diǎn)的功能、請(qǐng)求方法、參數(shù)和響應(yīng)格式。確保文檔易于閱讀和理解,以便用戶能夠快速上手。
5.提供示例代碼:為API提供示例代碼,展示如何使用不同的請(qǐng)求方法和參數(shù)。這將幫助用戶更快地掌握API的使用技巧。
在軟件工程上,少即是多,一個(gè)很小、很簡(jiǎn)單的API通常也是一個(gè)對(duì)問(wèn)題深刻理解的標(biāo)志。
案例1:Promise適配M系統(tǒng)API 背景:M系統(tǒng)的時(shí)效是自己計(jì)算閉環(huán)的,promise是對(duì)外統(tǒng)一收口時(shí)效,在M系統(tǒng)時(shí)效業(yè)務(wù)線上,promise只是透?jìng)?,不做任何時(shí)效邏輯 復(fù)雜解法: 1)每次M系統(tǒng)相關(guān)時(shí)效需求,下游M系統(tǒng)的API需要變更,promise也需要參與改造,改造點(diǎn)2個(gè),第一個(gè)是從訂單中間件xml獲取M系統(tǒng)需要的參數(shù)。第二點(diǎn)把獲取的參數(shù)調(diào)用M系統(tǒng)API透?jìng)?2)缺點(diǎn):需求改造系統(tǒng)多,但都是轉(zhuǎn)發(fā)適配,無(wú)核心邏輯,工作量耗時(shí)長(zhǎng),項(xiàng)目排期協(xié)調(diào),溝通成本大 簡(jiǎn)單解法: 1)跟M系統(tǒng)溝通,M系統(tǒng)時(shí)效要的信息從X節(jié)點(diǎn)獲取,promise把該節(jié)點(diǎn)的json信息全部透?jìng)鹘oM系統(tǒng),這樣后期需求promise不參與改造, 2)優(yōu)點(diǎn):從promise角度來(lái)說(shuō)新需求不用改造,從M系統(tǒng)角度來(lái)說(shuō)時(shí)效自己閉環(huán)。這是雙贏的局面,從全局來(lái)說(shuō),減少了鏈路的開(kāi)發(fā)/聯(lián)調(diào)/溝通/協(xié)調(diào)成本,整個(gè)項(xiàng)目交互效率提升了.
案例2:?錯(cuò)誤碼設(shè)計(jì)---未傳播錯(cuò)誤碼 案例:外單無(wú)妥投時(shí)間,目前鏈路是A---->B---->C系統(tǒng)。但錯(cuò)誤碼是各自封裝,沒(méi)有把根本原因傳播出去,而是各自加工,導(dǎo)致最終看到的原因跟真實(shí)的原因千差萬(wàn)別。導(dǎo)致整個(gè)鏈路牽扯 業(yè)務(wù)方--->A研發(fā)---->B研發(fā)---->C研發(fā)---->C業(yè)務(wù)同事 總共5個(gè)環(huán)節(jié),如下圖:
??
?
案例2:?錯(cuò)誤碼信息--傳播錯(cuò)誤碼信息 1、如果API在翻譯錯(cuò)誤時(shí),需要把底層根本原因返回上去,比如上面案例,把沒(méi)有妥投日期的根本原因【XXXXXX】周知 2、改造后鏈路 A業(yè)務(wù)方---->C業(yè)務(wù)同事 總共2個(gè)環(huán)節(jié)(改造前5個(gè)環(huán)節(jié)),因?yàn)榻缑嫣崾惧e(cuò)誤信息,所見(jiàn)即所得,減少了中間環(huán)節(jié)。提升了業(yè)務(wù)效率,減少了研發(fā)內(nèi)部中間環(huán)節(jié)的排查成本。
??
4)代碼簡(jiǎn)單
編碼簡(jiǎn)單化也是提高技術(shù)穩(wěn)定性的有效方法。過(guò)于復(fù)雜的編碼可能會(huì)導(dǎo)致錯(cuò)誤和漏洞的出現(xiàn),從而影響系統(tǒng)的穩(wěn)定性。因此,我們應(yīng)該盡量使用簡(jiǎn)單、清晰的代碼。此外,我們還應(yīng)該注重代碼的可讀性和可維護(hù)性,這樣可以更容易地找到和修復(fù)錯(cuò)誤。
1.遵循單一職責(zé)原則:每個(gè)函數(shù)或類(lèi)應(yīng)該只負(fù)責(zé)一個(gè)特定的任務(wù)。這樣可以使代碼更易于理解和維護(hù),并減少錯(cuò)誤的可能性。
2.避免冗余代碼:盡量避免重復(fù)的代碼。如果需要多次使用相同的代碼塊,請(qǐng)將其封裝為函數(shù)或方法,以便在需要時(shí)調(diào)用。
3.使用注釋來(lái)解釋復(fù)雜的邏輯:如果代碼中包含復(fù)雜的邏輯或算法,請(qǐng)使用注釋來(lái)解釋其工作原理。這可以幫助其他人更好地理解代碼。
4.將長(zhǎng)代碼段拆分為多個(gè)小段:如果一個(gè)代碼段很長(zhǎng),可以考慮將其拆分為多個(gè)小段,每個(gè)小段只做一件事情。這可以使代碼更加清晰明了,并有助于調(diào)試和維護(hù)。
5.使用有意義的變量名和函數(shù)名:變量名和函數(shù)名應(yīng)具有描述性,以便其他人可以快速了解其用途。
總之,編寫(xiě)簡(jiǎn)單的代碼需要考慮多個(gè)方面,包括可讀性、可維護(hù)性和可重用性等。
五、簡(jiǎn)單原則--踐行中
我也是正在積極踐行以下原則。雖然在實(shí)踐中仍面臨挑戰(zhàn),但正不斷學(xué)習(xí)和改進(jìn)
1)復(fù)雜(重復(fù))的事情簡(jiǎn)單(工具)化
當(dāng)我們面對(duì)重復(fù)而無(wú)差別的任務(wù)時(shí),工具化的價(jià)值便凸顯出來(lái)。引入合適的工具不僅簡(jiǎn)化工作流程,還能大幅提升效率。
對(duì)于復(fù)雜的業(yè)務(wù)邏輯,我們應(yīng)致力于深入梳理和理解。詳盡的文檔是理解這些邏輯的鑰匙,它能夠?qū)?fù)雜性降低。
對(duì)于系統(tǒng)架構(gòu),我們應(yīng)該梳理上下游依賴、交互、核心接口、業(yè)務(wù)場(chǎng)景、應(yīng)急預(yù)案等,具備全局視圖
對(duì)于技術(shù)密集的代碼,充分的注釋和示例案例是必不可少的,它們是簡(jiǎn)化理解過(guò)程的橋梁。
我們還應(yīng)該將復(fù)雜的系統(tǒng)解構(gòu)為小型、可管理的模塊,這是一個(gè)將復(fù)雜事物簡(jiǎn)化的過(guò)程。
2)簡(jiǎn)單的事情標(biāo)準(zhǔn)化
一旦這些復(fù)雜的系統(tǒng)被拆分成多個(gè)簡(jiǎn)單的組件,我們就可以對(duì)每個(gè)組件進(jìn)行定制化和標(biāo)準(zhǔn)化。
3)標(biāo)準(zhǔn)的事情流程化
這樣的標(biāo)準(zhǔn)化模塊,一旦定制完成,就能夠形成一個(gè)簡(jiǎn)潔且固定的流程。這種流程化不僅為防止最糟糕情況的發(fā)生提供了保障,也使得任務(wù)能以統(tǒng)一和高效的方式運(yùn)行。
4)流程的事情自動(dòng)化
正如自動(dòng)化測(cè)試所示,一旦流程化得以實(shí)施,自動(dòng)化的基礎(chǔ)便已鋪墊?;谶@一基礎(chǔ),我們可以將復(fù)雜的任務(wù)轉(zhuǎn)化為自動(dòng)化的操作,從而盡可能地減少手動(dòng)干預(yù),實(shí)現(xiàn)高效運(yùn)作。
案例:行云部署發(fā)布上線 簡(jiǎn)單提效快 背景:為解決用戶手動(dòng)部署操作耗時(shí)高、分組多人工容易遺漏、對(duì)人依賴度高等痛點(diǎn),2個(gè)以上分組,20個(gè)容器以上的應(yīng)用,強(qiáng)烈推薦您使用【部署編排】功能,用戶可靈活制定部署策略,實(shí)現(xiàn)從編譯構(gòu)建到實(shí)例部署的自動(dòng)化運(yùn)行,提高部署效率! 復(fù)雜-->簡(jiǎn)單-->標(biāo)準(zhǔn)-->流程-->自動(dòng)化:部署編排接入了豐富的原子,提供了部署策略、流量管理、編譯構(gòu)建等功能,可基于這些功能進(jìn)行任務(wù)排布,形成一個(gè)獨(dú)立的部署編排。部署時(shí),只需執(zhí)行此編排任務(wù)即可,解放雙手實(shí)現(xiàn)自動(dòng)化部署!同時(shí)部署編排支持多分組同時(shí)部署。
六、總結(jié)
1.復(fù)雜的事情簡(jiǎn)單化
2.簡(jiǎn)單的事情標(biāo)準(zhǔn)化
3.標(biāo)準(zhǔn)的事情流程化
4.流程的事情自動(dòng)化
我們先踏出第一步化繁為簡(jiǎn)
簡(jiǎn)化復(fù)雜性不僅能在短期內(nèi)提高開(kāi)發(fā)效率和代碼質(zhì)量,也對(duì)產(chǎn)品和技術(shù)的長(zhǎng)期價(jià)值產(chǎn)生深遠(yuǎn)影響
1.當(dāng)我們考慮如何簡(jiǎn)化一個(gè)給定的任務(wù)的每一步時(shí),這不并是在偷懶。相反,我們是在明確實(shí)際上要完成的任務(wù)是什么,以及如何更容易做到。
2.我們對(duì)某些無(wú)意義的新功能說(shuō)“不”的時(shí)候,不是在限制創(chuàng)新,是在保持環(huán)境整潔,以免分心。
3.軟件的簡(jiǎn)單性是可靠性的前提條件。這樣我們可以持續(xù)關(guān)注創(chuàng)新,并且可以進(jìn)行真正的有價(jià)值的事、長(zhǎng)期的事。
?
本文旨在拋磚引玉,僅就偶然復(fù)雜度的議題,從產(chǎn)品與技術(shù)的角度,分享一些關(guān)于簡(jiǎn)單化的個(gè)人思考。希望這些初步的觀點(diǎn)能激發(fā)更多精彩的思考和深入的實(shí)踐。如果文中有任何不足之處,懇請(qǐng)各位不吝賜教,留言指正。謝謝大家的閱讀和反饋!
審核編輯 黃宇
-
API
+關(guān)注
關(guān)注
2文章
1504瀏覽量
62166 -
代碼
+關(guān)注
關(guān)注
30文章
4802瀏覽量
68738
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論