不知不覺已是2019年的7月,恍惚之間已工作四年。懵懵懂懂的成長,間歇性努力,實話說,對現在自己取得的成果不大滿意。不過,好在時不時頓悟,知道適時作出改變。
此後發文會適當記錄一些心路歷程,與君共勉。
歡迎Star和訂閱我的博客。
本文要點:
- 什麼項目,爲何會重構?
- 怎麼重構的?
- 重構前後對比
什麼項目,爲何會重構?
項目是公司主打業務產品之一的可視化子項目,與其他子項目幾乎沒有耦合,所以可以單獨拎出來重構。
具體業務不作描述。技術主要用的是Vue2系列和JavaScript,還有一個自研的可視化工具庫。第一個重構原因就是沒有引入靜態類型,導致查看一個對象結構需要翻來覆去在多個文件中查找。第二是因爲之前新增代碼模式一般爲:“來一個需求加一段代碼”,長期積累導致代碼結構混亂,可讀性差。第三是各個狀態模塊耦合度高,加大了代碼維護難度。
怎麼重構的?
一、在JavaScript中使用TypeScript。“什麼?在JS中使用TS? 聞所未聞。 ” 在看到TS官網手冊最後一條"Type Checking JavaScript File"之前,我也這樣想。其實,TS和VSCode(一款IDE)結合,也可以實現靜態類型檢測,只不過使用註釋形式,一樣支持tsconfig.json
和自定義Typing。
type TypeApple = { name: string, count: number }
/** @type {TypeApple} */
const apple = { name: 'foo', count: 100 }
二、細化模塊分類。一般情況下,模塊都會有耦合。但如果耦合度過高,往往是因爲模塊沒有細分到位。如果細化模塊?舉例,假如有一個模塊叫Operation
,裏面既包含操作相關邏輯,也有操作面板邏輯。隨着業務發展,操作面板邏輯越來越多。我們完全可以將操作面板邏輯單獨抽成一個模塊OperationPanel
。
三、解耦可視化庫和Vue/Vuex。寫業務的時候,很容易因爲方便,在Vue組件或Vuex模塊中代碼越寫越長,越來越難維護。這個項目也不列外。所以重構的時候,單獨將可視化庫喜愛那個管邏輯抽成模塊,並使用類Vuex寫法(state, getters, mutations, actions)進行管理。
class Counter {
// # state
/** @type {number} */
count = 0
// # getters
get countText() { return `Count is: ${ this.count }` }
// # mutations
/** @param {number} count*/
SET_COUNT = count => { this.count = count }
// # actions
/** @param {number} count*/
logCount = ( count ) => {
this.SET_COUNT( count )
console.log( this.countText )
}
}
四、最後一條,編寫可維護性高的代碼。這裏說兩個方法。
第一個是“使用Map
”。處理“一個有多類型的數據”需要使用判斷,常見有3種方法:If
, Switch
, Map
。If
的使用簡單粗暴,容易理解。
if ( animalType === 'dog' ) {
console.log( 'Wang!' )
} else if ( animalType === 'cat' ) {
console.log( 'Miao!' )
} else if ( animalType === 'bird' ) {
console.log( 'Jiu!' )
}
Switch
可以看做是If
的簡化。
switch ( animalType ) {
case 'dog':
console.log( 'Wang!' )
break
case 'cat':
console.log( 'Miao!' )
break
case 'bird':
console.log( 'Jiu!' )
break
}
而Map
針對性最強,並且最簡潔、最易於維護。
const logMap = {
dog: () => console.log( 'Wang!' ),
cat: () => console.log( 'Miao!' ),
bird: () => console.log( 'Jiu!' ),
}
logMap[ animalType ]()
具體使用也哪一種因場景而異,但多數場景下,使用Map
可讀性更強。
第二個是“使用getters和mutations”。比如定義一個模塊的`:
operationGetters.js`, 裏面提供各種用來獲取與操作有關的常量和方法。
export const OPERATION_TYPE_A = 0
export const OPERATION_TYPE_B = 1
export const OPERATION_TITLE_MAP = {
[ OPERATION_TYPE_A ]: 'Title A',
[ OPERATION_TYPE_B ]: 'Title B',
}
export const getOperationTitleByType = type => OPERATION_TITLE_MAP[ type ]
定義mutations
則是定義一個提供相關各種變更數據方法的文件。在維護代碼的時候,查找變更方法名即可直接找到更改數據的出處。
export const SET_OPERATION_TITLE = ( operation, title ) => { operation.title = title }
重構前後對比
代碼量減少了快一半,性能顯著提升,最重要的是代碼可讀性、可維護性大大增強,從而淡定從容應對之後的新需求。
感謝你花時間閱讀這篇文章。如果你喜歡這篇文章,歡迎點贊、收藏和分享,讓更多的人看到這篇文章,這也是對我最大的鼓勵和支持!
歡迎Star和訂閱我的原創前端技術博客。