<?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/%E7%A8%8B%E5%BC%8F%E7%A2%BC%E7%94%9F%E6%88%90/</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/%E7%A8%8B%E5%BC%8F%E7%A2%BC%E7%94%9F%E6%88%90/index.xml" rel="self" type="application/rss+xml"/><item><title>freezed</title><link>https://tarrragon.github.io/blog/flutter/knowledge-cards/freezed/</link><pubDate>Fri, 10 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/flutter/knowledge-cards/freezed/</guid><description>&lt;p>freezed 是 Dart 生態中最廣泛使用的 immutable data class 程式碼生成器。標記 &lt;code>@freezed&lt;/code> 後，它自動產生 &lt;a href="https://tarrragon.github.io/blog/flutter/knowledge-cards/copywith/" data-link-title="copyWith" data-link-desc="物件的逐欄位覆寫方法在什麼時候是正確工具、什麼時候是逃生口時使用。copyWith 對資料袋語意清晰、對有領域方法的 entity 是繞過不變式的逃生口。">copyWith&lt;/a>、&lt;code>==&lt;/code> / &lt;code>hashCode&lt;/code>、&lt;code>toString()&lt;/code>、以及 sealed union（多態分支的 exhaustive switch）。它把「寫一個 immutable class 需要的 boilerplate」壓到接近零。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>freezed 的預設路徑對所有型別一視同仁——它不區分&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>和有領域方法的 &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>。每個被 &lt;code>@freezed&lt;/code> 標記的 class 都會得到全欄位的 public &lt;a href="https://tarrragon.github.io/blog/flutter/knowledge-cards/copywith/" data-link-title="copyWith" data-link-desc="物件的逐欄位覆寫方法在什麼時候是正確工具、什麼時候是逃生口時使用。copyWith 對資料袋語意清晰、對有領域方法的 entity 是繞過不變式的逃生口。">copyWith&lt;/a>、包含狀態欄位與稽核欄位。這是生態推力：規範說「請走領域方法」、工具預設給全欄位 copyWith——規範和預設衝突時、預設會贏。&lt;/p>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>在 entity 上使用 freezed 時、需要額外措施收窄 copyWith 的開放程度：把 copyWith 改 private、或從參數列移除受約束的欄位。freezed 的 sealed union 在枚舉分層上有正面價值——exhaustive switch 讓「忘記決定新成員歸哪類」在編譯期就走不通。結構細節見 &lt;a href="https://tarrragon.github.io/blog/work-log/dart_freezed_anatomy/" data-link-title="Freezed 的三層結構解剖：with、_$、以及更好懂的替代路徑" data-link-desc="freezed `class X with _$X implements Y` 的分層結構解剖：`with` 與 `_$` 各自的角色、沒有 freezed 怎麼手做、中間投影物件 vs DTO 直接 implements 的維護取捨。">Freezed 三層結構解剖&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>freezed 是 Dart 生態中最廣泛使用的 immutable data class 程式碼生成器。標記 <code>@freezed</code> 後，它自動產生 <a href="/blog/flutter/knowledge-cards/copywith/" data-link-title="copyWith" data-link-desc="物件的逐欄位覆寫方法在什麼時候是正確工具、什麼時候是逃生口時使用。copyWith 對資料袋語意清晰、對有領域方法的 entity 是繞過不變式的逃生口。">copyWith</a>、<code>==</code> / <code>hashCode</code>、<code>toString()</code>、以及 sealed union（多態分支的 exhaustive switch）。它把「寫一個 immutable class 需要的 boilerplate」壓到接近零。</p>
<h2 id="概念位置">概念位置</h2>
<p>freezed 的預設路徑對所有型別一視同仁——它不區分<a href="/blog/ddd/knowledge-cards/data-bag/" data-link-title="Data Bag" data-link-desc="判斷一個型別要不要投資領域模型設計時使用。資料袋是欄位組合全部合法、沒有不變式要守的型別——DTO、API model、UI state 都屬於這一類。">資料袋</a>和有領域方法的 <a href="/blog/ddd/knowledge-cards/entity/" data-link-title="Entity" data-link-desc="判斷一個概念該建成 entity 還是 value object 時使用。entity 的同一性由身份定義——欄位全部改變、只要身份參照不變就是同一個。">entity</a>。每個被 <code>@freezed</code> 標記的 class 都會得到全欄位的 public <a href="/blog/flutter/knowledge-cards/copywith/" data-link-title="copyWith" data-link-desc="物件的逐欄位覆寫方法在什麼時候是正確工具、什麼時候是逃生口時使用。copyWith 對資料袋語意清晰、對有領域方法的 entity 是繞過不變式的逃生口。">copyWith</a>、包含狀態欄位與稽核欄位。這是生態推力：規範說「請走領域方法」、工具預設給全欄位 copyWith——規範和預設衝突時、預設會贏。</p>
<h2 id="設計責任">設計責任</h2>
<p>在 entity 上使用 freezed 時、需要額外措施收窄 copyWith 的開放程度：把 copyWith 改 private、或從參數列移除受約束的欄位。freezed 的 sealed union 在枚舉分層上有正面價值——exhaustive switch 讓「忘記決定新成員歸哪類」在編譯期就走不通。結構細節見 <a href="/blog/work-log/dart_freezed_anatomy/" data-link-title="Freezed 的三層結構解剖：with、_$、以及更好懂的替代路徑" data-link-desc="freezed `class X with _$X implements Y` 的分層結構解剖：`with` 與 `_$` 各自的角色、沒有 freezed 怎麼手做、中間投影物件 vs DTO 直接 implements 的維護取捨。">Freezed 三層結構解剖</a>。</p>
]]></content:encoded></item></channel></rss>