一些提高開發效率的小體會

無責任此方_修行中發表於2019-04-22

最近在工作中遇到了比較緊急的專案,短時間以及不能再刪減(甚至還可能會變)的需求就意味著要儘可能地提升開發效率。前端因為與互動相關,因此會受到大部分需求變更的影響。如何儘可能地減少因需求變更而產生的工作量,一直以來都困擾著前端開發人員。

由於自己平時的程式碼風格還不夠規範以及知識領悟不深,自然我也沒少受苦,但也因此對提高開發效率方面有了一些體會。本文便是總結與覆盤,用於日後提醒自己。

如何提高效率

對於我們做開發的同學來說,提高工作效率最有效的方法就是降低 BUG 率;而降低 BUG 率最有效的方法就是減少程式碼量。還記得 GitHub 上之前大火的專案 No Code 嗎?資深的谷歌工程師告訴我們,一行程式碼都沒有的程式是最安全的穩定的。

其次如果程式碼擴充性足夠強,那麼在面對需求變更時的工作量就會相對減少(作為前端,不變更時不存在的)。而增強程式碼擴充性比較常用的方法就是通用元件的封裝與抽象。

下面就是有關於這兩部分的一些總結和思考。

降低 BUG 的方法

良好的程式碼風格應該是降低 BUG 最有效的方法,可以參考《程式碼整潔之道》一書。下面的一些方法是我在平時工作中所總結出來的幾點。

1. 減少程式碼量

程式碼量越少也就越難出現 BUG。在平時的工作中,應該儘可能地減少編寫的程式碼量。在前端中,最簡單的就是儘量使用 ES6 語法。相比 ES5,通過 ES6 的解構、箭頭函式、async/await 可以減少 30% 以上的程式碼量。在有大量(3 個以上)的 if 判斷時,可以使用物件的形式。

// 常規賦值操作
let a = 1
let b = 2
let c = 3
// 使用解構賦值
let [a,b,c] = [1,2,3]

// 使用 if
if(a === '1'){
  ....
}else if(a === '2'){
  ...
}else if(a === '3'){
  ....
}
...

// 使用物件進行分類處理, 邏輯上會更簡潔一點
// PS:這個方法在 React 進行元件渲染的時候非常有用
const handleAction = (act) => {
  const actions = {
    '1': action1,
    '2': action2,
    '3': action3
  }
  const action = actions[act]
  action()
}
// 根據情況進行處理
handleAction('1')
複製程式碼

在 React 的專案中,如果使用了 Redux。那麼應該儘可能地使用 function 元件來減少程式碼。同時這麼做也可以讓我們在進行 UI 移植的時候省下很多改動(最近有一個專案是部分功能的遷移,Redux -> dva 在移植 function 元件時幾乎沒有什麼改動),而且現在有了 Hook,function 元件中不能控制 state 的問題也能解決。

2. 設定預設值

缺少預設值非常容易造成 BUG,這是之前一個專案中血和淚的教訓。特別是 React 專案中使用了上面介紹的物件的方法進行元件切換時,如果沒有設定預設值就會直接造成頁面崩潰。

class A extends React.Component {
  const Components = {
    // 特別是根據 Response 來進行元件切換時,應該設定 default 防止意外情況
    A: Component1,
    B: Component2,
    C: Component3,
    'default': () => <div />
  }

  render(){
    const {render} = this.state
    // 如果沒有預設值,一旦物件匹配不到,頁面直接崩潰
    const RenderComponent = Components[render] || Components.default
    return (
      <RenderComponent />
    )
  }
}
複製程式碼

其次函式引數的預設值除了能減少 BUG 外也能幫助減少程式碼量。對於使用次數較多的方法,直接設定預設值可以讓我們在呼叫時省去引數的傳入。

// 當 0.0.0.1 和 api service 方法較多時,設為預設引數可以減少引數的傳入
function customizeFetch(service='api', base = '0.0.0.1'){
  ...
}

customizeFetch()
複製程式碼

3. 拆分函式與抽象方法

說到拆分函式,用的最多的應該是 request 的應用部分。比如對 fetch 的封裝。

// 封裝好的 fetch (有柯里化的影子在)
function customizeFetch(server = "api", base = "0.0.0.1") {
  return function(api = "", options = {}, withAuth = false) {
    const url = `${base}/${server}/${api}`;
    const opts = {
      method: options.method || "POST",
      headers: {
        // 可以設定預設引數,比如頭什麼的
        ...options.headers
      },
      body: {
        ...options.body
      }
    };

    return fetch(url, opts).then(response => response.json());
  };
}

// 當我們進行呼叫時,對於業務來說寫起來基本一致
// 由於使用透傳,其實在 service 還能偷懶寫成一個方法
// 產品列表
const fetchAPI = customizeFetch("api1");
const getProductList = opts => {
  const options = {
    body: { ...opts }
  };
  return fetchAPI("getProductList", options);
};

// 新聞列表
const fetchAPI = customizeFetch("api2);
const getNewsList = opts => {
  const options = {
    body: { ...opts }
  };
  return fetchAPI("getNewsList", options);
};
複製程式碼

4. 強型別和強檢查

eslint 的好處就不用提了吧?再配合 prettier 可以讓程式碼格式統一(umilint 雖然在不習慣時會覺得很煩,但是一旦習慣後對程式碼風格的提升還是很有幫助的)。如果再用上 TypeScript 更是可以讓我們在編碼時檢查到錯誤。TypeScript 雖然在剛開始使用時很不習慣,特別是對於型別的強要求(全部 any 的話等於沒有型別)很頭痛。不過適應之後就能體會到 TypeScript 帶來的快感了。

在引入 TypeScirpt 之後,最容易出現的 xxx from undefined 錯誤就能完全避免。可以幫助我們節省下許多除錯的時間。

應對需求變更

前端的元件化開發,在更多的程度上是為了應對需求的變更(個人認為)。而由於前端是最接近使用者的,因此只要需求有變是逃不過要進行一番修改的。因此讓修改的工作量減少以及減少因修改帶來的 BUG,也是提高效率的方法。

1. 提升副作用,儘量使用 Stateless 元件

對於 React/Vue 專案,只要使用了 Redux/Vuex 這類狀態管理工具,我們就能很容易地把元件做成不依賴於 statestateless 元件。這類元件很“純”基本只依賴於傳入的 props,即便有 state 也是屬於自治範圍,不會參與業務邏輯計算。這麼一來就能儘可能地讓 UI 層更加純淨,職責更單一。(當然這只是一種美好的願望,實際上根據副作用切換元件狀態或者其他業務邏輯操作還是會讓業務邏輯下沉到 UI 層去)

讓 UI 層儘可能地變得簡單,而處理業務邏輯的部分就應該轉移到 Redux 的 action 的部分中。Reducer 的部分也應該儘量純淨,不做業務處理。這樣如果當需求有變化的時候,修改的部分就能儘可能地被縮小在 action 部分,同時在做專案移植時也會比較方便(基本 action 層很大可能會重寫)。當然實際中並不可能剝離得非常乾淨,UI 層往往也會跟著一起變動,不過還是可以減少修改的範圍。

2. 通用業務元件的封裝與抽象

另一個就是根據專案需求提煉出通用的業務元件,比如簡訊驗證碼、可編輯 label 的表單控制元件、許可權驗證元件、搜尋元件等。這類元件基本與業務相關,基本是某個元件庫的再封裝(比如 antd),這個也是現在許多同學平時會做的。這樣在某一個業務中可以減少我們的開發量。具體的可以使用 HOC 等方法來進行封裝和抽象(比如許可權驗證元件)。

提煉元件固然不錯,但是也要避免過度封裝。曾經在寫 Vue 的時候封裝了一個可配置的表單元件,結果當業務需要兩個表單控制元件的互相控制以及按鈕狀態控制時就傻眼了。因此在設計封裝元件時也要考慮到之後業務的變化。

以上便是最近這段時間的一些工作感悟,算是作為自己的一個備忘。程式設計原本的目的就是提高做事的效率,而提高開發的效率又是每一個程式設計師都要面臨的難題。所以程式設計是一件十分有意思的事情,其中一點就是可以不斷地挑戰和提升自己。

相關文章