自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

讓你的 JS 代碼變得更加優(yōu)雅且可維護(hù)

開(kāi)發(fā) 前端
在開(kāi)發(fā)的過(guò)程中,總結(jié)了一些優(yōu)化開(kāi)發(fā)的編碼經(jīng)驗(yàn),當(dāng)然這些經(jīng)驗(yàn)都是前人總結(jié)出來(lái)的,這次就特別拿出來(lái)跟大家一起分享。

在開(kāi)發(fā)的過(guò)程中,總結(jié)了一些優(yōu)化開(kāi)發(fā)的編碼經(jīng)驗(yàn),當(dāng)然這些經(jīng)驗(yàn)都是前人總結(jié)出來(lái)的,這次就特別拿出來(lái)跟大家一起分享,當(dāng)然這些經(jīng)驗(yàn)不一定是最佳實(shí)踐,各位讀者有興趣或者有不同意見(jiàn)的可以跟魚(yú)頭一起探討一下。

拒絕魔法

眾所周知,魔法是這樣的:

[[375838]]

哦,不是。。

在編程的世界里也有魔法,一般稱其為:魔法數(shù)字,魔法變量,魔法字符串。例如這樣:

  1. const a = await abcdefg(); 
  2. console.log(a === 200); 
  3. const b = await asdfgh(); 
  4. if (b === 0) { 
  5. } else if (b === 1) { 
  6. } else if (b === 2) {}; 
  7. for (let i = 0; i < 10; i++) {}; 

以上直接出現(xiàn)的,莫名其妙的變量名,字符串以及判斷條件數(shù)字,就叫魔法。。。

這種寫(xiě)法寫(xiě)出來(lái)的代碼晦澀難懂,難以維護(hù),隱藏 BUG 多,除非你準(zhǔn)備給接手的人埋坑,或者準(zhǔn)備辭職,不然千萬(wàn)別這么寫(xiě)(容易被打斷腿,👨‍🦽 )

那么怎么寫(xiě)才更優(yōu)雅?

語(yǔ)義化

首先便是語(yǔ)義化。一個(gè)是變量,常量的語(yǔ)義化,例如:

  1. const SUCCESS_STATUS = 200
  2. const requestStatus = await getStatus(); 
  3. console.log(requestStatus === SUCCESS_STATUS); 
  4. const userRole = await getUserRole(); 
  5. const GUEST_CODE = 0
  6. const USER_CODE = 1
  7. const ADMIN_CODE = 2
  8. if (userRole === GUEST_CODE) { 
  9. } else if (userRole === USER_CODE) { 
  10. } else if (userRole === ADMIN_CODE) {}; 
  11. const MAX_NUM = 10
  12. const MIN_NUM = 0
  13. for (let currentNum = MIN_NUM; currentNum < MAX_NUM; currentNum++) {}; 

一般的規(guī)則就是變量用小寫(xiě),常量用大寫(xiě),把變量名語(yǔ)義化,那么當(dāng)你看到這段代碼的時(shí)候,一眼就能知道它是做什么的,而不是非得要浪費(fèi)時(shí)間看完上下文,或者是猜。

枚舉

對(duì)于上面判斷 userRole 的代碼,其實(shí)我們可以用更優(yōu)雅的方式去實(shí)現(xiàn),那就是 枚舉 。

按照維基百科的說(shuō)明:在數(shù)學(xué)和計(jì)算機(jī)科學(xué)理論中,一個(gè)集的枚舉是列出某些有窮序列集的所有成員的程序,或者是一種特定類型對(duì)象的計(jì)數(shù)。這兩種類型經(jīng)常(但不總是)重疊。

其實(shí)就是組織收集有關(guān)聯(lián)變量的一種方式。枚舉的好處在于方便多狀態(tài)的管理,以及可讀性更強(qiáng)。例如:

  1. const ROLES = { 
  2.   GUEST: 0, 
  3.   USER: 1, 
  4.   ADMIN: 2 
  5. }; 
  6. const userRole = await getUserRole(); 
  7. if (userRole === ROLES.GUEST) { 
  8. } else if (userRole === ROLES.USER) { 
  9. } else if (userRole === ROLES.ADMIN) {}; 

通過(guò)枚舉的方式歸納起來(lái),維護(hù)起來(lái)更方便,而且要添加狀態(tài)直接在 ROLES 對(duì)象里寫(xiě)就行,更方便快捷。

策略模式

維基百科上說(shuō):策略模式作為一種軟件設(shè)計(jì)模式,指對(duì)象有某個(gè)行為,但是在不同的場(chǎng)景中,該行為有不同的實(shí)現(xiàn)算法。

上面的代碼依舊是可優(yōu)化的,在這里我們可以利用策略模式來(lái)做進(jìn)一層的優(yōu)化。

具體的例子就是如下:

  1. const ROLES = { 
  2.   GUEST: 0, 
  3.   USER: 1, 
  4.   ADMIN: 2 
  5. }; 
  6. const ROLE_METHODS = { 
  7.   [ROLES.GUEST]() {}, 
  8.   [ROLES.USER]() {}, 
  9.   [ROLES.ADMIN]() {}, 
  10. }; 
  11. const userRole = await getUserRole(); 
  12. ROLE_METHODS[userRole](); 

通過(guò)上面的寫(xiě)法,我們可以知道,當(dāng)我們需要增加角色,或者修改角色數(shù)字的時(shí)候,只需要修改 ROLES 里對(duì)應(yīng)的字段,以及 ROLE_METHODS 里的方法即可,這樣我們就可以將可能很冗長(zhǎng)的 if...else 代碼給抽離出來(lái),顆粒度更細(xì),更好維護(hù)。

更在狀態(tài)

除了上面的方式之外,我們還可以利用“ 狀態(tài) ”的概念來(lái)寫(xiě)代碼。在看代碼之前,我們先了解下什么是 “有限狀態(tài)機(jī)”。

根據(jù)維基百科的解釋:有限狀態(tài)機(jī)(英語(yǔ):finite-state machine,縮寫(xiě):FSM)又稱有限狀態(tài)自動(dòng)機(jī)(英語(yǔ):finite-state automation,縮寫(xiě):FSA),簡(jiǎn)稱狀態(tài)機(jī),是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)計(jì)算模型。

例如我們熟悉的 Promise ,它就是在狀態(tài)集:PENDIN 、 FULFILLED 、 REJECTED 之間單向流轉(zhuǎn)的有限狀態(tài)機(jī)。

狀態(tài)機(jī)的概念跟策略模式類似,實(shí)現(xiàn)方式也類似,這里面最大的不同是在于 “語(yǔ)義” 。

策略模式更適合于互不依賴,同時(shí)只能存在一個(gè)狀態(tài)的場(chǎng)景,例如:

  1. const 吃 = { 
  2.   沙縣大酒店() { 
  3.     吃云吞() 
  4.   }, 
  5.   開(kāi)封菜() { 
  6.     吃漢堡() 
  7.   }, 
  8.   在家() { 
  9.     吃外賣() 
  10.   } 
  11. }; 

這里面如果我們肚子餓了,就只能在 沙縣大酒店() , 開(kāi)封菜() , 在家() 這幾個(gè)狀態(tài)里選。

你不能都吃,當(dāng)然以下情況除外。。。

如果是狀態(tài)模式,則會(huì)有這種情況:

  1. const 打工人 = { 
  2.   起床() {}, 
  3.   上班() {}, 
  4.   加班() {}, 
  5.   下班() {} 
  6. }; 
  7. // 早上6點(diǎn) 
  8. 打工人.起床(); 
  9. // 早上9點(diǎn) 
  10. 打工人.上班(); 
  11. // 晚上6點(diǎn) 
  12. 打工人.加班(); 
  13. // 晚上12點(diǎn) 
  14. 打工人.下班(); 

這里的打工人根據(jù)不同的時(shí)間,進(jìn)行不同的任務(wù),便是打工人模式,哦不,狀態(tài)模式。這里的時(shí)間就是狀態(tài)。

我們舉個(gè)實(shí)際的業(yè)務(wù)例子,就是訂單列表頁(yè),通常我們的訂單可能有這幾種狀態(tài):

不同的狀態(tài)展示的 UI 也不同,所以我們以不同的狀態(tài)劃分好模塊之后,代碼寫(xiě)起來(lái)就會(huì)清晰很多,我們以 Vue 代碼為例:

  1. // contants.js 
  2. export const ORDER_STATUS = { 
  3.   INIT: 0, // 初始化 
  4.   CREATED: 1, // 訂單創(chuàng)建 
  5.   ARREARAGE: 2, // 待支付 
  6.   PURCHASED: 3, // 已購(gòu)買 
  7.   SHIPPED: 4, // 已發(fā)貨 
  8.   COMPLETED: 5 // 已完成 
  9. }; 
  1. // order.vue 
  2. <template> 
  3.   <div> 
  4.         <section v-if="orderIsInit"></section> 
  5.         <section v-if="orderIsCreated"></section> 
  6.         <section v-if="orderIsArrearage"></section> 
  7.         <section v-if="orderIsPurchased"></section> 
  8.         <section v-if="orderIsShipped"></section> 
  9.         <section v-if="orderIsCompleted"></section> 
  10.   </div> 
  11. </template> 
  12.  
  13. <script> 
  14.   import ORDER_STATUS from './contants'; 
  15.   import eq from 'lodash'; 
  16.    
  17.   export default { 
  18.     computed: { 
  19.       /** 
  20.        * @func 
  21.        * @name orderIsInit 
  22.        * @desc 判斷訂單是否初始化的狀態(tài) 
  23.        * @returns {string} 判斷訂單是否初始化的狀態(tài) 
  24.        */ 
  25.       orderIsInit() { 
  26.         return eq(this.orderStatus, ORDER_STATUS.INIT); 
  27.       }, 
  28.       /** 
  29.        * @func 
  30.        * @name orderIsCreated 
  31.        * @desc 判斷訂單是否已創(chuàng)建的狀態(tài) 
  32.        * @returns {string} 訂單是否已創(chuàng)建 
  33.        */ 
  34.       orderIsCreated() { 
  35.         return eq(this.orderStatus, ORDER_STATUS.CREATED); 
  36.       }, 
  37.       /** 
  38.        * @func 
  39.        * @name orderIsArrearage 
  40.        * @desc 判斷訂單是否未付款的狀態(tài) 
  41.        * @returns {string} 訂單是否未付款 
  42.        */ 
  43.       orderIsArrearage() { 
  44.         return eq(this.orderStatus, ORDER_STATUS.ARREARAGE); 
  45.       }, 
  46.       /** 
  47.        * @func 
  48.        * @name orderIsPurchased 
  49.        * @desc 判斷訂單是否已購(gòu)買的狀態(tài) 
  50.        * @returns {string} 訂單是否已購(gòu)買 
  51.        */ 
  52.       orderIsPurchased() { 
  53.         return eq(this.orderStatus, ORDER_STATUS.PURCHASED); 
  54.       }, 
  55.       /** 
  56.        * @func 
  57.        * @name orderIsShipped 
  58.        * @desc 判斷訂單是否已發(fā)貨的狀態(tài) 
  59.        * @returns {string} 訂單是否已發(fā)貨 
  60.        */ 
  61.       orderIsShipped() { 
  62.         return eq(this.orderStatus, ORDER_STATUS.SHIPPED); 
  63.       }, 
  64.       /** 
  65.        * @func 
  66.        * @name orderIsCompleted 
  67.        * @desc 判斷訂單是否已完成的狀態(tài) 
  68.        * @returns {string} 訂單是否已完成 
  69.        */ 
  70.       orderIsCompleted() { 
  71.         return eq(this.orderStatus, ORDER_STATUS.COMPLETED); 
  72.       }, 
  73.     }, 
  74.     data() { 
  75.       return { 
  76.         orderStatus: ORDER_STATUS.INIT // 訂單狀態(tài) 
  77.       } 
  78.     }, 
  79.     methods: { 
  80.       /** 
  81.        * @func 
  82.        * @name getOrderStatus 
  83.        * @desc 判斷訂單狀態(tài) 
  84.        * @returns {string} 返回當(dāng)前訂單狀態(tài) 
  85.        */ 
  86.       async getOrderStatus() {} 
  87.     }, 
  88.     async created() { 
  89.       this.orderStatus = await this.getOrderStatus(); 
  90.     } 
  91.   } 
  92. </script> 

將頁(yè)面組件按狀態(tài)劃分,實(shí)現(xiàn)獨(dú)立自治,這樣子既能防止代碼耦合,方便維護(hù) debug,也方便開(kāi)發(fā)者自測(cè),如果需要看不同狀態(tài)的展示效果,只要手動(dòng)給 orderStatus 賦值即可,方便快捷。

面向切面

按照維基百科的解釋:面向切面的程序設(shè)計(jì)(Aspect-oriented programming,AOP,又譯作面向方面的程序設(shè)計(jì)、剖面導(dǎo)向程序設(shè)計(jì))是計(jì)算機(jī)科學(xué)中的一種程序設(shè)計(jì)思想,旨在將橫切關(guān)注點(diǎn)與業(yè)務(wù)主體進(jìn)行進(jìn)一步分離,以提高程序代碼的模塊化程度。

上面這段文字估計(jì)沒(méi)有什么人看,算了,直接上代碼吧

[[375840]]

我們看回上面打工人的場(chǎng)景,假定老板想要知道打工人每個(gè)狀態(tài)開(kāi)始前跟結(jié)束前的時(shí)間以及做點(diǎn)什么,那么該怎么做呢?這個(gè)時(shí)候我們不難想到可以直接往狀態(tài)函數(shù)里寫(xiě)代碼,例如:

  1. const 打工人 = { 
  2.   起床() { 
  3.     老板.start(); 
  4.     打工人.do(); 
  5.     老板.end(); 
  6.   }, 
  7.   上班() { 
  8.     老板.start(); 
  9.     打工人.do(); 
  10.     老板.end(); 
  11.   }, 
  12.   加班() { 
  13.     老板.start(); 
  14.     打工人.do(); 
  15.     老板.end(); 
  16.   }, 
  17.   下班() { 
  18.     老板.start(); 
  19.     打工人.do(); 
  20.     老板.end(); 
  21.   } 
  22. }; 
  23. // 早上6點(diǎn) 
  24. 打工人.起床(); 
  25. // 早上9點(diǎn) 
  26. 打工人.上班(); 
  27. // 晚上6點(diǎn) 
  28. 打工人.加班(); 
  29. // 晚上12點(diǎn) 
  30. 打工人.下班(); 

但是這樣打工人一下子就察覺(jué)到到了老板在監(jiān)控他的生活,如果要做到不被人察覺(jué)(不影響業(yè)務(wù)邏輯),那我們既可以采用 AOP 的實(shí)現(xiàn)方式。代碼如下:

  1. import eq from 'lodash'; 
  2. const TYPES = { 
  3.   FUNCTION: 'function' 
  4. const 老板監(jiān)控中的打工人 = new Proxy(打工人, { 
  5.     get(target, key, value, receiver) { 
  6.         console.log('老板開(kāi)始看你了~'); 
  7.        const res = Reflect.get(target, key, value, receiver); 
  8.        const 打工人任務(wù) = eq(typeof res, TYPES.FUNCTION) ? res() : res; 
  9.         console.log('老板開(kāi)始記你小本本了~'); 
  10.         return () => 打工人任務(wù); 
  11.     } 
  12. }); 

所以我們可以看到以下結(jié)果:

這樣子,我們就可以輕松簡(jiǎn)單地監(jiān)控到了打工人每天干的活,而且還不讓打工人發(fā)現(xiàn),簡(jiǎn)直是資本家聽(tīng)了都流淚呀。

 

責(zé)任編輯:趙寧寧 來(lái)源: 魚(yú)頭的Web海洋
相關(guān)推薦

2021-09-22 11:05:19

JS代碼前端

2024-06-13 12:24:06

C++開(kāi)發(fā)代碼

2022-09-19 15:02:24

C語(yǔ)言

2023-01-27 14:53:03

2015-12-02 09:37:24

數(shù)據(jù)中心數(shù)據(jù)中心優(yōu)化

2018-03-30 10:02:08

代碼規(guī)范維護(hù)工程師

2021-08-16 12:13:02

SwiftUIList ArticleList

2025-03-11 08:30:00

Pythonretrying代碼

2023-11-18 09:07:59

Go語(yǔ)言技巧

2013-11-29 16:54:27

Windows 8制造業(yè)智能化

2014-08-01 09:50:39

Oracle營(yíng)銷云Oracle Eloq

2023-10-07 14:49:45

2022-03-08 06:41:35

css代碼

2020-04-03 14:55:39

Python 代碼編程

2018-02-05 00:01:41

2019-07-19 08:38:55

物聯(lián)網(wǎng)智慧城市智能照明

2011-01-25 22:13:29

云計(jì)算防災(zāi)

2024-11-15 07:20:00

應(yīng)用程序編程C#

2024-02-07 01:47:47

atexit模塊程序

2024-04-26 11:54:10

Pygments代碼Pytho
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)