<?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>Adapter on Tarragon</title><link>https://tarrragon.github.io/blog/tags/adapter/</link><description>Recent content in Adapter on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 13 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/adapter/index.xml" rel="self" type="application/rss+xml"/><item><title>Adapter</title><link>https://tarrragon.github.io/blog/ddd/knowledge-cards/adapter/</link><pubDate>Mon, 13 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/ddd/knowledge-cards/adapter/</guid><description>&lt;p>adapter 是 &lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/port/" data-link-title="Port" data-link-desc="判斷介面該宣告在哪一層、依賴方向該朝哪時使用。port 是 domain 對外宣告的介面——需求用領域語言說完、技術細節留在實作端。">port&lt;/a> 的具體實作：把領域宣告的需求翻譯成某項技術的操作——SQLite 的查詢、HTTP 的請求、檔案系統的讀寫。技術細節被擋在六角形之外的位置就是這裡：領域只看得見 port、看不見 adapter。adapter 在 &lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/composition-root/" data-link-title="Composition Root" data-link-desc="依賴組裝、路由註冊該集中在哪、組裝斷裂去哪檢查時使用。composition root 是應用程式唯一的組裝起點——DI、路由、事件接線的集中處。">composition root&lt;/a> 被插上 port；測試裡的 mock 是 adapter 的替身。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>adapter 有兩側。driven adapter 被領域呼叫（資料庫、外部服務的實作）；driving adapter 呼叫領域（UI 事件處理、API handler）。兩側的共同責任是翻譯：領域語言與技術語言在這裡互換、不讓任何一邊的詞彙滲到對面。adapter 對外接的介面是 &lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/port/" data-link-title="Port" data-link-desc="判斷介面該宣告在哪一層、依賴方向該朝哪時使用。port 是 domain 對外宣告的介面——需求用領域語言說完、技術細節留在實作端。">port&lt;/a>、兩者插上的位置是 &lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/composition-root/" data-link-title="Composition Root" data-link-desc="依賴組裝、路由註冊該集中在哪、組裝斷裂去哪檢查時使用。composition root 是應用程式唯一的組裝起點——DI、路由、事件接線的集中處。">composition root&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>實作類 import 框架套件、以技術命名（SqliteBookRepository），是 adapter 各安其位的訊號。領域規則出現在 adapter 裡（折扣計算寫在 repository、狀態判斷寫在 handler）是反向滲透——規則離開了領域模型、&lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/invariant/" data-link-title="Invariant" data-link-desc="領域模型的約束規則落在哪一層時使用。不變式是在物件整個生命週期都必須為真的業務規則——狀態只能沿流程轉換、被同一條規則綁住的欄位必須一起換。">invariant&lt;/a> 的強制位置跟著失守。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>adapter 寫完、測試通過，只證明它自己行為正確；它有沒有被插上 port、插的是不是它，是組裝層的問題。接線的證言與強制層選擇見 &lt;a href="https://tarrragon.github.io/blog/ddd/composition-root-reachability/" data-link-title="組裝層的可達性" data-link-desc="行為測試全綠、功能在實機上沒有入口的失效形態出現時使用。mock 換掉的正是組裝，組裝完成與否在行為測試裡沒有證言；把可達性當成組裝層的不變式，在測試、發版與設計文件各給一個強制點。">組裝層的可達性&lt;/a>。adapter 作為變更偵測機制的具體歸屬案例（寫入點 emit vs 儲存層 hook 的選型）見 &lt;a href="https://tarrragon.github.io/blog/ddd/observation-outlet-responsibility-split/" data-link-title="觀測出口的職責三分" data-link-desc="repository 要補「資料變了」的推送能力、卻不確定 Stream 介面放 domain 算不算洩漏時使用。歸屬判準是介面用什麼語言表達、不是需求來自誰：契約歸 domain、變更偵測歸 infrastructure、框架訂閱歸組裝層。">觀測出口的職責三分&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>adapter 是 <a href="/blog/ddd/knowledge-cards/port/" data-link-title="Port" data-link-desc="判斷介面該宣告在哪一層、依賴方向該朝哪時使用。port 是 domain 對外宣告的介面——需求用領域語言說完、技術細節留在實作端。">port</a> 的具體實作：把領域宣告的需求翻譯成某項技術的操作——SQLite 的查詢、HTTP 的請求、檔案系統的讀寫。技術細節被擋在六角形之外的位置就是這裡：領域只看得見 port、看不見 adapter。adapter 在 <a href="/blog/ddd/knowledge-cards/composition-root/" data-link-title="Composition Root" data-link-desc="依賴組裝、路由註冊該集中在哪、組裝斷裂去哪檢查時使用。composition root 是應用程式唯一的組裝起點——DI、路由、事件接線的集中處。">composition root</a> 被插上 port；測試裡的 mock 是 adapter 的替身。</p>
<h2 id="概念位置">概念位置</h2>
<p>adapter 有兩側。driven adapter 被領域呼叫（資料庫、外部服務的實作）；driving adapter 呼叫領域（UI 事件處理、API handler）。兩側的共同責任是翻譯：領域語言與技術語言在這裡互換、不讓任何一邊的詞彙滲到對面。adapter 對外接的介面是 <a href="/blog/ddd/knowledge-cards/port/" data-link-title="Port" data-link-desc="判斷介面該宣告在哪一層、依賴方向該朝哪時使用。port 是 domain 對外宣告的介面——需求用領域語言說完、技術細節留在實作端。">port</a>、兩者插上的位置是 <a href="/blog/ddd/knowledge-cards/composition-root/" data-link-title="Composition Root" data-link-desc="依賴組裝、路由註冊該集中在哪、組裝斷裂去哪檢查時使用。composition root 是應用程式唯一的組裝起點——DI、路由、事件接線的集中處。">composition root</a>。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>實作類 import 框架套件、以技術命名（SqliteBookRepository），是 adapter 各安其位的訊號。領域規則出現在 adapter 裡（折扣計算寫在 repository、狀態判斷寫在 handler）是反向滲透——規則離開了領域模型、<a href="/blog/ddd/knowledge-cards/invariant/" data-link-title="Invariant" data-link-desc="領域模型的約束規則落在哪一層時使用。不變式是在物件整個生命週期都必須為真的業務規則——狀態只能沿流程轉換、被同一條規則綁住的欄位必須一起換。">invariant</a> 的強制位置跟著失守。</p>
<h2 id="設計責任">設計責任</h2>
<p>adapter 寫完、測試通過，只證明它自己行為正確；它有沒有被插上 port、插的是不是它，是組裝層的問題。接線的證言與強制層選擇見 <a href="/blog/ddd/composition-root-reachability/" data-link-title="組裝層的可達性" data-link-desc="行為測試全綠、功能在實機上沒有入口的失效形態出現時使用。mock 換掉的正是組裝，組裝完成與否在行為測試裡沒有證言；把可達性當成組裝層的不變式，在測試、發版與設計文件各給一個強制點。">組裝層的可達性</a>。adapter 作為變更偵測機制的具體歸屬案例（寫入點 emit vs 儲存層 hook 的選型）見 <a href="/blog/ddd/observation-outlet-responsibility-split/" data-link-title="觀測出口的職責三分" data-link-desc="repository 要補「資料變了」的推送能力、卻不確定 Stream 介面放 domain 算不算洩漏時使用。歸屬判準是介面用什麼語言表達、不是需求來自誰：契約歸 domain、變更偵測歸 infrastructure、框架訂閱歸組裝層。">觀測出口的職責三分</a>。</p>
]]></content:encoded></item></channel></rss>