關於重構問題——編寫可維護性高的代碼

1、使用TypeScript:html

背景:前端

RollBar是一個網頁檢測的網站,該網站統計了2018年前端項目拋出異常的種類,其中有七種是type error,即類型錯誤。異常最多的類型是讀取了undefined變量的屬性node

而這個問題能夠經過TS定義嚴格的數據類型解決:webpack

type TypeApple = { name: string, count: number }
/** @type {TypeApple} */ const apple = { name: 'foo', count: 100 }

TS和VSCode(一款IDE)結合,也能夠實現靜態類型檢測,只不過使用註釋形式,同樣支持tsconfig.json和自定義Typing。git

如何使用TS:github

npm install –g typescript
tsc –v

1.新建 .ts 後綴的文件 —— 2.編寫知足 ts 風格的代碼——3.使用tsc編譯ts文件(最後獲得的仍是js文件)web

TS主要語法:typescript

1.類型系統:npm

2.接口編程

 在TypeScript中,接口的做用是對值所擁有的結構進行類型檢查,接口是一種結構約束。同時提供了一種方式去抽象代碼。

3.類

js自己並非一種OOP(面向對象編程)的語言,並無類這樣一個概念。JS的對象使用原型鏈進行繼承和擴展。ES6中提供的Class關鍵字只是一個語法糖,讓你用面向對象的方式編寫類,底層仍是原型鏈的連接。

繼承,以某個類爲父類,繼承全部的屬性和方法,同時能夠進行擴展和重寫方法:

a.protected 在類自身的內部能夠訪問,子類能夠訪問,外部沒法訪問;

b.private 僅可在類自身的內部進行訪問,子類沒法訪問,外部沒法訪問。

抽象類。抽象類沒法實例化,只能做爲其餘類的基類。不一樣於接口,抽象類能夠描述類的實現細節。抽象方法在派生類中必須實現。

4.函數:

TS函數參數和返回值的類型指定以及函數重載。

指定了函數的參數類型和返回結果,函數的功能就比較特定了。可是js畢竟是動態類型的函數,js內根據參數類型不一樣返回不一樣的類型比較常見,因此ts提供函數重載功能

5.斷言:

注意事項:

1.文件聲明(開發環境對TS文件的支持):規定namespace+第三方庫+管理工具+聲明文件

2.項目工程化:

  a.使用webpack的文件變更檢測機制,自定義啓動腳本(當檢測到文件發生變化時從新編譯和運行入口js);

  b.使用ts-node和pm2,更改pm2的啓動配置,讓pm2使用ts-node直接運行ts的入口文件。

3.tsconfig.json相關:

  相似eslint,例如是否容許 使用 any 類型, 是否容許存在未使用的變量等等。

  https://www.tslang.cn/docs/handbook/compiler-options.html 

  https://www.tslang.cn/docs/handbook/error.html

2、細化模塊分類:

通常狀況下,模塊都會有耦合。但若是耦合度太高,每每是由於模塊沒有細分到位。若是細化模塊?舉例,假若有一個模塊叫Operation,裏面既包含操做相關邏輯,也有操做面板邏輯。隨着業務發展,操做面板邏輯愈來愈多。咱們徹底能夠將操做面板邏輯單獨抽成一個模塊OperationPanel

化繁爲簡:

//1.If的使用簡單粗暴,容易理解。

if ( animalType === 'dog' ) {
    console.log( 'Wang!' )
} else if ( animalType === 'cat' ) {
    console.log( 'Miao!' )
} else if ( animalType === 'bird' ) {
    console.log( 'Jiu!' )
}
//2.Switch能夠看作是If的簡化。

switch ( animalType ) {
    case 'dog':
      console.log( 'Wang!' )
      break
    case 'cat':
      console.log( 'Miao!' )
      break
    case 'bird':
      console.log( 'Jiu!' )
      break
}
//3.而Map針對性最強,而且最簡潔、最易於維護。

const logMap = {
    dog: () => console.log( 'Wang!' ),
    cat: () => console.log( 'Miao!' ),
    bird: () => console.log( 'Jiu!' ),
}
logMap[ animalType ]()

 

3、解耦可視化庫和Vue/Vuex:

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 )
  }
}

 

「使用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 }

-end-

相關文章
相關標籤/搜索