摘要:提高代碼的復(fù)用性,應(yīng)該是不同場(chǎng)景,不同解決方案的。不建議強(qiáng)制提高代碼復(fù)用性,如果提高代碼復(fù)用性會(huì)大大的降低代碼的可讀性,維護(hù)性,可能會(huì)得不償失。
ctrl+c 和 ctrl+v 給我們帶來(lái)了很多的便利,但是也使我們變得懶惰,不愿思考。1.前言
相信很多人和我一樣,在開(kāi)發(fā)項(xiàng)目的時(shí)候,因?yàn)轫?xiàng)目趕,或者一時(shí)沒(méi)想到等原因。頻繁使用 ctrl+c 和 ctrl+v ,導(dǎo)致代碼很多都是重復(fù)的。這幾天,也看了自己以前寫(xiě)的代碼,簡(jiǎn)單的探索了一下,挑選幾個(gè)實(shí)例,分享下如何在特定場(chǎng)景下,保證代碼質(zhì)量前提下,提高代碼復(fù)用性。
提高代碼的復(fù)用性,應(yīng)該是不同場(chǎng)景,不同解決方案的。同時(shí)也要保證代碼質(zhì)量。不建議強(qiáng)制提高代碼復(fù)用性,如果提高代碼復(fù)用性會(huì)大大的降低代碼的可讀性,維護(hù)性,可能會(huì)得不償失。2.HTML+CSS
在做項(xiàng)目的時(shí)候,相信頁(yè)面上總會(huì)有很多相似的按鈕,比如下圖,項(xiàng)目上幾個(gè)相似的按鈕。面對(duì)這樣的需求,之前是直接寫(xiě)三個(gè)按鈕
css
button{ border:none; font-family:"微軟雅黑"; } .u-btn-yes{ width:80px; height:36px; font-size:14px; color:#fff; border-radius:10px; background:#09f; } .u-btn-yes-samll{ width:60px; height:30px; font-size:12px; color:#fff; border-radius:10px; background:#09f; } .u-btn-yes-big{ width:100px; height:40px; font-size:16px; color:#fff; border-radius:10px; background:#09f; }
這樣相當(dāng)于每增加一種按鈕,就增加了幾行的 css 代碼,實(shí)際上改變的只有 width ,height ,font-size 這三個(gè)屬性。
實(shí)際上可以根據(jù)大小進(jìn)行代碼復(fù)用。
.u-btn-yes{ width:80px; height:36px; font-size:14px; color:#fff; border-radius:10px; background:#09f; } .u-btn-yes.u-btn-samll{ width:60px; height:30px; font-size:12px; } .u-btn-yes.u-btn-big{ width:100px; height:40px; font-size:16px; }
頁(yè)面調(diào)用
頁(yè)面上可能還有很多按鈕類似的,但是不同顏色的(如下圖),也可以靈活處理,這樣還可以自由組合。這個(gè)也是社區(qū)上很多 UI 庫(kù)所使用的方式。
.u-btn{ width:80px; height:36px; font-size:14px; color:#fff; border-radius:10px; background:#09f; } .u-btn-samll{ width:60px; height:30px; font-size:12px; } .u-btn-big{ width:100px; height:40px; font-size:16px; } .u-btn-red{ background:#f33; } .u-btn-yellow{ background:#f90; }
html
對(duì)于這些按鈕,不建議設(shè)置 margin ,positon 等樣式,因?yàn)椴煌陌粹o在不同的地方,上面這幾個(gè)屬性基本不會(huì)一樣。3.JavaScript
關(guān)于提高代碼復(fù)用性的好處,在上面 HTML+CSS的實(shí)例里面并沒(méi)有很明顯的優(yōu)勢(shì),但在 JS 里面提高代碼的復(fù)用性優(yōu)勢(shì)就比較明顯了,下面簡(jiǎn)單列舉幾個(gè)例子。
3-1.封裝常用函數(shù)在上家公司的項(xiàng)目里面有這樣代碼,目的也很明顯,就是用戶填寫(xiě)表單的時(shí)候,還沒(méi)有填寫(xiě)完整就提交,前端這里就需要給一個(gè)簡(jiǎn)單的提示。
//當(dāng)信息沒(méi)填寫(xiě)完整的時(shí)候彈出提示 layer.alert("請(qǐng)檢查信息是否填寫(xiě)完整",{ title:"提示", icon:2 })
基于 layer 這個(gè)開(kāi)源庫(kù),代碼看得特別的簡(jiǎn)單。但是隨著項(xiàng)目的開(kāi)發(fā),用戶填寫(xiě)表單的地方有多個(gè),那么上面的代碼就會(huì)被復(fù)制到多個(gè)地方,這樣難免會(huì)有有點(diǎn)多余。
另外,這樣做最大的一個(gè)問(wèn)題就是:如果上面的代碼在項(xiàng)目上有20個(gè)地方在用,有一天需求變了,title 這個(gè)屬性值要從‘提示’變成‘警告’。那就麻煩了,要找20個(gè)地方,即使編輯器有全局替換的功能,這樣的改動(dòng)出問(wèn)題的概率也比較大。面對(duì)這樣的情況。之前處理的方法是對(duì)這個(gè)彈窗進(jìn)行簡(jiǎn)單粗暴的封裝,方便復(fù)用。
function openTips(){ //當(dāng)信息沒(méi)填寫(xiě)完整的時(shí)候彈出提示 layer.alert("請(qǐng)檢查信息是否填寫(xiě)完整",{ title:"提示", icon:2 }); }
在需要的地方,需要的時(shí)候進(jìn)行調(diào)用就好,這樣可以寫(xiě)少很多代碼!修改起來(lái),也只需要修改 openTips 這一個(gè)地方就完事了。
openTips();3-2.使用策略模式代替 switch
下面再看一個(gè)實(shí)例。借用下之前群友的發(fā)的代碼。
模擬數(shù)據(jù)
let listWarnConf = [ { warnType: 1, warnCondition: 220, }, { warnType: 2, warnCondition: 36, }, { warnType: 3, warnCondition: 45, }, { warnType: 4, warnCondition: 110, }, { warnType: 5, warnCondition: 380, } ]
業(yè)務(wù)邏輯代碼
listWarnConf.forEach(item => { switch(item.warnType) { case 1: item.warnTypeText = "超壓"; item.warnConditionText = `電壓高于${item.warnCondition}V` break; case 2: item.warnTypeText = "欠壓"; item.warnConditionText = `電壓低于${item.warnCondition}V` break case 3: item.warnTypeText = "超載"; item.warnConditionText = `電流高于${item.warnCondition}A` break case 4: item.warnTypeText = "電壓不平衡"; item.warnConditionText = `電壓不平衡高于${item.warnCondition}%` break case 5: item.warnTypeText = "電流不平衡"; item.warnConditionText = `電流不平衡${item.warnCondition}%` break } })
這樣看著結(jié)果是沒(méi)問(wèn)題的,但是看著那么多 case 執(zhí)行的都是賦值操作。而且最大的問(wèn)題和上面一樣,如果多個(gè)地方使用,需求變了,那么還是要修改這么多的地方,下面優(yōu)化下,讓代碼的復(fù)用性提高下。
//設(shè)置配置數(shù)據(jù) let warnConfig={ 1:{ warnTypeText:"超壓", warnConditionText:"電壓高于replaceTextV" }, 2:{ warnTypeText:"欠壓", warnConditionText:"電壓低于replaceTextV" }, 3:{ warnTypeText:"超載", warnConditionText:"電流高于replaceTextV" }, 4:{ warnTypeText:"電壓不平衡", warnConditionText:"電壓不平衡高于replaceText%" }, 5:{ warnTypeText:"電流不平衡", warnConditionText:"電流不平衡高于replaceText%" } } //業(yè)務(wù)邏輯--根據(jù)配置數(shù)據(jù)設(shè)置warnTypeText和warnConditionText listWarnConf.forEach(item => { item.warnTypeText=warnConfig[item.warnType].warnTypeText; item.warnConditionText=warnConfig[item.warnType].warnConditionText.replace("replaceText",item.warnCondition); })
這樣改代碼量沒(méi)減少,可讀性比 switch 差,但能讀懂。但是這樣做就是重復(fù)的代碼少了,配置數(shù)據(jù)和業(yè)務(wù)邏輯分離了,如果以后要修改配置數(shù)據(jù)或者業(yè)務(wù)邏輯,就修改其中一項(xiàng)即可,互相不影響。把配置數(shù)據(jù)抽出來(lái)公用,那么在需要修改的時(shí)候,直接修改就好。
關(guān)于提高代碼的復(fù)用性,或者說(shuō)減少重復(fù)的代碼,個(gè)人覺(jué)可以往以下目標(biāo)努力--當(dāng)需求發(fā)生改變,需要修改代碼的時(shí)候,同樣的代碼不要修改兩次。3-3.保持函數(shù)單一職責(zé),靈活組合
保持函數(shù)的單一職責(zé),保證一個(gè)函數(shù)只執(zhí)行一個(gè)動(dòng)作,每個(gè)動(dòng)作互不影響,可以自由組合,就可以提高代碼的復(fù)用性。
比如下面的代碼,從服務(wù)端請(qǐng)求回來(lái)的訂單數(shù)據(jù)如下,需要進(jìn)行以下處理
1.根據(jù) status 進(jìn)行對(duì)應(yīng)值得顯示(0-進(jìn)行中,1-已完成,2-訂單異常)
2.把 startTime 由時(shí)間戳顯示成 yyyy-mm-dd
3.如果字段值為空字符串 ,設(shè)置字段值為 ‘--’
let orderList=[ { id:1, status:0, startTime:1538323200000, }, { id:2, status:2, startTime:1538523200000, }, { id:3, status:1, startTime:1538723200000, }, { id:4, status:"", startTime:"", }, ];
需求似乎很簡(jiǎn)單,代碼也少
let _status={ 0:"進(jìn)行中", 1:"已完成", 2:"訂單異常" } orderList.forEach(item=>{ //設(shè)置狀態(tài) item.status=item.status.toString()?_status[item.status]:""; //設(shè)置時(shí)間 item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(///g,"-"):""; //設(shè)置-- for(let key in item){ if(item[key]===""){ item[key]="--"; } } })
運(yùn)行結(jié)果也正常,但是這樣寫(xiě)代碼重復(fù)性會(huì)很多,比如下面,另一組重服務(wù)端請(qǐng)求回來(lái)的用戶數(shù)據(jù),用戶數(shù)據(jù)沒(méi)有 status,startTime,兩個(gè)字段,而且需要根據(jù) type 對(duì)應(yīng)顯示用戶的身份(0-普通用戶,1-vip,2-超級(jí)vip)。
let userList=[ { id:1, name:"守候", type:0 }, { id:2, name:"浪跡天涯", type:1 }, { id:3, name:"曾經(jīng)", type:2 } ]
出現(xiàn)這樣的需求,之前寫(xiě)的代碼無(wú)法重用,只能復(fù)制過(guò)來(lái),再修改下。
let _type={ 0:"普通用戶", 1:"vip", 2:"超級(jí)vip" } userList.forEach(item=>{ //設(shè)置type item.type=item.type.toString()?_type[item.type]:""; //設(shè)置-- for(let key in item){ if(item[key]===""){ item[key]="--"; } } })
結(jié)果正常,想必大家已經(jīng)發(fā)現(xiàn)問(wèn)題了,代碼有點(diǎn)多余。下面就使用單一職責(zé)的原則改造下操作函數(shù),設(shè)置 status,startTime,type,-- 。這里拆分成四個(gè)函數(shù)。
let handleFn={ setStatus(list){ let _status={ 0:"進(jìn)行中", 1:"已完成", 2:"訂單異常" } list.forEach(item=>{ item.status=item.status.toString()?_status[item.status]:""; }) return list }, setStartTime(list){ list.forEach(item=>{ item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(///g,"-"):""; }) return list; }, setInfo(list){ list.forEach(item=>{ for(let key in item){ if(item[key]===""){ item[key]="--"; } } }) return list; }, setType(list){ let _type={ 0:"普通用戶", 1:"vip", 2:"超級(jí)vip" } list.forEach(item=>{ item.type=item.type.toString()?_type[item.type]:""; }) return list; } }
下面直接調(diào)用函數(shù)就好
//處理訂單數(shù)據(jù) orderList=handleFn.setStatus(orderList); orderList=handleFn.setStartTime(orderList); orderList=handleFn.setInfo(orderList); console.log(orderList); //處理用戶數(shù)據(jù) userList=handleFn.setType(userList); userList=handleFn.setInfo(userList); console.log(userList);
運(yùn)行結(jié)果也正常
如果嫌棄連續(xù)賦值麻煩,可以借用 jQuery 的那個(gè)思想,進(jìn)行鏈?zhǔn)秸{(diào)用。
let ec=(function () { let handle=function (obj) { //深拷貝對(duì)象 this.obj=JSON.parse(JSON.stringify(obj)); }; handle.prototype={ /** * @description 設(shè)置保密信息 */ setInfo(){ this.obj.map(item=>{ for(let key in item){ if(item[key]===""){ item[key]="--"; } } }); return this; }, /** * @description 設(shè)置狀態(tài) */ setStatus(){ let _status={ 0:"進(jìn)行中", 1:"已完成", 2:"訂單異常" } this.obj.forEach(item=>{ item.status=item.status.toString()?_status[item.status]:"" }); return this; }, /** * @description 設(shè)置時(shí)間 */ setStartTime(){ this.obj.forEach(item=>{ item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(///g,"-"):""; }); return this; }, /** * @description 設(shè)置type */ setType(){ let _type={ 0:"普通用戶", 1:"vip", 2:"超級(jí)vip" } this.obj.forEach(item=>{ item.type=item.type.toString()?_type[item.type]:""; }) return this; }, /** * @description 返回處理結(jié)果 * @return {Array|*} */ end(){ return this.obj; } } //暴露構(gòu)造函數(shù)接口 return function (obj) { return new handle(obj); } })();
這樣就可以鏈?zhǔn)秸{(diào)用了
//處理訂單數(shù)據(jù) orderList=ec(orderList).setStatus().setStartTime().setInfo().end(); console.log(orderList); //處理用戶數(shù)據(jù) userList=ec(userList).setType().end(); console.log(userList);
事情到這里了,相信大家發(fā)現(xiàn)一個(gè)很嚴(yán)重的問(wèn)題就是循環(huán)的次數(shù)增加了。沒(méi)優(yōu)化之前,只需要循環(huán)一次,就可以把設(shè)置狀態(tài),設(shè)置時(shí)間,設(shè)置--這些步驟都完成,但是現(xiàn)在 setStatus().setStartTime().setInfo() 這里的代碼,每執(zhí)行一個(gè)函數(shù),都遍歷了一次數(shù)組,這個(gè)就得優(yōu)化下。處理的方式就是在每一個(gè)函數(shù)里面,只記錄要處理什么,但是不進(jìn)行處理,等到執(zhí)行到 end 的時(shí)候再統(tǒng)一處理,以及返回。
let ec=(function () { let handle=function (obj) { //深拷貝對(duì)象 this.obj=JSON.parse(JSON.stringify(obj)); //記錄要處理的步驟 this.handleFnList=[]; }; handle.prototype={ /** * @description 設(shè)置保密信息 */ handleSetInfo(item){ for(let key in item){ if(item[key]===""){ item[key]="--"; } } return this; }, setInfo(){ this.handleFnList.push("handleSetInfo"); return this; }, /** * @description 設(shè)置狀態(tài) */ handleSetStatus(item){ let _status={ 0:"進(jìn)行中", 1:"已完成", 2:"訂單異常" } item.status=item.status.toString()?_status[item.status]:"" return item; }, setStatus(){ this.handleFnList.push("handleSetStatus"); return this; }, /** * @description 設(shè)置時(shí)間 */ handleSetStartTime(item){ item.startTime=item.startTime.toString()?new Date(item.startTime).toLocaleDateString().replace(///g,"-"):""; return item; }, setStartTime(){ this.handleFnList.push("handleSetStartTime"); return this; }, /** * @description 設(shè)置type */ handleSetType(item){ let _type={ 0:"普通用戶", 1:"vip", 2:"超級(jí)vip" } item.type=item.type.toString()?_type[item.type]:""; return item; }, setType(){ this.handleFnList.push("handleSetType"); return this; }, /** * @description 返回處理結(jié)果 * @return {Array|*} */ end(){ //統(tǒng)一處理操作 this.obj.forEach(item=>{ this.handleFnList.forEach(fn=>{ item=this[fn](item); }) }) return this.obj; } } //暴露構(gòu)造函數(shù)接口 return function (obj) { return new handle(obj); } })();
這樣改,之前的調(diào)用方式不需要改變,然后結(jié)果也是正確的
可能大家會(huì)覺(jué)得很簡(jiǎn)單一個(gè)需求,卻搞得這么復(fù)雜。如果這樣想是正確的,因?yàn)檫@個(gè)的確搞復(fù)雜了,可讀性也差了,但想到項(xiàng)目遇到的處理數(shù)據(jù)不止這一些,還有比如金額的格式顯示,其它數(shù)據(jù)的各種狀態(tài)碼解析顯示,銀行卡號(hào)每隔4位分割,電話號(hào)碼的顯示等等。所以就先封裝一下,以后用的時(shí)候,直接使用。不知道算不算是先苦后甜?如果需求比較簡(jiǎn)單,可能真的沒(méi)必要這么樣封裝。4.小結(jié)
假期看代碼,提高代碼復(fù)用性的總結(jié),差不多就是這些了,當(dāng)然還有一些實(shí)例,但是在之前已經(jīng)寫(xiě)過(guò)了,和該文章提及的實(shí)例也是大同小異,就不再重復(fù)提及。提高代碼的復(fù)用性是一個(gè)很大的話題,如果大家有什么好的建議,實(shí)例,歡迎分享。
-------------------------華麗的分割線--------------------
想了解更多,和我交流,內(nèi)推職位,請(qǐng)?zhí)砑游椅⑿拧;蛘哧P(guān)注我的微信公眾號(hào):守候書(shū)閣
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/113977.html
摘要:提高代碼的復(fù)用性,應(yīng)該是不同場(chǎng)景,不同解決方案的。不建議強(qiáng)制提高代碼復(fù)用性,如果提高代碼復(fù)用性會(huì)大大的降低代碼的可讀性,維護(hù)性,可能會(huì)得不償失。 ctrl+c 和 ctrl+v 給我們帶來(lái)了很多的便利,但是也使我們變得懶惰,不愿思考。 1.前言 相信很多人和我一樣,在開(kāi)發(fā)項(xiàng)目的時(shí)候,因?yàn)轫?xiàng)目趕,或者一時(shí)沒(méi)想到等原因。頻繁使用 ctrl+c 和 ctrl+v ,導(dǎo)致代碼很多都是重復(fù)的。這...
摘要:提高代碼的復(fù)用性,應(yīng)該是不同場(chǎng)景,不同解決方案的。不建議強(qiáng)制提高代碼復(fù)用性,如果提高代碼復(fù)用性會(huì)大大的降低代碼的可讀性,維護(hù)性,可能會(huì)得不償失。 ctrl+c 和 ctrl+v 給我們帶來(lái)了很多的便利,但是也使我們變得懶惰,不愿思考。 1.前言 相信很多人和我一樣,在開(kāi)發(fā)項(xiàng)目的時(shí)候,因?yàn)轫?xiàng)目趕,或者一時(shí)沒(méi)想到等原因。頻繁使用 ctrl+c 和 ctrl+v ,導(dǎo)致代碼很多都是重復(fù)的。這...
摘要:與類型庫(kù)相比,設(shè)計(jì)模式是一個(gè)更為普遍的概念。是在年,由建筑設(shè)計(jì)大師亞力山大建筑的永恒之道描述模式是一條由三部分組成的通過(guò)規(guī)則它表示了一個(gè)特定環(huán)境一類問(wèn)題和一個(gè)解決方案之間的關(guān)系。設(shè)計(jì)模式是在這方面開(kāi)始探索的一塊里程碑。 設(shè)計(jì)模式并非類庫(kù) 為了方便地編寫(xiě)java程序,我們會(huì)使用類庫(kù),但設(shè)計(jì)模式不是類庫(kù)。 與類型庫(kù)相比,設(shè)計(jì)模式是一個(gè)更為普遍的概念。類庫(kù)是由程序組合...
摘要:下面就通過(guò)一個(gè)簡(jiǎn)單的例子,怎么讓更加的實(shí)用,更好的復(fù)用。代碼的實(shí)用性,只能盡量,盡量再盡量。關(guān)于實(shí)用性,命名和擴(kuò)展性也很重要。而且,這樣沒(méi)復(fù)用性。關(guān)于這篇文章,也是我目前嘗試的一種方式,如果大家有更好的一個(gè)實(shí)現(xiàn)方式,歡迎在評(píng)論區(qū)留言。 程序員的精神,不應(yīng)不止于實(shí)現(xiàn),更要注重優(yōu)化。不應(yīng)止于表面,更要研究?jī)?nèi)部機(jī)制,方能青出于藍(lán)而勝于藍(lán)。 1.前言 在上家公司開(kāi)發(fā)后臺(tái)管理系統(tǒng)的時(shí)候,頻繁要處理各...
摘要:下面就通過(guò)一個(gè)簡(jiǎn)單的例子,怎么讓更加的實(shí)用,更好的復(fù)用。代碼的實(shí)用性,只能盡量,盡量再盡量。關(guān)于實(shí)用性,命名和擴(kuò)展性也很重要。而且,這樣沒(méi)復(fù)用性。關(guān)于這篇文章,也是我目前嘗試的一種方式,如果大家有更好的一個(gè)實(shí)現(xiàn)方式,歡迎在評(píng)論區(qū)留言。 程序員的精神,不應(yīng)不止于實(shí)現(xiàn),更要注重優(yōu)化。不應(yīng)止于表面,更要研究?jī)?nèi)部機(jī)制,方能青出于藍(lán)而勝于藍(lán)。 1.前言 在上家公司開(kāi)發(fā)后臺(tái)管理系統(tǒng)的時(shí)候,頻繁要處...
閱讀 3566·2023-04-25 16:35
閱讀 706·2021-10-11 11:09
閱讀 6177·2021-09-22 15:11
閱讀 3360·2019-08-30 14:03
閱讀 2601·2019-08-29 16:54
閱讀 3353·2019-08-29 16:34
閱讀 3060·2019-08-29 12:18
閱讀 2130·2019-08-28 18:31