記一次前端項目重構要點總結

不知不覺已是2019年的7月,恍惚之間已工作四年。懵懵懂懂的成長,間歇性努力,實話說,對現在自己取得的成果不大滿意。不過,好在時不時頓悟,知道適時作出改變。

此後發文會適當記錄一些心路歷程,與君共勉。

歡迎Star和訂閱我的博客

本文要點:

  1. 什麼項目,爲何會重構?
  2. 怎麼重構的?
  3. 重構前後對比

什麼項目,爲何會重構?

項目是公司主打業務產品之一的可視化子項目,與其他子項目幾乎沒有耦合,所以可以單獨拎出來重構。

具體業務不作描述。技術主要用的是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, MapIf的使用簡單粗暴,容易理解。

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和訂閱我的原創前端技術博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章