昨天把烤箱和工具都選定了,接下來,總算要真的開始動手做了。
老實說,我第一次真正打開 BuJo 的資料庫時,腦袋是一片糊塗的——user_id、@@unique、那些方框之間牽來牽去的線,看起來真的很像一串工程世界的摩斯密碼。
那時候的我只知道:
「資料要存進資料庫。」
但我完全不知道,資料要怎麼存,居然會直接影響一個功能以後改不改得動。
所以今天先不急著解那些符號,我想先從更前面開始:
資料模型,到底為什麼這麼重要?
我後來才慢慢搞懂,資料模型設計可以先從幾個最基礎的問題開始理解:
這個產品裡有哪些東西、它們彼此怎麼連在一起、每個東西要記住哪些資訊。
工程上,這些通常會先對應到幾個基本概念:
當然,真正的資料模型設計不只這些,後面還會牽涉到主鍵、外鍵、基數、約束、索引等規則。
但如果先翻成人話,其實就是在回答:
「我的產品世界裡有哪些角色?它們彼此是什麼關係?每個角色需要記住什麼?」
想像一個購物網站,一開始每項商品都只有一個價格和一個庫存數量。
後來想加入「同一件衣服可以選擇不同顏色和尺寸」,才發現這不只是商品頁多放兩個選單而已。系統還需要分別記錄「白色 S 號」「白色 M 號」「黑色 S 號」的價格、庫存與商品編號。
如果原本的資料結構只替每項商品留下一組價格和庫存,就沒有地方存放這些不同規格的資料,連帶也要調整購物車與訂單的記錄方式。
BuJo 也真實遇過這種情況:如果一開始活動時間只設計成一個欄位,後來想加「候選日投票」這種讓大家對多個日期投票決定的玩法,就完全沒有地方放,得回頭改整個結構。
應用程式裡寫的判斷式可以被繞過——多個入口、後台腳本、手動改資料庫,都可能讓某段判斷式沒被執行到。
但資料庫用 約束(Constraint) 寫下來的規則,不會被繞過。
同一個欄位名稱,在不同人腦袋裡可能對應到不同的意思——這個名字指的是「使用者看到的狀態」還是「系統內部判斷用的狀態」?
兩個人心裡想的不一樣,程式就會長歪。
Schema 命名的精確度,直接影響團隊溝通的精確度,而且它活得比任何一段程式碼都久。
BuJo 資料庫裡就有一組真實發生過的例子,往下看就知道代價有多具體。
我會把它想成——程式碼是液體,資料模型是水泥。
液體還沒乾之前,怎麼倒都可以重新來;水泥一旦乾了,上面又已經蓋了東西,要打掉重做,就是真正的工程。
所以資料模型不是不能改,而是:
有些結構一旦改錯,後面的修改成本會非常高。
這件事重要到,值得接下來整段拆開來講。
聽起來資料模型設計好像動不得,但實際上,開發過程中會不斷修改資料模型,是完全正常的事,不是規劃沒做好。
真正的關鍵是:
修改分成兩種等級,成本差了好幾個量級。
隨時可做,幾乎沒有風險,因為它不會動到任何已經存在的東西。
真的要動手做,業界標準做法是 expand → migrate → contract 三階段:先加上新結構讓新舊並存,兩邊同時寫入、把舊資料回填過去,確認一切正常之後,才移除舊結構——這是好幾天的工,不是改一行就結束。
真正專業的做法,不是「一次設計到位、永遠不用改」——那不可能,需求本來就會一路長出來。
而是:
把前期思考的力氣,押在「一旦錯了會很貴」的那幾件事上,其餘的允許自己邊做邊加。
| 一旦錯了會很貴的決策 | 為什麼貴 |
|---|---|
| 核心實體有哪些 | 拆錯要重寫大半系統 |
| 關聯基數(1:1/1:N/M:N) | 從 1:N 改成 M:N 要建中介表、搬資料 |
| 狀態機:有哪些狀態、哪些轉換合法 | 狀態定義錯會污染所有既有資料 |
| 唯一性約束(誰跟誰組合起來只能有一筆) | 補加時可能已經有髒資料,無法建立 |
| 硬刪還是軟刪 | 資料刪掉就真的沒了 |
反過來,大部分一般欄位、顯示用的資訊、非關鍵的預設值、索引怎麼調——這些都便宜、可以晚點再決定,不用逼自己一開始就想到完美。
還有一條分水嶺,常常被低估:
本機開發、還沒有真實使用者資料的時候,其實是最適合大膽改結構的階段。
這時候砍掉重建,成本可能只是幾分鐘。
但一旦正式上線、有真實資料進來,每一次結構修改,就會開始多一層風險。
而且就算還沒上線,只要是團隊開發,改 Schema 也不只是自己的事。
你改一個欄位名稱,隊友手上的功能可能瞬間一起壞掉;改一個欄位型別,也可能牽動十幾個檔案一起調整。
所以後來我才知道,這種修改除了技術本身,還有一個很現實的成本:
要讓所有正在依賴這份資料結構的人知道。
這也是為什麼團隊裡會需要把 Schema 修改集中處理、獨立一個 PR、改完立刻同步。
而接下來 BuJo 真的就發生過一個「大家看著同一組欄位,理解卻完全不一樣」的問題。
BuJo 有四種排程情境,都會用到 deadline_at 和 vote_deadline_at。
我一直以為它們的意思很清楚:
vote_deadline_at:報名截止時間deadline_at:活動自動取消時間但我們當時只有口頭討論過,沒有真的把欄位語意定義清楚。
後來不同情境由不同夥伴接手時,兩邊竟然把這兩個欄位理解成相反的意思。
最後是操作畫面時才發現:
「咦?明明都顯示揪團中,為什麼有些活動可以報名,有些報名按鈕卻按不下去?」
一路往回查,才發現真正的問題不是前端按鈕,而是:
同一組欄位,在不同情境裡被解讀成了不同的意思。
回頭看,這個問題其實可以從三個地方提早避免:
deadline_at 留太多解讀空間vote_deadline_at 必須早於 deadline_at
這也是我第一次很具體地感受到:
資料模型不只是拿來存資料,它也是團隊共同理解產品規則的一部分。
那麼今天的主題——資料模型設計,在 Vibe Coding 和專業開發上的差異在哪呢?
AI 讓「生出一組 Schema」這件事變得超級容易。
跟 AI 說:
「幫我做一個排程 App 的資料表!」
幾秒後,就可能拿到一組命名整齊、型別完整、還順手幫你補上建立時間和更新時間的 Schema。
而且它看起來通常真的很合理。
真正容易漏掉的,不是格式,而是那些只有產品本身才知道的問題:
哪些關係不能被破壞?
哪些欄位的意思不能模糊?
哪些決定現在看起來很小,以後改起來卻會很貴?
所以差異更像是:
AI 可以把 Schema 寫得很快。
但哪些規則值得被寫進 Schema,本身還是產品和工程判斷。
回頭看這一關,我現在最有感的是:資料模型設計,其實是在替未來的自己留下選擇空間。
以前我會覺得,只要資料存得進去、功能跑得動就好。
現在看到一個欄位或一段關聯,我會多問兩句:
「這個決定如果錯了,以後改起來會不會很貴?」
「這個名字,團隊每個人理解的是不是同一件事?」
光是開始會問這兩個問題,對我來說就已經是很大的差別。
原則先走到這裡。
明天,就把實體、主鍵、外鍵、基數、約束這些當初讓我一頭霧水的摩斯密碼,一個一個拆開來看。
那些讓我當初看不懂的符號,該開始解密了。
iThome鐵人賽