PawPal 的醫院卡片旁邊有一顆愛心。
使用者點一下可以收藏,再點一次可以取消收藏。
從畫面上看,好像只是:
空心愛心
↓
實心愛心
但真正開始整理這個需求後,我才發現,一顆收藏按鈕背後其實還牽涉到:
資料怎麼存
登入身分
後端 API
前端狀態
錯誤處理
驗收條件
而其中最讓我卡住的問題是:
收藏資料到底應該怎麼存?
這次我負責的重點,不是把整套收藏功能從資料庫一路寫到前端。
而是先把這個看起來很簡單的需求拆清楚,再整理成 GitHub Issue,讓團隊後續可以實作與驗收。
剛開始想收藏功能時,我第一個問題是:
收藏資料表到底需要哪些欄位?
最直覺可能會想到:
使用者 ID
醫院 ID
醫院名稱
醫院地址
醫院電話
收藏時間
但醫院名稱、地址、電話本來就已經存在醫院資料裡。
如果收藏表又全部存一次,不只資料重複,未來醫院資訊修改時,也可能出現兩邊不一致的問題。
當時我還不太清楚資料表之間應該怎麼分工,所以先和 AI 一起討論:
哪些資料原本就已經存在?
收藏功能真正需要另外記住的是什麼?
慢慢整理後,我才理解:
收藏表真正要記錄的,是「哪一個會員收藏了哪一間醫院」。
而不是再存一份完整的醫院資料。
團隊後續建立的 hospital_favorites,主要概念可以理解成:
user_id
+
hospital_id
也就是:
會員 A
↓
收藏
↓
醫院 B
例如:
user_id: 10
hospital_id: 25
代表 ID 10 的會員收藏了 ID 25 的醫院。
另外,同一位會員也不應該重複收藏同一間醫院,所以資料表加入:
UNIQUE (user_id, hospital_id)
這個限制的意思就是:
同一位會員不能重複收藏同一間醫院。
這次我第一次比較明確地理解:
關聯表不一定要保存畫面需要的所有資料,它可以只負責記錄兩份資料之間的關係。
理解資料關係後,我開始整理 GitHub Issue。
當時我不是只寫:
新增收藏功能。
而是開始往下拆:
收藏資料怎麼存?
未登入能不能收藏?
怎麼知道是哪個會員?
同一間醫院能不能收藏兩次?
收藏失敗時畫面怎麼辦?
取消收藏後畫面怎麼更新?
沒有任何收藏時要顯示什麼?
手機、平板、電腦要怎麼呈現?
這也是我第一次發現:
需求拆解本身,也是開發的一部分。
如果 Issue 只寫「做一個收藏按鈕」,真正開始實作的人還是會遇到一大堆沒有定義的問題。
所以一張 Issue,不只是記錄:
我要做什麼?
也要慢慢整理成:
要做到什麼程度,才算真的完成?
資料表只是其中一層。
收藏是會員自己的資料,所以後端還要知道:
現在登入的人到底是誰?
PawPal 後續的收藏與取消收藏,會透過 API 處理。
概念上像:
點擊收藏
↓
後端確認登入身分
↓
取得目前會員
↓
建立會員與醫院的收藏關係
前端不是自己送一個:
user_id
然後告訴後端:
我要替這個會員收藏。
而是由後端根據驗證過的登入身分,判斷目前是哪一位使用者。
這讓我更清楚:
收藏不只有「哪間醫院」,還一定包含「是誰收藏的」。
如果收藏按鈕只是:
點一下
↓
直接變成實心
畫面當然看起來正常。
但如果後端其實收藏失敗:
畫面顯示已收藏
↓
資料庫卻沒有收藏
前端和真實資料就不同步了。
PawPal 後續的做法,是讓收藏操作經過 API 確認,再同步前端狀態。
概念上:
點擊愛心
↓
呼叫 API
↓
等待結果
↓
成功
↓
更新畫面
而且 API 還在處理時,也要避免使用者快速連點造成重複 Request。
所以一顆小小的愛心,其實還要考慮:
處理中狀態
按鈕是否能再次點擊
API 成功或失敗
畫面狀態同步
這些都是我一開始只看 UI 時沒有想到的事情。
除了單一醫院卡片上的愛心,我當時整理的需求還包含:
只顯示目前會員收藏的醫院。
一開始很容易以為,只要前端把收藏的醫院篩選出來就好。
但真正串起來後,收藏清單還需要知道:
目前登入的是誰
↓
他收藏了哪些醫院
↓
後端回傳資料
↓
前端呈現收藏狀態
後端也會提供「目前登入會員是否已收藏這間醫院」的狀態,讓前端知道愛心應該顯示成空心還是實心。
這讓我更清楚看到:
使用者最後看到的一顆愛心,其實是整條資料流最後呈現出來的結果。
回頭看這張收藏功能的 Issue,我覺得這次最大的學習,不是某一段程式怎麼寫。
因為整套收藏功能最後是團隊一起完成的。
我這次真正負責的重要部分,是先把一個原本看起來只有:
加一顆收藏按鈕。
的需求拆開。
最後才發現它其實包含:
前端互動
↓
登入身分
↓
會員與醫院的關係
↓
資料庫
↓
API
↓
狀態同步
↓
錯誤處理
↓
驗收
以前我可能會比較快開始想:
畫面要怎麼做?
但這次之後,我開始會先問:
資料從哪裡來?
誰可以操作?
資料要存在哪?
失敗會怎樣?
畫面怎麼知道結果?
最後怎麼確認功能真的完成?
這些問題,反而比一開始就急著寫程式更重要。
如果現在再遇到類似功能,我會更早先整理:
使用者情境
↓
資料關係
↓
API
↓
成功與失敗狀態
↓
前端互動
↓
驗收條件
同時把未登入、重複操作、API 失敗、空狀態等例外情況一起想進去。
而不是只想到:
收藏成功時要變成實心愛心。
這也是 PawPal 讓我開始改變的一個地方。
我慢慢發現:
做功能,不只是把畫面做出來。
還要先把這個功能背後真正需要解決的問題想清楚。
使用者最後看到的,只是一顆愛心。
但這次讓我第一次比較完整地看到,一個功能從需求、資料關係、登入身分、API,一路走到前端畫面與驗收。
我也開始理解:
團隊開發裡的「做功能」,不一定只有寫程式。把問題定義清楚、把需求拆清楚,也同樣是開發的一部分。
一顆收藏按鈕背後,有很多資料與狀態需要處理。
而下一個功能看起來也很簡單:
換一張頭像。
但真的做下去後,我才發現,一張圖片從選擇、裁切、預覽到真正上傳,中間其實還有不少事情。
下一篇:
Day 19|換一張頭像,原來不是只把照片傳上去