從資料庫到前端,使用 enum 代替 constant number

shanyue發表於2019-05-07

在我經歷過的幾個以node為主的後端專案中,都有一個檔案 constant.js。顧名思義,裡邊儲存著各種常量,而大多是字串與數字的對應關係。

但是在實際工作中,根據數字來除錯相當費勁,先不說後端程式碼中 where (status === 1) 這種可避免的神奇操作。(PS: 雖然我在吐槽它,但是有時我也會犯,給後來不熟悉業務者一臉懵逼...)。在資料庫中查詢也會遇到一些問題。

記得在我們資料庫中,有一個使用者表,其中一個欄位 user_type 中 1和2代表學生和老師,剛開始還可以輕易分清,後來文件對列的註釋給搞反了,自此每次查詢之前我都需要先查一遍資料庫的註釋,試想一下如果此時它是一個 enum('STUDENT', 'TEACHER') 的值,則可以輕易分清了,不需要再記各種數字了

以下以一個 TODO 的三種狀態 TODODONE 以及 DOING 來描述下資料庫,後端和前端如何傳輸以及展示

本文地址 shanyue.tech/post/consta…

使用數字

在資料庫中使用數字來表示狀態,有可能是 Base 1 的 123,也有可能是 Base 0 的 012。不過最重要的是要記得在資料庫中對列新增註釋

-- mysql 可以直接註釋
create table todo (
  status smallint default 1 comment "1: TODO, 2: DOING, 3: DONE";
)

-- postgres 在 comment 中進行註釋
create table todo (
  status smallint default 1;
)
comment on column todo.status is '1: TODO, 2: DOING, 3: DONE';
複製程式碼

在後端為了篩選條件下避免以下情況的出現,需要維護一個 constant 的變數

const where = {
  // 為了避免直接出現 1
  Status: 1
}
複製程式碼

使用 Status 來維護一個常量,response 代表返給前端的資料

const Status = {
  TODO: 1,
  DOING: 2,
  DONE: 3
}

const where = {
  Status: Status.TODO
}

const response = [{
  status: Status.TODO
}]
複製程式碼

在前端維護一個數字至中文展示的對映

const status_show = {
  1: '待辦',
  2: '進行中',
  3: '已完成'
}

const url = '/api/todos?status=1'
複製程式碼

但在這種情況下,在進行介面聯調時仍會是 1/2/3,不便於除錯

使用 enum

在 postgres 中新增 todos_status 的 type

create type todo_status as enum ('UNDO', 'DOING', 'DONE');

create table todo (
  status todo_status default 'UNDO',
);
複製程式碼

在後端可以直接在篩選條件中使用字串

const where = {
  Status: 'TODO'
}
複製程式碼

如果為了避免使用字串打錯了字元,可以使用 typescript 的 const enum 在編譯器發現問題

const enum Status {
    TODO = 'TODO',
    DOING = 'DOING',
    DONE = 'DONE'
}

const where = {
  Status: Status.TODO
}
複製程式碼

編譯之後的 javascript 程式碼如下

var where = {
    Status: "TODO" /* TODO */
};
複製程式碼

在前端維護一個常量至中文展示的對映,可以看出請求的 url 對於除錯與可讀性已經很友好了

const status_show = {
  TODO: '待辦',
  DOING: '進行中',
  DONE: '已完成'
}

const url = '/api/todos?status=TODO'
複製程式碼

使用 graphql

資料庫依然使用 enum 來表示 TODO 的狀態

在 graphql 中,使用以下 Schema 表示 TODO,TodoStatus 以及查詢列表的 query。TodoStatus 可以使用 enum 來表示

enum TodoStatus {
  DONE 
  DOING
  UNDO
}

type Todo {
  id: ID!
  status: TodoStatus!
}

type Query {
  todos (
    status: TodoStatus
  ): [Poem!]
}
複製程式碼

使用以下 query 篩選 todos

query TODOS ($status: TodoStatus) {
  todos (status: $status) {
    id
    status
  }
}
複製程式碼

相關文章