小晴 · 使用者
「我不在乎資料表,我只想知道十點有沒有設備。」
提醒我們:成果要回到使用情境。STORY LAB · 完整示範篇
跟著阿哲與 ChatGPT,從一句「做個借用系統」走到能被驗證的交付。
設備借用 × ASP.NET Core × PostgreSQL
圖解加長版 · 約 100–140 分鐘 · 先看完整故事,再獨立解題
每幕新增圖解或成果快照;讀完後勾選的是「能解釋」,不是「滑到底」。進度僅存在本次頁面,重新整理會重設。
已自我確認 0 / 12 幕
星期一,早上九點零五分。小晴抱著筆電站在器材室門口:「我十點要提案,昨天核准的投影機呢?」
管理員美玲翻開試算表,臉色變了一下。另一位同事阿凱也有一張核准單,設備編號一模一樣:P-001。
主管:「阿哲,你不是會用 AI?幫我們做個借用系統吧。可以申請、核准、歸還就好,很簡單。」
工程師阿哲打開 ChatGPT。他差點輸入「用 ASP.NET Core 和 PostgreSQL 做借用系統」,但停住了:畫面能跑,和公司不再把設備借兩次,是兩回事。
一份能追溯決策的 MVP 規格、一條「核准 → 領用 → 歸還」垂直切片設計、資料庫防線、測試計畫與上線檢查。故事中的成功不是「AI 寫了好多程式」,而是我們知道什麼已確認、什麼仍需驗證。
「我不在乎資料表,我只想知道十點有沒有設備。」
提醒我們:成果要回到使用情境。「系統說歸還,東西真的回來了嗎?」
提醒我們:系統狀態要對應現實。「先把規則說清楚,再讓 AI 幫忙實作。」
提醒我們:決策不能外包給猜測。事件現場|找出真正損失
訪談桌|核准的需求
設計室|狀態與不變條件
施工區|小而可驗證的切片
測試台|成功與失敗證據
交接處|可重現與可復原
讀法:第一遍跟著劇情走;第二遍只看每幕「成果快照」;第三遍遮住解析,把自己的決策說出來。看懂是起點,能解釋反例才是更有力的吸收證據。
阿哲先試了一次模糊的問法。
幫我設計一套專業的設備借用系統,要完整一點。
加入預約月曆、主管簽核、電子郵件通知、逾期罰款,並在申請成功後扣除庫存。
看起來很完整。美玲卻問:「我們沒有罰款,而且申請還沒核准,為什麼就不能借給別人?」
第一個錯誤浮出來了:AI 把合理猜測寫得像既定政策。阿哲沒有要求它「更聰明一點」,而是改變工作順序。
先不要寫程式。我們要解決設備重複借出的問題。 請列出會改變資料模型或權限設計的關鍵問題。 區分:已知事實、待確認事項、你的建議。 不要自行把建議當成公司規定。
| 關鍵問題 | 美玲確認的答案 |
|---|---|
| 一筆設備是一種品項,還是一台實體? | 一台實體,有唯一設備編號。 |
| 何時占用設備? | 核准時保留;申請時不保留。 |
| 是否可預約下個月? | MVP 不做未來時段預約。 |
| 誰能核准、領用、歸還? | 管理員登記;員工只能申請及查自己的紀錄。 |
| 逾期會自動釋出嗎? | 不會。沒還就是還在外面。 |
| 核准後一直沒領? | 管理員可取消;本版不做自動到期。 |
帶走的概念:好 Prompt 不是修飾詞多,而是能讓未決事項浮出來。
可以列為建議,但不能當成已授權功能。通知涉及收件人、個資、寄送時機與外部動作;先確認範圍。設計通知草稿和真的寄出是不同授權。
阿哲:「如果小晴提出申請,阿凱也提出申請,你們希望誰先拿到?」
美玲:「不是先申請先贏,我要看用途。核准之前都只是候選。」
阿哲:「那核准後、還沒領走呢?」
美玲:「就要幫她留著。不然我核准了也沒意義。」
阿哲:「所以『占用』從核准開始,不是領用開始。我把這個寫進規格,你確認一下。」
「做個可以借東西的系統。」
不知道誰、何時、什麼算成功。
「管理員核准申請時,即保留那台設備;其他申請不得同時獲得保留。」
角色、時機與約束已可辨識。
決策:Approved 開始占用,Pending 不占用。 理由:管理員需要在多個用途間選擇。 確認者:美玲(故事角色) 受影響:可用性查詢、唯一索引、核准 API、並行測試。 若改變:不能只改按鈕文字,要同步重看以上項目。
那是另一套分配政策。需確認「先」依伺服器收到、資料提交還是人工優先順序判定。先到先得也不會自動消除並行問題;排序政策與資料庫保證是兩件事。
午餐前,阿哲把確認結果整理成一張「案卷」。他不再把整段聊天丟回去要求 AI 自己猜哪句最新。
【任務】設計設備借用 MVP 的核准流程。 【已確認/規格 v1】 一筆設備代表一台實體。Pending 不占用。 Approved、CheckedOut 占用。逾期不釋出。 不做未來預約、罰款、通知、自動核准。 管理員操作核准、領用、歸還;員工看自己的借用。 【技術】ASP.NET Core + PostgreSQL,版本尚待專案確認。 【本輪成果】狀態轉移表 + 不變條件 + 驗收案例。 【限制】不寫整個專案;新增假設另列,不能默默改規格。 【檢查】找出至少三個容易漏掉的失敗情境。
這就是 Context:讓這一輪判斷所需的資訊到位,而不是字數越多越好。即使留在同一個對話,也要有可引用、可更新的決策摘要。
美玲確認的內部政策,不需要上網找答案。若要選實際套件版本、查資料庫語法與安全設定,就查官方文件並記錄版本。本章的規則推導可以先做;不能把「AI 記得某個版本」當成部署依據。
阿哲要求更仔細地比較並行情境,卻沒有要求 AI 保證正確。推理深度能幫助分析,不能取代資料庫測試、權限測試或事實查證。
不會。帶入核准的規格、目前程式版本、已知失敗與本輪目標,就能接手。同一對話也不等於永遠記得全部細節。工作連續性靠可交接的案卷,不靠期待 AI 自動記住。
已確認政策、既有系統、實際錯誤與程式版本。
本版採用什麼?排除什麼?為什麼?
這次只要狀態表,不要整個專案。
要查什麼?要測什麼?哪些仍待確認?
第二天阿哲開了新對話。他沒有說「接著昨天做」,而是貼入案卷,附上目前要修改的服務檔及相關測試,要求先確認理解。
請先回覆: 1. 本輪會維持的三個不變條件。 2. 你仍缺少哪些資訊。 3. 你打算修改的範圍。 等範圍確認後,再產出修改。 不要把文件中的範例值當成正式環境設定。
我會維持單設備單占用、管理員核准、狀態與稽核一起提交。目前缺少專案版本、資料存取介面及現有授權方式,因此先交付設計,不宣稱能編譯。
這個回應比「沒問題,全部完成」更可用:它說出缺口,讓下一輪有方向。若 AI 誤以為申請就占用,先修正案卷理解,別讓錯誤一路長到程式碼裡。
「不可以重複借出。」主管點頭。阿哲追問:「兩個人同時按核准,也算嗎?」這句追問把漂亮需求變成工程問題。
| ID | 規則 | 可觀察的驗收結果 |
|---|---|---|
| R1 | 同一設備最多一筆有效占用 | 兩筆 Pending 同時核准,最多一筆成功;另一筆衝突,不得留下核准稽核。 |
| R2 | 只有管理員能核准 | 已登入員工直接呼叫核准 API 仍被拒絕,資料不變。 |
| R3 | 狀態與稽核一起成立 | 稽核寫入失敗時,狀態修改也回滾。 |
| R4 | 逾期不等於歸還 | 超過期限仍維持 CheckedOut,別人的核准仍失敗。 |
| R5 | 重試不可造成重複副作用 | 重複歸還不新增第二筆歸還稽核。 |
Given P-001 有兩筆 Pending:A、B When 兩個管理員同時核准 A 與 B Then 只有一筆成為 Approved And 有效占用筆數 = 1 And 只有成功者新增核准稽核 And 失敗者收到可理解的衝突訊息
這裡沒有規定 A 一定贏。先後順序可能不確定,但不變條件不能變。
沒有。隱藏按鈕是介面體驗,後端仍須檢查登入與角色。員工也不能只靠換網址就讀到別人的紀錄;資源層級存取要另外驗證。
用途:客戶提案
期望歸還:明日下午 17:00
送出後顯示「等待管理員核准」,不能顯示「借用成功」。
兩筆都是申請,不等於設備有兩台。核准任一筆後,另一筆應更新為「設備已被占用」,而不是假裝操作沒發生。
你的申請尚未核准。請重新整理設備狀態,或與管理員確認其他設備。
畫面應提供下一步,不顯示資料庫例外與其他借用者的非必要個資。
小晴點申請後看見 Pending;美玲核准後看見 Approved;網路逾時時顯示「結果尚未確認」,不能直接說失敗。這三句介面文字其實都需要後端契約支撐。
AI 提議增加一個 Overdue 狀態。美玲說:「那今天一逾期,原本那筆 CheckedOut 不就不算占用了?」
阿哲把圖重畫了。這不是所有系統的唯一設計,但符合本案:逾期是由時間推導的標籤,不是釋出設備的生命週期狀態。
主路徑由左至右(小螢幕由上至下)。旁支:Pending → Rejected/Cancelled;Approved → Cancelled。CheckedOut 必須歸還,不能直接取消來掩蓋未歸還事實。
isOverdue = status == CheckedOut AND nowUtc > dueAtUtc isOccupied = status IN (Approved, CheckedOut)
核准時必須設定未來的歸還期限;領用時再確認期限仍在未來。時間以 UTC 儲存,畫面依使用者時區顯示。剛好等於期限尚不算逾期,超過才算:邊界也要測。
不夠。目前保證的是任何時刻最多一筆有效占用,不是時段不重疊。未來預約會改變衝突模型、取消政策及測試;須重新設計區間重疊約束,不能直接沿用本章索引。
這張圖最重要的不是箭頭,而是「點收」。本案由管理員確認歸還,避免員工在家按下歸還,設備卻還沒回來。若以後要自助歸還,必須新增證據或待點收政策,不能默默沿用 Returned 的語意。
設備已保留
記錄取消原因及操作人
釋出占用,保留歷史
要先確認設備是否已被另一筆申請占用。修正不是任意倒帶;需要授權、衝突檢查與更正稽核。這是本版尚未涵蓋的管理更正流程,應另列需求。
下午兩點,阿哲看到 AI 寫出的第一版邏輯:
如果查不到有效占用:
把這筆申請改成 Approved
儲存「看起來對呀?」小晴問。阿哲把兩個請求並排放在白板上。
| 時刻 | 請求 A | 請求 B |
|---|---|---|
| 1 | 查詢:沒有占用 | |
| 2 | 查詢:也沒有占用 | |
| 3 | 更新 A 為 Approved | |
| 4 | 更新 B 為 Approved |
兩邊都沒有說謊,只是都用過時的觀察做決定。阿哲補上最後一道防線:
-- 設計片段:loans 的每列是一筆申請
CREATE UNIQUE INDEX ux_loans_one_active_equipment
ON loans (equipment_id)
WHERE status IN ('Approved', 'CheckedOut');
局部唯一索引只對符合條件的列要求唯一。兩筆申請可同時 Pending;一旦爭取同一設備的有效占用,資料庫不允許兩筆都成功。這是 PostgreSQL 支援的機制;此處不是已套用的 migration。官方:Partial Indexes
資料模型還需要 equipment_id、borrower_id 的非空與外鍵,status 合法值約束,以及占用/歸還階段必要時間欄位的檢查。索引只解決「最多一筆占用」,不會替你檢查管理員權限或合法狀態轉移。
不一定。原子性確保一組修改一起成功或失敗,不代表兩個交易不會都讀到「沒有占用」。本案用唯一索引守住跨申請的不變條件,並用條件更新守住同一申請的狀態轉移。
這是「A 成功提交」的一條示範時序,不是承諾 A 必勝。實際等待與錯誤時機依交易交錯而定。若 A 回滾,B 可能成功;要驗證的是最後不會出現兩筆有效占用。
守同一申請:只能由 Pending 核准,不能把 Returned 重新核准。
守不同申請:不同 loan_id 也不能同時占用同一 equipment_id。
守整組操作:狀態更新與稽核不能只完成一半。
守操作資格:知道網址的人不等於有權核准。
四道防線各有責任,不能互相代替。前端停用按鈕可減少誤點,但不列為資料一致性的最後保證。
阿哲沒有直接叫 AI「補上錯誤處理」,而是先要求列出使用者會遇到的結果。
請依 R1–R5 設計核准 API 契約。 列出成功、未登入、無權限、找不到、 狀態已改變、設備被占用的回應。 操作人從伺服器驗證的登入身分取得,不接受 body 的角色。
| 請求 | 成功 | 重要失敗 |
|---|---|---|
| POST /loans/{id}/approve | 200,回傳 Approved 與 dueAt | 401 未登入、403 非管理員、404 不存在、409 狀態/占用衝突、400 不合法期限 |
| POST /loans/{id}/checkout | 200,回傳 CheckedOut | 409 非 Approved 或期限已過 |
| POST /loans/{id}/return | 200,回傳 Returned | 409 非 CheckedOut;若已 Returned,依本案契約回 200 但不再新增稽核 |
以上操作都先做管理員授權;錯誤不能包含 SQL、連線資訊或其他人的個資。員工查自己的紀錄另做 borrower_id 篩選,不能信任前端傳來的 userId。
美玲又問:「我按歸還後網路斷了,再按一次呢?」這讓阿哲看見重試不是少見例外,而是正常使用情境。同一結果可重回,不代表副作用可重做。
不可以。可能資料已提交,只是回應沒到。先查最新狀態,或按已定義的可重試契約重送;對寄信、扣款等額外副作用還需要獨立去重設計。
送出 loanId 與歸還期限;不決定自己是不是管理員。
伺服器確認登入及角色;拒絕不合格操作。
檢查輸入、執行合法轉移、組織交易。
約束有效占用;提交狀態與稽核。
回傳成功或可理解的衝突;畫面重新反映事實。
| 資料 | 核准之前 | 核准提交後 |
|---|---|---|
| loan A.status | Pending | Approved |
| loan A.due_at | 尚未核准的期限 | 管理員核准期限 |
| 有效占用數 | 0 | 1 |
| 核准稽核 | 0 | 1 |
表格是示範預期。若稽核寫入失敗,右欄不能只保留前三項;這正是交易必須保護的邊界。
測試可以建立測試身分或注入測試授權情境;正式操作人的來源仍應是已驗證身分。不能為了測試方便,留下使用者可偽造操作人的正式 API。
阿哲準備請 AI 寫完整專案,想了想改成:「先做核准這一條。」小切片比較容易審查,也容易用測試推翻。
依規格 v1,先產出 ApproveLoan 的服務流程。 保留條件更新、局部唯一索引衝突處理、稽核同交易。 標明示意碼和未實作依賴。不要宣稱測試通過。 另外列出:這段程式仍不能保證什麼。
// C# 風格示意碼;不是可直接編譯的實作。
RequireAuthenticatedAdmin(actor);
ValidateFutureDueAt(dueAtUtc);
await using var tx = await db.BeginTransactionAsync();
try {
// 參數化 SQL:
// UPDATE loans SET status='Approved', due_at=@due
// WHERE id=@id AND status='Pending' RETURNING id;
var changed = await ConditionalApprove(id, dueAtUtc);
if (!changed) {
// 同交易查明不存在或狀態衝突;不建立稽核
throw await NotFoundOrConflict(id);
}
await InsertAudit(id, "Approved", actor.Id);
await tx.CommitAsync();
return Approved;
}
catch (PostgresException ex)
when (ex.SqlState == "23505"
&& ex.ConstraintName == "ux_loans_one_active_equipment") {
await tx.RollbackAsync();
return EquipmentOccupiedConflict;
}
// 其他例外不得偽裝成占用衝突;交易 dispose 回滾,
// 由統一錯誤處理記錄安全診斷資訊並回適當錯誤。
同一筆申請被核准兩次時,條件更新只允許從 Pending 轉移;不同申請搶同一設備時,由索引限制。稽核與更新包在同一交易,才不會留下「核准成功,稽核卻失蹤」的半套結果。
EF Core 在支援交易的 provider 上,單次 SaveChanges 通常以交易處理;本例有多個操作,必須明確保證它們使用同一連線/交易。不能因為程式出現 BeginTransaction 就假定所有 helper 都參與了它。官方:Using Transactions
不對。連線中斷、SQL 錯誤、其他約束失敗都不是「有人先借走」。只精準映射指定衝突,其餘保留可診斷性,對外不洩漏敏感細節。
id(主鍵)
asset_code(唯一編號)
display_name
id(主鍵)
equipment_id(外鍵)
borrower_id
status · due_at
id(主鍵)
loan_id(外鍵)
action · actor_id
occurred_at
這是概念模型,不是完整建表腳本。borrower_id 與 actor_id 需對應既有身分系統;設備歷史和刪除策略也要定義。把 borrower_name 直接塞在設備表會讓歷史、身分變更與多次借用難以表達。
阿哲的價值不是比 AI 打字快,而是能判斷什麼問題值得追問,以及哪個答案仍缺證據。
美玲說:「程式我看不懂,但你讓我按一次,我就知道有沒有怪。」下面是只在這個網頁執行的狀態模型:不連資料庫、不登入、不寄信、不證明並行安全。它讓你看清規則造成的結果。
建議照順序按:核准 A → 核准 B → 領用 A → 時間超過期限 → 再核准 B → 歸還 A → 核准 B → 再歸還 A。
A 核准成功,占用 P-001;B 核准衝突。A 領用後,即使逾期仍占用,B 仍失敗。A 歸還才釋出,B 此時可核准。再次歸還 A 回傳已歸還,不新增稽核,也不能釋出 B 的占用。
最後應為 A=Returned、B=Approved、稽核 4 筆(A 核准、A 領用、A 歸還、B 核准)。讓時間前進不是使用者狀態操作,不寫入此示範的操作稽核。
前端可暫時停用按鈕,但第二個請求仍可能抵達。後端應只接受一次合法轉移,稽核不能加兩次。
事故 B · 小晴逾期兩天畫面變成「逾期」,實體設備仍在她手上。若系統把它列為可借,這是業務規則錯誤,不是介面顏色問題。
事故 C · A 歸還後,B 已核准,A 又重送歸還系統應認出 A 已 Returned;不能用「把設備設成可用」的粗略更新,誤釋出 B 的占用。
錯誤思路: 歸還任何借用 → equipment.available = true 本案思路: 確認這筆 loan 是否可歸還 → 轉移這筆 loan 狀態 設備是否占用 → 根據仍有效的 loan 判定
若實務上要保存額外快取欄位,也必須處理它與借用紀錄的一致性。本章刻意避免第二份可用性真相,先把主要規則做清楚。
AI 交出一張測試表,每列都寫「通過」。阿哲問:「你在哪個環境、用哪個版本、執行了哪個命令?」對方若拿不出紀錄,這些勾勾只能刪掉。
請產出測試案例,不要填入未執行的實際結果。 每例包含前置資料、操作、預期 HTTP、資料列與稽核斷言。 並行案例必須使用真實 PostgreSQL 的兩個獨立連線, 不能只用前端按鈕或記憶體 fake 宣稱通過。
| 測試 | 預期證據 | 本教材後端執行狀態 |
|---|---|---|
| 一般核准 | 200;Approved;一筆核准稽核 | 未執行 |
| 兩申請並行核准 | 一個成功、一個 409;有效占用=1;核准稽核=1 | 未執行 |
| 同申請並行核准 | 只轉移一次;只一筆核准稽核 | 未執行 |
| 稽核故障注入 | 整筆回滾;仍 Pending;無稽核 | 未執行 |
| 員工偽造 admin 欄位 | 403;狀態、稽核不變 | 未執行 |
| 歸還重試 | 重送仍 200;歸還稽核維持一筆 | 未執行 |
| 期限邊界 | 等於期限不逾期;超過才逾期;兩者都不釋出 | 未執行 |
並行測試要安排兩個工作者競爭,記錄回應、交易結果及最終資料;不要只依序呼叫兩次。使用隔離測試資料庫,不能在正式借用資料上試故障。
不行。自我審查有助找遺漏,但可能反覆忽略同一假設。需要可執行的檢查、獨立觀察與失敗證據;檢查次數不是正確率證明。
隔離 PostgreSQL
P-001 一台
A、B 兩筆 Pending
兩個獨立連線
協調兩個工作者競爭核准
收集各自回應
等待兩者完成
成功數 = 1
衝突數 = 1
有效占用 = 1
核准稽核 = 1
測試者故意讓稽核儲存失敗。若 API 回錯誤,但資料庫裡 A 已 Approved,表示使用者看到失敗,設備卻被保留:這不是「錯誤處理有做」,而是交易邊界有洞。
測試紀錄樣板(不是已執行結果) 程式 commit: 資料庫/provider 版本: 測試命令: 測試資料與隔離方式: 實際 HTTP: 最終 loan: 最終 audit: 結果:未執行 / 通過 / 失敗 失敗附件與重現方式:
預期:稽核失敗時 loan 維持 Pending。 實際:API 回 500,但 loan 變成 Approved。 附上:服務方法、交易建立處、兩個 helper 的連線取得方式。 請先提出可驗證的原因假說與檢查順序, 不要直接重寫整個專案,也不要斷言唯一原因。
好的診斷會檢查是否不同連線、提前提交或例外被吞掉。這些都是假說,需用程式與紀錄確認;不是因為聽起來合理就算找到原因。
星期五,美玲已經能說出「逾期不釋出」。阿哲準備交付,卻在舊資料中找到兩筆同設備的有效核准。若直接建立唯一索引,migration 會失敗。
他沒有讓 AI 自動刪掉其中一筆,而是產生衝突清單,請管理員確認真實借用狀態,保留修正紀錄。技術上的重複,不代表可以替業務決定哪筆是真的。
| 交付物 | 必須讓接手者知道 |
|---|---|
| 規格與決策紀錄 | R1–R5、角色、狀態圖、不做未來預約、尚未決定事項 |
| 程式與資料庫版本 | commit、套件鎖定、migration、設定樣板;不含密碼 |
| 測試證據 | 環境、命令、時間、結果;未測明列,不能混入通過欄 |
| 部署與復原 | 備份與還原演練、既有衝突清查、暫停寫入/切換方案、失敗復原步驟 |
| 操作與觀察 | 核准/歸還流程、衝突訊息、錯誤監控、負責人 |
正式部署還需依資料量、維護窗口與實際版本確認 migration 策略。回滾不能只是「把索引刪掉」;那會拿掉保護,必須評估舊版程式與資料相容性。
業務已確認
未知已列出
版本固定
變更可追溯
權限與並行已測
失敗可重現
備份能還原
負責人與復原流程明確
四扇門不是看完教學就自動變綠。本故事走完的是決策與設計示範,真正專案要拿出各門的證據。
「故障/維修中的設備是否能申請」是尚需新增的範圍。本版不因為故事提到實體點收,就假裝已實作完整資產維護系統。
依目前已確認內容產出交接摘要: 已完成(附證據)、未完成、已知限制、部署前必要檢查。 每項對應檔案或測試紀錄;沒有證據標註未驗證。 另外列出明天接手者的前三個動作。
美玲關上器材櫃:「下次再做請假系統,是不是把設備換成假單就好?」
阿哲笑了:「要帶走的是做事方法,不是照抄資料表。」
| 故事中的動作 | 可遷移的能力 |
|---|---|
| 先問何時占用 | 找出改變設計的未決需求 |
| 整理案卷 v1 | 控制 Context,區分事實、假設與建議 |
| 要求失敗案例 | 用反例檢驗答案,不只看成功路徑 |
| 分開條件更新、索引與交易 | 知道每道機制保障什麼、沒保障什麼 |
| 要求執行證據 | 區分建議、示意、已實作與已驗證 |
這些方法也能用在 Claude;本章是示範如何與 ChatGPT 協作,不是宣稱另一個產品沒有工作流程能力。
新需求:小晴已領用 P-001,想延長三天。員工可以提出延期,但只有管理員可核准。若設備已逾期,仍可申請;核准前原期限不變。
請先自行寫出:要問的問題、最小 Context、狀態/資料變更、兩個失敗情境及其可觀察斷言。不要只把「借用」換成「延期」。下方可寫草稿(不會自動儲存,離頁前請自行複製)。
20 分|找未知:問最長可延幾天、可否重複申請、誰能取消、以原期限或核准日為基準。每個真正影響設計的問題 5 分,最多 20;不能自行當成既定政策。
20 分|Context:說明目前 CheckedOut、現有 dueAt、占用不釋出、管理員核准前期限不變。各 5 分。
20 分|模型:延期申請與借用生命週期分開(5);保存 proposedDueAt 與原核准期限(5);核准時才更新 dueAt(5);更新與稽核同交易(5)。這是參考設計,不是唯一資料表答案。
30 分|反例:提出「等待核准時先歸還」與「兩個管理員同時處理延期」。各 15 分:前置條件 5、預期行為 5、資料/稽核斷言 5。核准時須重新確認仍 CheckedOut;並行處理不得重複核准或覆寫較新的期限。
10 分|證據邊界:列出需要真實後端/DB 測試(5);沒有執行結果不宣稱通過(5)。
示範 Prompt:「依設備借用規格 v1,新增延期申請。先列未決政策,不直接實作。產出申請與借用狀態的關係、原期限更新時點,以及『先歸還後核准』『並行核准』的驗收案例。不要讓待核准申請改變有效期限。」
解讀:90–100 表示本次回答涵蓋主要重點,仍不代表已具備實作能力;75–89 補弱項;低於 75 重讀對應場景。若先看過答案再寫,這次分數只算練習。隔天改做「取消核准」,不看答案重做,才能增加對遷移能力的信心。
不應如此。Returned 已不在占用索引範圍,保留歷史才能追溯;刪資料不是狀態設計。
依本案不算。尚未占用,允許多人申請;業務上的不變條件不是『每台只能有一筆紀錄』。
不表示。來源支持機制,不證明你使用同一交易、正確參數或完整例外處理;仍須檢查與執行。
不適合。設備確實被占用時,重試不會改變業務事實。應呈現衝突並更新狀態,不無限重試。
不能推定。教學用虛構或去識別資料;真實資料的存取、用途與分享範圍需要分別確認。
還不夠。要能解釋它不管權限、不管合法轉移、不能直接支援未來時段預約,並能提出可驗證反例。
主管追上阿哲:「我想讓員工自己取消申請。」這次阿哲不急著加按鈕。
阿哲:「只取消自己的 Pending,還是連 Approved 也能取消?」
主管:「先只讓員工取消自己的 Pending。核准後找管理員。」
阿哲:「如果你取消的同時,管理員正好核准呢?」
主管:「只能一個成功。取消若沒成功,要讓員工知道已核准。」
沿用規格 v1。新增:員工可取消自己的 Pending。 Approved 的取消仍由管理員操作。 本輪只設計員工取消,不變更核准政策。 請列授權條件、條件更新、並行驗收與錯誤回應。
取消操作要同時確認申請所有人及 Pending。示意條件是 id=@id AND borrower_id=@actor AND status='Pending'。actor 來自已驗證登入身分。更新與取消稽核使用同一交易。
零筆更新不能一律說取消成功;需依契約區分不可見資源與狀態衝突,並避免藉由回應洩漏他人申請。本案可對非本人資源回 404,對自己的非 Pending 回 409。
| 情境 | 預期 |
|---|---|
| 小晴取消自己的 Pending | Cancelled;一筆取消稽核。 |
| 阿凱改網址取消小晴的申請 | 拒絕;狀態與稽核不變。 |
| 取消與核准同時發生 | 只有一個 Pending 轉移成功;不得同時留下兩個成功操作。 |
| 小晴取消已領用設備 | 拒絕;不能以取消代替歸還。 |
你不必照抄任何一句 Prompt,但應能自行找出所有權、狀態前提、並行競爭、稽核一致性。如果只想到「新增取消按鈕」,請回看請求剖面圖;若只想到 transaction,請回看四道防線。
① 為什麼申請和核准不能混為一談?因為它們承擔不同業務承諾;本案只有核准開始占用。
② 為什麼 AI 回覆完整,仍不能直接交付?因為完整敘述不代表政策已確認、程式已執行或風險已驗證。
③ 換成會議室預約,哪個設計最先不能照抄?本案「任何時間只能一筆有效占用」的限制;會議室通常要處理時段重疊,需重新確認模型。