<?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>值物件 on Tarragon</title><link>https://tarrragon.github.io/blog/tags/%E5%80%BC%E7%89%A9%E4%BB%B6/</link><description>Recent content in 值物件 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 10 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E5%80%BC%E7%89%A9%E4%BB%B6/index.xml" rel="self" type="application/rss+xml"/><item><title>Value Object</title><link>https://tarrragon.github.io/blog/ddd/knowledge-cards/value-object/</link><pubDate>Fri, 10 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/ddd/knowledge-cards/value-object/</guid><description>&lt;p>Value object 的同一性由內容定義：內容相等就是同一個、替換一個內容相同的實例對系統沒有任何影響。要「改」就是造一個新值換上去——不可變。跟 &lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/entity/" data-link-title="Entity" data-link-desc="判斷一個概念該建成 entity 還是 value object 時使用。entity 的同一性由身份定義——欄位全部改變、只要身份參照不變就是同一個。">entity&lt;/a> 相反：entity 的同一性由身份定義。相等性定義本身可以承載業務規則：「什麼算同一個」是業務決策寫進相等性定義的例子。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Value object 有兩個獨立的價值。第一個跟 entity 的判準有關——操作以內容為對象（累加、合併、比對、替換）就用 value object。第二個是語意封閉：把一個領域概念的合法運算限縮成封閉集合——差集裡的每個運算都是等著被誤用的 API。語意封閉的價值獨立於同一性判定、也獨立於容器型別的類別——&lt;a href="https://tarrragon.github.io/blog/ddd/knowledge-cards/data-bag/" data-link-title="Data Bag" data-link-desc="判斷一個型別要不要投資領域模型設計時使用。資料袋是欄位組合全部合法、沒有不變式要守的型別——DTO、API model、UI state 都屬於這一類。">資料袋&lt;/a>裡照樣可以放語意封閉的 value object。&lt;/p>
&lt;h2 id="可觀察訊號">可觀察訊號&lt;/h2>
&lt;p>一個領域概念以裸的通用型別跨模組流通（金額是 double、識別碼是 string）、而它的合法運算遠少於底層型別——語意封閉的價值已成立。封裝後要給原始值一個語意明確的官方出口（見 &lt;a href="https://tarrragon.github.io/blog/ddd/construction-path-design/" data-link-title="建構路徑設計" data-link-desc="工廠表達力不足時缺陷如何被逃生口吸收——逃生口讓正確的修法變不必要、以語意錯誤在下游復發。含原始值官方出口的穩態邊界、封裝擺盪的判讀。">建構路徑設計&lt;/a>）。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>Value object 需要決定相等性定義（哪些欄位參與比對、參與本身就是業務規則）、不可變策略、以及封裝出口。枚舉是 value object 的一種——粒度判準看消費者需求、不看分類系統本身。判準的完整展開見 &lt;a href="https://tarrragon.github.io/blog/ddd/entity-vs-value-object/" data-link-title="entity 與 value object 的判準" data-link-desc="同一個業務概念該建成 entity 還是 value object：判準是「操作需不需要 identity-based 回寫」、而不是概念重要性或有沒有 id 可填。含判準隨生命週期重問的交棒時機、value object 的語意封閉、枚舉分層。">entity 與 value object 的判準&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Value object 的同一性由內容定義：內容相等就是同一個、替換一個內容相同的實例對系統沒有任何影響。要「改」就是造一個新值換上去——不可變。跟 <a href="/blog/ddd/knowledge-cards/entity/" data-link-title="Entity" data-link-desc="判斷一個概念該建成 entity 還是 value object 時使用。entity 的同一性由身份定義——欄位全部改變、只要身份參照不變就是同一個。">entity</a> 相反：entity 的同一性由身份定義。相等性定義本身可以承載業務規則：「什麼算同一個」是業務決策寫進相等性定義的例子。</p>
<h2 id="概念位置">概念位置</h2>
<p>Value object 有兩個獨立的價值。第一個跟 entity 的判準有關——操作以內容為對象（累加、合併、比對、替換）就用 value object。第二個是語意封閉：把一個領域概念的合法運算限縮成封閉集合——差集裡的每個運算都是等著被誤用的 API。語意封閉的價值獨立於同一性判定、也獨立於容器型別的類別——<a href="/blog/ddd/knowledge-cards/data-bag/" data-link-title="Data Bag" data-link-desc="判斷一個型別要不要投資領域模型設計時使用。資料袋是欄位組合全部合法、沒有不變式要守的型別——DTO、API model、UI state 都屬於這一類。">資料袋</a>裡照樣可以放語意封閉的 value object。</p>
<h2 id="可觀察訊號">可觀察訊號</h2>
<p>一個領域概念以裸的通用型別跨模組流通（金額是 double、識別碼是 string）、而它的合法運算遠少於底層型別——語意封閉的價值已成立。封裝後要給原始值一個語意明確的官方出口（見 <a href="/blog/ddd/construction-path-design/" data-link-title="建構路徑設計" data-link-desc="工廠表達力不足時缺陷如何被逃生口吸收——逃生口讓正確的修法變不必要、以語意錯誤在下游復發。含原始值官方出口的穩態邊界、封裝擺盪的判讀。">建構路徑設計</a>）。</p>
<h2 id="設計責任">設計責任</h2>
<p>Value object 需要決定相等性定義（哪些欄位參與比對、參與本身就是業務規則）、不可變策略、以及封裝出口。枚舉是 value object 的一種——粒度判準看消費者需求、不看分類系統本身。判準的完整展開見 <a href="/blog/ddd/entity-vs-value-object/" data-link-title="entity 與 value object 的判準" data-link-desc="同一個業務概念該建成 entity 還是 value object：判準是「操作需不需要 identity-based 回寫」、而不是概念重要性或有沒有 id 可填。含判準隨生命週期重問的交棒時機、value object 的語意封閉、枚舉分層。">entity 與 value object 的判準</a>。</p>
]]></content:encoded></item></channel></rss>