<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Destructive-Action on Tarragon</title><link>https://tarrragon.github.io/blog/tags/destructive-action/</link><description>Recent content in Destructive-Action on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 17 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/destructive-action/index.xml" rel="self" type="application/rss+xml"/><item><title>Fail-Safe Default（安全預設）</title><link>https://tarrragon.github.io/blog/ux-design/knowledge-cards/fail-safe-default/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/ux-design/knowledge-cards/fail-safe-default/</guid><description>&lt;p>Fail-safe 預設的核心概念是「保護機制本身故障時，系統選擇倒向哪個方向」。確認對話框沒渲染、事件沒綁上、回應逾時 — 這些故障發生時系統仍要做一個決定：把故障當同意（執行）或當拒絕（不執行）。安全預設的原則是倒向不可逆性低的那邊：不清空可以重試、清空無法還原。這是 &lt;a href="https://tarrragon.github.io/blog/ux-design/knowledge-cards/gate/" data-link-title="Gate（UX）" data-link-desc="說明使用者操作流程中「必須通過才能繼續」的關卡，以及成功/失敗/不確定三條路徑的設計責任">Gate&lt;/a> 的第二層設計 — gate 攔使用者、fail-safe 管 gate 自己壞掉的情況。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Fail-safe 預設與 &lt;a href="https://tarrragon.github.io/blog/ux-design/knowledge-cards/ux-fallback/" data-link-title="Fallback（UX）" data-link-desc="說明 gate 未通過時使用者的替代路徑，和 backend fallback（server-side 降級）的語意區別">UX Fallback&lt;/a> 的分工：fallback 是給使用者的替代路徑（主路徑失敗後使用者往哪走）、fail-safe 是系統自己的預設方向（保護機制失效時系統做什麼）— 前者是使用者可見的路、後者是程式碼裡的 else 分支。安全領域的對應概念是 fail-open vs fail-closed：破壞性操作的確認機制要 fail-closed（故障即拒絕）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>需要檢查 fail-safe 的訊號是「保護邏輯存在、但它的故障分支沒人設計過」。實戰正面案例：匯入覆蓋模式的確認 Modal 在 DOM 缺失時一律視為未確認、預設不清空書庫（&lt;a href="https://tarrragon.github.io/blog/ux-design/cases/destructive-import-fail-safe-confirm/" data-link-title="U.C12 匯入空檔會清空書庫 — 破壞性操作的確認與安全預設" data-link-desc="設計會覆蓋 / 清空既有資料的操作時使用。破壞性操作 gate 有兩層：確認使用者意圖、加上確認機制本身故障時的安全預設 — 故障要倒向不可逆性低的那邊">U.C12&lt;/a>）。反向的檢查問句：確認元件不存在時、你的程式碼走哪個分支？&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Fail-safe 的設計責任是為每個保護機制（確認對話框、權限檢查、二次驗證）顯式寫下故障分支的方向。程式碼層的掃描訊號：確認邏輯的 else / null / timeout 分支最終呼叫的是「執行」還是「中止」— 分支缺失或走向執行的，就是故障會靜默放行破壞的候選。&lt;/p></description><content:encoded><![CDATA[<p>Fail-safe 預設的核心概念是「保護機制本身故障時，系統選擇倒向哪個方向」。確認對話框沒渲染、事件沒綁上、回應逾時 — 這些故障發生時系統仍要做一個決定：把故障當同意（執行）或當拒絕（不執行）。安全預設的原則是倒向不可逆性低的那邊：不清空可以重試、清空無法還原。這是 <a href="/blog/ux-design/knowledge-cards/gate/" data-link-title="Gate（UX）" data-link-desc="說明使用者操作流程中「必須通過才能繼續」的關卡，以及成功/失敗/不確定三條路徑的設計責任">Gate</a> 的第二層設計 — gate 攔使用者、fail-safe 管 gate 自己壞掉的情況。</p>
<h2 id="概念位置">概念位置</h2>
<p>Fail-safe 預設與 <a href="/blog/ux-design/knowledge-cards/ux-fallback/" data-link-title="Fallback（UX）" data-link-desc="說明 gate 未通過時使用者的替代路徑，和 backend fallback（server-side 降級）的語意區別">UX Fallback</a> 的分工：fallback 是給使用者的替代路徑（主路徑失敗後使用者往哪走）、fail-safe 是系統自己的預設方向（保護機制失效時系統做什麼）— 前者是使用者可見的路、後者是程式碼裡的 else 分支。安全領域的對應概念是 fail-open vs fail-closed：破壞性操作的確認機制要 fail-closed（故障即拒絕）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>需要檢查 fail-safe 的訊號是「保護邏輯存在、但它的故障分支沒人設計過」。實戰正面案例：匯入覆蓋模式的確認 Modal 在 DOM 缺失時一律視為未確認、預設不清空書庫（<a href="/blog/ux-design/cases/destructive-import-fail-safe-confirm/" data-link-title="U.C12 匯入空檔會清空書庫 — 破壞性操作的確認與安全預設" data-link-desc="設計會覆蓋 / 清空既有資料的操作時使用。破壞性操作 gate 有兩層：確認使用者意圖、加上確認機制本身故障時的安全預設 — 故障要倒向不可逆性低的那邊">U.C12</a>）。反向的檢查問句：確認元件不存在時、你的程式碼走哪個分支？</p>
<h2 id="設計責任">設計責任</h2>
<p>Fail-safe 的設計責任是為每個保護機制（確認對話框、權限檢查、二次驗證）顯式寫下故障分支的方向。程式碼層的掃描訊號：確認邏輯的 else / null / timeout 分支最終呼叫的是「執行」還是「中止」— 分支缺失或走向執行的，就是故障會靜默放行破壞的候選。</p>
]]></content:encoded></item><item><title>U.C12 匯入空檔會清空書庫 — 破壞性操作的確認與安全預設</title><link>https://tarrragon.github.io/blog/ux-design/cases/destructive-import-fail-safe-confirm/</link><pubDate>Fri, 17 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/ux-design/cases/destructive-import-fail-safe-confirm/</guid><description>&lt;p>這個案例的核心責任是展示破壞性操作 gate（使用者必須通過才能繼續的關卡）的完整設計（正面案例）：確認對話框攔截使用者意圖之外，確認機制本身的故障模式也被設計了 — UI 元件缺失時視為「未確認」，預設不執行破壞。&lt;/p>
&lt;h2 id="觀察">觀察&lt;/h2>
&lt;p>電子書庫總覽 Chrome 擴充功能（book_overview_v1）的匯入功能有覆蓋 / 合併兩種模式；覆蓋模式的語意是「以檔案內容取代現有書庫」— 該模式下匯入空檔等於清空全部資料。設計（&lt;code>src/overview/import-flow-controller.js&lt;/code>，W1-049）：&lt;/p>
&lt;ol>
&lt;li>覆蓋模式下偵測到匯入內容為空時，彈出專屬確認 Modal 描述後果（現有書庫非空時文案帶具體數字「將清空現有 N 本書」）、使用者明確確認才執行；合併模式不觸發這道確認。&lt;/li>
&lt;li>Modal 帶 &lt;code>aria-labelledby&lt;/code> / &lt;code>aria-describedby&lt;/code>，螢幕閱讀器使用者能取得完整的後果描述。&lt;/li>
&lt;li>關鍵設計：&lt;strong>確認 Modal 的 DOM 元件缺失時，視為使用者未確認、預設不清空&lt;/strong>。確認機制故障不會讓破壞性操作靜默通過。&lt;/li>
&lt;/ol>
&lt;h2 id="判讀">判讀&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>破壞性操作 gate 是 gate 的一個獨立類型&lt;/strong>。認證 / 網路 / 權限 gate 攔「使用者能不能繼續」，破壞性操作 gate 攔「使用者是否理解後果」— 觸發條件不是身分或環境、是操作的破壞半徑（不可逆、影響既有資料、影響範圍大於使用者的直覺預期）。「匯入」聽起來是加法、覆蓋模式的實際語意是取代 — 語意與直覺預期的落差越大、越需要確認。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>確認機制本身有故障模式&lt;/strong>。元件沒渲染、事件沒綁上、動態載入失敗 — 確認 UI 故障時系統要選一個預設方向：執行（把故障當同意）或不執行（把故障當拒絕）。安全預設的原則是倒向不可逆性低的那邊：不清空可以重試匯入、清空無法還原。這與「fail-open vs fail-closed」的安全設計同構。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>確認對話框的可及性是 gate 有效性的一部分&lt;/strong>。看不到後果描述的確認（螢幕閱讀器讀不出 Modal 內容）等於沒有確認 — 使用者按了「確定」但不知道確定了什麼。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="策略">策略&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>識別破壞性操作&lt;/strong>：列出所有會覆蓋 / 刪除 / 取代既有資料的操作，語意與直覺預期有落差的是高風險項（匯入的覆蓋模式 = 取代、同步 = 可能覆蓋、重設 = 清空）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>確認 UI 描述後果、不只問「確定嗎」&lt;/strong>：帶上具體數字（「將清空現有 N 本書」）讓使用者對照自己的預期。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>為確認機制設計故障預設&lt;/strong>：確認元件不存在 / 事件未觸發 / 回應逾時，一律視為未確認。程式碼層的檢查訊號：確認邏輯的 else / null 分支走向哪邊。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>Gate 的必答問題與類型 → &lt;a href="https://tarrragon.github.io/blog/ux-design/02-gate-fallback/gate-three-questions/" data-link-title="Gate 分類與三問設計法" data-link-desc="每個 gate 設計時問三個問題：成功時做什麼、失敗時做什麼、使用者不知道發生什麼時做什麼">Gate 分類與三問設計法&lt;/a>&lt;/li>
&lt;li>確認機制故障的預設方向 → &lt;a href="https://tarrragon.github.io/blog/ux-design/knowledge-cards/fail-safe-default/" data-link-title="Fail-Safe Default（安全預設）" data-link-desc="說明保護機制本身故障時系統倒向哪個方向的設計決策 — 預設倒向不可逆性低的那邊，確認 UI 壞掉不該讓破壞性操作靜默通過">Fail-safe 預設&lt;/a>&lt;/li>
&lt;li>通知形式的干擾程度判準（Dialog 的阻斷性是設計需求）→ &lt;a href="https://tarrragon.github.io/blog/ux-design/06-interaction-feedback/notification-pattern-selection/" data-link-title="通知模式選擇：SnackBar、Dialog、Banner 與 Bottom Sheet" data-link-desc="操作結果該用 SnackBar 閃一下還是彈 Dialog 問使用者 — 干擾程度與是否需要使用者操作的二軸判準，選錯形式的症狀是通知被忽略或流程被打斷">通知模式選擇&lt;/a>&lt;/li>
&lt;li>對照案例（gate 缺 fallback）→ &lt;a href="https://tarrragon.github.io/blog/ux-design/cases/biometric-only-no-fallback/" data-link-title="U.C2 biometricOnly=true 無密碼 fallback" data-link-desc="Flutter app 的生物辨識設定 biometricOnly: true 阻擋所有非生物辨識認證方式 — Face ID 不可用時使用者直接被擋住，沒有替代路徑">U.C2 biometricOnly 無 fallback&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>這個案例的核心責任是展示破壞性操作 gate（使用者必須通過才能繼續的關卡）的完整設計（正面案例）：確認對話框攔截使用者意圖之外，確認機制本身的故障模式也被設計了 — UI 元件缺失時視為「未確認」，預設不執行破壞。</p>
<h2 id="觀察">觀察</h2>
<p>電子書庫總覽 Chrome 擴充功能（book_overview_v1）的匯入功能有覆蓋 / 合併兩種模式；覆蓋模式的語意是「以檔案內容取代現有書庫」— 該模式下匯入空檔等於清空全部資料。設計（<code>src/overview/import-flow-controller.js</code>，W1-049）：</p>
<ol>
<li>覆蓋模式下偵測到匯入內容為空時，彈出專屬確認 Modal 描述後果（現有書庫非空時文案帶具體數字「將清空現有 N 本書」）、使用者明確確認才執行；合併模式不觸發這道確認。</li>
<li>Modal 帶 <code>aria-labelledby</code> / <code>aria-describedby</code>，螢幕閱讀器使用者能取得完整的後果描述。</li>
<li>關鍵設計：<strong>確認 Modal 的 DOM 元件缺失時，視為使用者未確認、預設不清空</strong>。確認機制故障不會讓破壞性操作靜默通過。</li>
</ol>
<h2 id="判讀">判讀</h2>
<ol>
<li>
<p><strong>破壞性操作 gate 是 gate 的一個獨立類型</strong>。認證 / 網路 / 權限 gate 攔「使用者能不能繼續」，破壞性操作 gate 攔「使用者是否理解後果」— 觸發條件不是身分或環境、是操作的破壞半徑（不可逆、影響既有資料、影響範圍大於使用者的直覺預期）。「匯入」聽起來是加法、覆蓋模式的實際語意是取代 — 語意與直覺預期的落差越大、越需要確認。</p>
</li>
<li>
<p><strong>確認機制本身有故障模式</strong>。元件沒渲染、事件沒綁上、動態載入失敗 — 確認 UI 故障時系統要選一個預設方向：執行（把故障當同意）或不執行（把故障當拒絕）。安全預設的原則是倒向不可逆性低的那邊：不清空可以重試匯入、清空無法還原。這與「fail-open vs fail-closed」的安全設計同構。</p>
</li>
<li>
<p><strong>確認對話框的可及性是 gate 有效性的一部分</strong>。看不到後果描述的確認（螢幕閱讀器讀不出 Modal 內容）等於沒有確認 — 使用者按了「確定」但不知道確定了什麼。</p>
</li>
</ol>
<h2 id="策略">策略</h2>
<ol>
<li>
<p><strong>識別破壞性操作</strong>：列出所有會覆蓋 / 刪除 / 取代既有資料的操作，語意與直覺預期有落差的是高風險項（匯入的覆蓋模式 = 取代、同步 = 可能覆蓋、重設 = 清空）。</p>
</li>
<li>
<p><strong>確認 UI 描述後果、不只問「確定嗎」</strong>：帶上具體數字（「將清空現有 N 本書」）讓使用者對照自己的預期。</p>
</li>
<li>
<p><strong>為確認機制設計故障預設</strong>：確認元件不存在 / 事件未觸發 / 回應逾時，一律視為未確認。程式碼層的檢查訊號：確認邏輯的 else / null 分支走向哪邊。</p>
</li>
</ol>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Gate 的必答問題與類型 → <a href="/blog/ux-design/02-gate-fallback/gate-three-questions/" data-link-title="Gate 分類與三問設計法" data-link-desc="每個 gate 設計時問三個問題：成功時做什麼、失敗時做什麼、使用者不知道發生什麼時做什麼">Gate 分類與三問設計法</a></li>
<li>確認機制故障的預設方向 → <a href="/blog/ux-design/knowledge-cards/fail-safe-default/" data-link-title="Fail-Safe Default（安全預設）" data-link-desc="說明保護機制本身故障時系統倒向哪個方向的設計決策 — 預設倒向不可逆性低的那邊，確認 UI 壞掉不該讓破壞性操作靜默通過">Fail-safe 預設</a></li>
<li>通知形式的干擾程度判準（Dialog 的阻斷性是設計需求）→ <a href="/blog/ux-design/06-interaction-feedback/notification-pattern-selection/" data-link-title="通知模式選擇：SnackBar、Dialog、Banner 與 Bottom Sheet" data-link-desc="操作結果該用 SnackBar 閃一下還是彈 Dialog 問使用者 — 干擾程度與是否需要使用者操作的二軸判準，選錯形式的症狀是通知被忽略或流程被打斷">通知模式選擇</a></li>
<li>對照案例（gate 缺 fallback）→ <a href="/blog/ux-design/cases/biometric-only-no-fallback/" data-link-title="U.C2 biometricOnly=true 無密碼 fallback" data-link-desc="Flutter app 的生物辨識設定 biometricOnly: true 阻擋所有非生物辨識認證方式 — Face ID 不可用時使用者直接被擋住，沒有替代路徑">U.C2 biometricOnly 無 fallback</a></li>
</ul>
]]></content:encoded></item></channel></rss>