代碼質量第 2 層 - 可重用的代碼

點擊一鍵訂閱《雲薦大咖》專欄,獲取官方推薦精品內容,學技術不迷路!

可重用的代碼可以減少重複勞動。一個軟件中,會有很多類似的業務場景。將這些場景抽象成可重用的代碼。開發新功能時,重用代碼可減少重複勞動。

可重用的代碼可以減少因需求變動,導致多次改動和漏改的情況。試想,要修改全站提交按鈕的顏色,如果全站有100個包含提交按鈕的頁面,每個頁面的按鈕的樣式都沒複用,這改動量和漏改的風險都很大。如果做成可重用的,則只需改動一處。

如何寫出可重用的代碼?

代碼塊的職責越多,越難被複用。寫出可重用的代碼就是:識別,分離出可複用的部分。

考慮這樣的場景:代碼塊A 的功能是獲取接口數據,並渲染 UI。代碼塊B 的 UI 和 A 一樣,但獲取的接口數據不一樣。代碼塊C 獲取的數據和 A 一樣,但 UI 和 A 不一樣。A,B,C 之間的代碼都不能被複用。

要改成可複用的代碼,就是將可複用的 UI,獲取接口數據的代碼獨立出來。

下面,我們來看些常見的可複用的部分和複用方法。

一、UI 展示

UI 展示爲外觀的展示,包含:HTML 和 CSS。不包含數據的獲取和事件處理。

用組件可以實現 UI 展示代碼的複用。這樣的組件被稱爲展示組件。數據和事件處理通過屬性傳入。Ant Design 之類的組件庫裏的組件均爲展示組件。如下是 React 實現的新聞列表:

import React from 'react'
import s from './style.scss'
import Item, {IItem} from './item'

export interface INewsListProps {
  list: IItem[],
  onItemClick: (id: number) => void
}

const NewsList: FC<INewsListProps> = ({ list, onItemClick }) => {
  return (
    <div className={s.list}>
      {
        list.map(item => (
          <Item
            key={item.id}
            onClick={onItemClick}
            payload={item}
          />
        ))
      }
    </div>
  )
}

export default React.memo(NewsList)

二、接口調用

接口調用有兩部分可以複用:

  1. 接口請求和響應的通用處理。
  2. 具體接口的調用。

三、接口請求和響應的通用處理

接口調用時,常常要做一些通用的處理。比如:

  • 前後端分離的網站,要在接口的請求頭中要加 token 來標識用戶。
  • 接口報錯時,要將錯誤碼轉化成對用戶友好的錯誤信息。

axios 這麼處理:

// 請求攔截器
axios.interceptors.request.use(...)
// 響應攔截器
axios.interceptors.response.use(...)

四、具體接口的調用

接口調用代碼一般會放在一個文件中,如 service.js:

export const fetchList = ...
export const fetchDetail = ...
export const createItem = ...
export const updateItem = ...
export const deleteItem = ...

接口調用,還有 Loading 狀態管理,防抖,節流,錯誤重試,緩存等場景。React 可以用 useRequest,Vue 也有類似的輪子

五、業務流程

很多業務流程是類似的,可以被複用。比如,管理後臺列表頁的業務流程都類似是這樣的:

  1. 進入頁面時,獲取列表數據。
  2. 點搜索按鈕,根據當前的查詢條件,獲取列表數據。
  3. 點分頁,獲取指定頁的列表。

自定義 hooks(Vue3 中叫組合式 API) 支持內部的狀態管理和生命週期。因此,可以用 hooks 來封裝業務流程。下面是用 Vue3 的組合式 API 來封裝管理後臺的列表頁的實現:

import { onMounted, reactive, ref, Ref } from 'vue'
export interface Params {
  url: string
  searchConditions: Record<string, any>
}

interface Return<T> {
  searchConditions: Record<string, any>
  resetConditions: () => void
  pagination: Record<string, any>
  fetchList: (isReset: boolean) => void
  list: Ref<T[]>
  isLoading: Ref<boolean>
}

function useList<T extends Record<string, any>> ({
  url,
  searchConditions: initCondition
}: Params): Return<T> {
  const searchConditions = reactive({...initCondition})
  const pagination = reactive({
    pageSize: 10
  })
  const list = ref<T[]>([]) as Ref<T[]>
  const isLoading = ref(false) as Ref<boolean>
  // isReset 爲 true 表示搜第一頁。
  const fetchList = (isReset: boolean = false): void => ...

  // 進入頁面
  onMounted(() => {
    fetchList()
  })

  return {
    searchConditions,
    pagination,
    fetchList,
    list,
    isLoading,
  }
}

export default useList

推薦個 hooks 工具庫:ahooks。Vue 版:ahooks-vue

六、數據

有些數據指會被多個地方用到。如:登錄的用戶信息,權限數據。

可以用狀態管理庫來管理這些數據。React 狀態管理一般用 ReduxMobxContext API。 Vue 一般用 Vuex

七、工具函數

工具函數是與業務無關的。如:格式化日期,生成唯一的 id 等。Lodashmoment.js 包含了很多的工具方法。

總結

要寫出可重用的代碼,本質就是識別和分離出可複用的部分。前端可以從 UI 展示,接口調用,業務流程,數據,工具函數 中找出可複用的部分。

代碼質量的下一層次就是:可重構的代碼。我會在下一篇文章中介紹。

金偉強往期精彩文章推薦:

代碼質量第 3 層 - 可讀的代碼

代碼質量第 4 層 - 健壯的代碼

代碼質量第 5 層 - 只是實現了功能

聊聊代碼質量 - 《學得會,抄得走的提升前端代碼質量方法》前言

 

 

《雲薦大咖》是騰訊雲加社區精品內容專欄。雲薦官特邀行業佼者,聚焦於前沿技術的落地及理論實踐之上,持續爲您解讀雲時代熱點技術、探索行業發展新機。點擊一鍵訂閱,我們將爲你定期推送精品內容。

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