ub-mode
寫程式時照精簡原則走:先讓它能動,再做對,最後遵守實務
中文翻譯
--- name: ub-mode description: > 寫程式或改程式時,遵循精簡過的原則。每次改動都照 先讓它能動(First Make it Work)、再把它做對(Then Make it Right)、最後遵守實務(Follow Practice)的順序。 使用者執行 /ub-mode 或要求精簡原則時使用。 --- # ub-mode 每次被要求做改動時,照這個順序: * 先讓它能動(First Make it Work)。 * 再把它做對(Then Make it Right)。 * 遵守實務(Follow Practice) # 先讓它能動(First Make it Work) ## 偷懶協議(Laziness Protocol) * 一個決定只放在一個地方。 * 只送出能解決問題的最小改動。 ## 基礎思考 * 先把資料的形狀弄對,再寫邏輯。 * 先做那些對後面每個階段都有幫助的事。 * 如果並行寫入會有影響,就不要共用 state。 ## TDD * 改程式之前,先寫會失敗的測試。 * 確認它是因為你預期的原因失敗。 * 做出能讓它通過的最小改動。 * 如果誠實的測試做不出來,就不要寫一個爛的。 ## 從第一原理重新設計 * 不要把新需求硬接在舊設計上。 * 問自己:如果一開始就有這個需求,你會怎麼蓋?把它想清楚,然後分段交付。 ## 攻擊前提 * 當兩個共用同一個前提的修法,在同一道關卡失敗,用一句話把那個前提寫下來,並數一數哪些角色握有那個不平衡。 * 把這個指派拿掉。 * 做完這件事之前,不要開始另一個修法。 ## 先減再加 * 加任何東西之前,先把複雜度拿掉。 ## 以結果為導向的執行 * 瞄準你能檢查的最終狀態。 * 中途可以有中斷,前提是你事先規劃過、而且能還原。 ## 打造槓桿 * 如果這個工作不是一眼就看得出怎麼做,就去做一個能做這件事的工具。 * 先手動做一個單位,再讓工具對上那個單位。 ## 架構 ### 為領域建模 * 把領域放進一個讓非法狀態不可能出現的結構裡。 * 維護一份領域名詞的詞彙表。 * 如果程式碼已經清楚而且是區域性的,就別動它。 ### 邊界紀律 * 在資料進來的地方檢查它。 * 進到裡面就信任它。 * 業務邏輯放在純函式裡。 ### 型別系統紀律 * 讓非法的值根本寫不出來。 * 外部資料在進來的地方只解析一次。 * 不要讓編譯器閉嘴。 ### 讓操作具有冪等性 * 執行兩次,或在中途當機後再執行,最後都會落在同樣的狀態。 ### 序列化共享狀態之前先分離 * 如果它們不需要同一個可變的東西,就各給一份。 * 如果需要,就只允許一個寫入者,並且在結構上強制做到。 # 再把它做對(Then Make it Right) ## 修根本原因 * 重現它。 * 修原因。 * 只是把當機遮起來的防護,不算修好。 ## 把工作切成可驗證的單位 * 完成一個小單位並檢查它。 * 然後再開始下一個。 ## 測試行為,不測實作 * 測試要用使用者呼叫程式碼的方式去呼叫,並檢查使用者會看到的結果。 * 如果每個函式都回傳空值,這個測試還是會通過,那就把它丟掉。 ## Crapper * 使用 crapper 工具 * 把每個函式的 CRAP 分數降到 10 以下,方法是拆分它、測試它,或兩者都做。 * 想想 case 敘述值不值得去降。 ## Dryer * 使用 dryer 工具,消除排名 0.8 以上的重複。 ## Mutator * 使用 mutator 工具 * 補上沒覆蓋到的部分。 * 殺掉存活的 mutant。 * 刪除死碼。 ## 重構 * 把程式碼目前的行為釘住。 * 改結構。 * 證明行為沒有變。 # 實務(Practice) ## 記錄日誌 * 把你做的每個動作和原因都記成日誌。 * 完成時回報這份日誌。 ## 守護 Context Window * 讓主執行緒保持精簡。 * 大量的內容送去別的地方,只留摘要。 ## Worktree 清理 * 找出可以安全移除的東西,確認沒有還在用的東西需要它,再回收磁碟空間。 * 還沒 commit 的工作要等人決定。 ## Commit 與 Push * 常常 commit,切成小而有順序的 commit。 * 每個 commit 都要說明為什麼改、改了什麼、怎麼證明它沒問題。 * 最後 push 到主線。
英文原文
--- name: ub-mode description: > Follow the reduced principles when writing or changing code. Every change follows First Make it Work, then Then Make it Right, then Follow Practice. Use when the user runs /ub-mode or asks for the reduced principles. --- # ub-mode Every time you are asked to make a change follow: * First Make it Work. * Then Make it Right. * Follow Practice # First Make it Work ## Laziness Protocol * One decision lives in one place. * Ship the smallest edit that solves the problem. ## Foundational Thinking * Get the data shape right before you write the logic. * Do first whatever helps every later phase. * If a concurrent writer would matter, do not share state. ## TDD * Write the failing test before you change the code. * See it fail for the reason you expect. * Make the smallest change that makes it pass. * If an honest test is impractical, do not write a bad one. ## Redesign From First Principles * Do not bolt a new requirement onto the old design. * Ask what you would have built if it had been there from the start, think that through, and deliver it in pieces. ## Attack the Premise * When two fixes that share one premise fail the same gate, write that premise in one sentence and count which actors hold the imbalance. * Remove the assignment. * Do not start another fix until you have done that. ## Subtract Before You Add * Take complexity out before you add anything. ## Outcome-Oriented Execution * Aim at the end state you can check. * A break in the middle is allowed when you planned it and can undo it. ## Build the Lever * If the work is not obvious at a glance, build the tool that does it. * Do one unit by hand, then make the tool match that unit. ## Architecture ### Model the Domain * Put the domain in a structure that makes the illegal states impossible. * Maintain a glossary of domain terms. * If the code is already clear and local, leave it. ### Boundary Discipline * Check the data where it enters. * Inside, trust it. * Keep the business logic in a pure function. ### Type System Discipline * Make the illegal value impossible to write. * Parse outside data once, where it comes in. * Do not silence the compiler. ### Make Operations Idempotent * Running it twice, or running it after a crash halfway through, ends in the same state. ### Separate Before Serializing Shared State * If they do not need the same mutable thing, give each its own. * If they do, allow one writer, and enforce that in the structure. # Then Make it Right ## Fix Root Causes * Reproduce it. * Fix the cause. * A guard that only hides the crash is not a fix. ## Sequence work into verifiable units * Finish one small unit and check it. * Then start the next. ## Test Behavior, Not Implementation * The test calls the code the way its user does and checks the result that user would see. * If the test would still pass when every function returned nothing, throw it out. ## Crapper * Use the crapper tool * Reduce each function under CRAP 10 by splitting it, by testing it, or both. * Consider whether case statements are worth reducing. ## Dryer * Use the dryer tool to eliminate duplication that rank 0.8 or above. ## Mutator * Use the mutator tool * Cover the uncovered. * Kill the survivors. * Delete dead code. ## Refactoring * Pin what the code does. * Change the structure. * Prove the behavior did not change. # Practice ## Keep a Log * Keep a log of every action you take and the reason you took it. * Report that log upon completion. ## Guard the Context Window * Keep the main thread small. * Send the bulk elsewhere, and keep the summary. ## Worktree Cleanup * Find what is safe to remove, confirm nothing still in use needs it, then reclaim the disk. * Uncommitted work waits for a decision. ## Commit and Push * Commit often, in small ordered commits. * Each commit says why, what changed, and how you proved it. * Push to the main line at the end.