API 表面一致性
本文件定義 OdfKit 公開 API 的長期命名與分層規則。它是實作與審查 時判斷「是否需要一級 C# 物件模型」的依據,並同步排除專案既有文件已確認 不是核心目標的項目。
目前靜態盤點結果見 docs/api-surface-inventory.md。
1. API 分層
| 層級 | 名稱 | 完成線 | 主要入口 |
|---|---|---|---|
| L0 | 封裝 API | 所有 ODF package entry、manifest、media、RDF 與 unknown entry 可存取、儲存與來回讀寫。 | OdfPackage、OdfDocument |
| L1 | 型別化 DOM API | 所有 ODF 1.4 schema element / attribute 可透過產生的 wrapper、型別化屬性 helper 或 schema-aware DOM 存取。 | OdfNode、OdfElement、generated DOM wrappers、OdfTypedDomCoverage |
| L2 | 語意外觀層 API | 常見文件工作流程具備高階 C# 外觀層,不需要呼叫端理解 XML 細節。 | TextDocument、SpreadsheetDocument、PresentationDocument、DrawingDocument、Chart / Formula / Image / Database facade |
| L3 | 外部引擎邊界 | 需要辦公軟體行為、外部環境或不可穩定受控化的能力,只能作為 extension 或 optional validation。 | OdfKit.Extensions.Rendering、LibreOffice / Office interop scripts |
「所有 ODF 功能可用 C# 存取」表示 L0 + L1 必須完整;「所有常見工作流程有 一級 C# 物件模型」表示 L2 必須覆蓋高價值使用情境。L3 不屬於核心 API 完成條件。
L2 外觀層設計基準
- 高階物件必須直接組合既有
OdfNode/typed DOM 與 package resource,不維護另一份平行狀態。 ODF Toolkit 的舊 Simple API 因大量重複 ODFDOM 程式碼及脫節的清單模型而被棄用;OdfKit 不採用相同 fork 式架構。 - 集合公開為唯讀快照或受控 editor;新增、更新、移除與清除使用具名方法,不讓呼叫端直接
修改 backing list。Apache POI 的
XDDFChartData同樣要求使用addSeries/removeSeries(index),並明確警告直接修改回傳 List 可能破壞文件;LibreOffice Chart2XDataSeriesContainer亦分別定義 add/get/set/remove。 - 外觀層完成度以工作流程與逐操作證據衡量,不以公開型別或方法總數衡量。若 ODF 規格本身
限制結構(例如嚴格 ODI 僅有一個
draw:frame且其中僅有一個draw:image),不得為增加 API 數量而虛構圖層、群組或其他 schema 不存在的模型。
參考:ODF Toolkit Simple API deprecation、 Apache POI XDDFChartData、 LibreOffice XDataSeriesContainer、 OASIS ODF 1.4 Part 3。
次要格式深度工作流
ODC、ODB、ODF 與 ODI 的高階 API 以「能完成安全工作流」而非方法數量判定深度:
| 格式 | 已完成的受控工作流 | 邊界 |
|---|---|---|
| ODC | 序列新增、editor 更新、移除、清除、重排,以及 immutable snapshot 的單筆/批次套用;操作既有節點並保留 style、已知子項與未知內容。 | 不暴露可直接修改的 backing list。 |
| ODB | table/query/form/report/data-source setting 的查找、新增、desired-state 更新、移除與清除;schema 欄位、主鍵、外鍵與索引只透過受控 editor 修改。 | 只管理 ODF 資料庫描述,不連線或執行 SQL。 |
| ODF | 真正唯讀的 immutable token tree、predicate/factory 單一/全樹替換、屬性移除/清除、文件層移除與清除。 | 全樹替換不再次處理 replacement subtree;移除必要複合子節點時以空 mrow 維持結構。 |
| ODI | FindImageFrame nullable lookup、bytes 單筆/批次替換、layout/metadata、rotation、crop、filter、批次更新與檢查報告。 |
strict ODF 1.4 只有單一 draw:frame/draw:image,不建立虛構的多圖文件模型。 |
集合重排、desired-state 更新與 immutable tree rewrite 都必須保留無關及 foreign namespace 內容;公開 API 基線與 round-trip 測試是此工作流契約的一部分。
上述四項是高階 API 結構性加厚的完成線。完成線之後,不再以公開方法數量、 競品型別數量或 schema 元素數量驅動 facade 擴張;新高階 API 必須由可重現的真實使用案例、 ODF 規格更新或已確認缺陷觸發,並在同一變更中補齊工作流證據。Options、結果 DTO、 公式 AST 與 evaluation context 的可修改集合不屬於文件 DOM backing collection, 不得被機械改寫成 editor。
2. 命名契約
新增或破壞性重新命名公開 API 時,請使用以下規則;本專案尚未正式發佈 套件,因此允許一次性重構儲存庫內所有使用點,不保留舊名稱 shim。
| 形狀 | 用途 | 回傳語意 |
|---|---|---|
Create / Load / Save / Validate |
文件生命週期。 | 依既有文件 API 慣例。 |
Builder() |
Fluent 建立入口。 | 回傳 builder;builder 使用 With* 設定狀態、Add* 新增內容。 |
Add* |
新增節點、實體或 relation。 | 回傳新增項目或 void,不得表示查找。 |
Get* |
讀取快照、摘要、集合或不可變資訊。 | 集合讀取統一使用 Get* 或屬性。 |
Set* |
設定或覆寫單一狀態。 | 回傳更新後外觀層或 void。 |
Update* |
依回呼、request 或批次規則修改既有內容。 | 回傳變更數量或更新結果。 |
Remove* |
移除指定內容。 | 不存在時優先回傳 false;輸入無效才拋例外。 |
Find* |
查找單一可選項。 | 找不到回傳 null。不得用於集合。 |
Try* |
嘗試取得或執行可能失敗的操作。 | 回傳 bool,搭配 out 或明確結果。 |
List* 不作為新的公開 API 命名。若需要列出集合,使用 Get* 或唯讀集合屬性。
低階 DOM / 型別化屬性 accessor 可保留 Get*,即使回傳 nullable;這些 API
描述的是「讀取目前節點或屬性的值」,不是依領域 key 查找語意物件。
例如 OdfNode.GetAttribute、OdfElement.Get*AttributeValue 與產生的 wrapper
屬性 setter 內部使用的 remove helper,不適用 L2 外觀層的 Find* 規則。
Clear* 表示清空一段可重建狀態或重設目前設定,可維持 no-op 命令語意與
void 回傳;若 API 需要表達「移除某個指定項目是否成功」,應提供或改用
Remove*,並遵守 bool 成功/失敗語意。
Database 與 Image 目前不強制補 Builder() 入口。Database 的主要 L2 工作流程
是 table / query / form / report CRUD 與 schema 設定;Image 的主要 L2 工作流程
是載入、框架、濾鏡與圖片 bytes 變更。這兩者沒有足以降低複雜度的常見 fluent
建立流程時,可保留 Create / Load / Set* / Add* / Find* 組合。
已套用的破壞性重新命名
第一批已將集合型 Find* 改為 Get*,以符合「Find* 只回傳單一可選項」:
| 範圍 | 新名稱 | 理由 |
|---|---|---|
| Schema name-class collection query | GetMatchingNameClasses |
回傳多個 name class。 |
| RDF triple collection query | GetTriples |
回傳多個 RDF triple。 |
| Math token collection query | GetAll |
回傳多個 Math token。 |
| Workbook formula-cell predicate query | GetFormulaCells overload |
回傳多個公式儲存格。 |
| Worksheet formula-cell predicate query | GetFormulaCells overload |
回傳多個公式儲存格。 |
| Tracked-change affected-node query | GetAffectedNodesForFormatChange |
回傳多個 DOM 節點。 |
第二批已將語意明確的單一 nullable lookup 從 Get* 改為 Find*:
| 範圍 | 新名稱 | 理由 |
|---|---|---|
| Workbook sheet lookup by name | FindSheet |
依名稱查找單一工作表,找不到回傳 null。 |
| Formula annotation lookup by encoding | FindAnnotation |
依 encoding 查找單一 MathML annotation,找不到回傳 null。 |
| Spreadsheet cell annotation lookup | FindAnnotation |
查找單一儲存格批注,找不到回傳 null。 |
第三批已統一指定項目移除 API 的成功/失敗語意:
| 範圍 | 回傳語意 |
|---|---|
| Package entry removal | 移除 entry、manifest 項目或 entry order 項目時回傳 true。 |
| DOM attribute / child removal | 目標存在且已移除時回傳 true;目標不屬於目前節點或不存在時回傳 false。 |
| Spreadsheet hyperlink / annotation removal | 移除既有內容時回傳 true;沒有可移除內容時回傳 false。 |
| Spreadsheet row / column page break removal | 目標分頁符存在且已移除時回傳 true;不存在時不建立新節點並回傳 false。 |
| Presentation placeholder removal | 至少移除一個指定型態的 placeholder 時回傳 true。 |
第四批已將依 key、name 或 dimension 查找單一 nullable 項目的 Get* 改為 Find*:
| 範圍 | 新名稱 |
|---|---|
| Database query optional children | FindQueryOrderStatement、FindQueryFilterStatement、FindQueryUpdateTable |
| Chart series optional children | FindDataLabels、FindErrorIndicator、FindRegressionCurve、FindMeanValue |
| Chart document optional lookups | FindSeriesDataLabels、FindAxisInfo、FindAxisTitle |
| Presentation page layout lookup | FindPresentationPageLayout |
| Image frame filter lookup | FindImageFilter |
| Package entry encryption lookup | FindEntryEncryptionInfo |
| Custom metadata property lookup | FindCustomProperty |
3. 明確排除的目標
下列項目已由專案文件確認不屬於核心 API 目標,不應因 API 一致性工作而被 重新納入:
- 完整物理分頁排版器、像素級高保真渲染與所有 LibreOffice 版本的像素一致性。
- 試算表完整公式重算、volatile function、多使用者計算狀態與任意外部連結資料來源。 Pivot 已提供有界重算、分組、總計與 Show Values As;完整 office suite 的互動式 pivot cache、slicer 與視覺化編輯器仍不在核心範圍。
- SmartArt 智慧圖形、複雜形狀布局器與 Office 專屬 layout 相容層。
- 完整多人協同演算法、任意衝突合併、undo stack、OT、CRDT、完整 drawing DOM、動態表格擴張與 header/footer/note selection 完整語意。
- 通用 RELAX NG validator;核心 validator 只服務內建 ODF profile gate。
- 外部 Office / LibreOffice / PDF pixel diff / large corpus 驗收進入主 CI Smoke。
- 不可再散布 corpus、商業 SDK 輸出或外部專案原始碼作為 golden。
相關邊界來源:docs/udx-non-goals.md、docs/rendering-backend-deployment.md、
docs/libreoffice-interop-matrix.md、docs/ci-cd.md、
docs/provenance/clean-room-source-index.md。
4. 文件與相容性要求
- 每次 breaking rename 必須同步更新 repo 內所有使用點,包含 tests、samples、docs、 tools、CLI 與 extensions。
- 若舊名稱存在於 corpus fixture、JSON wire shape 或外部格式資料中,不改資料格式; 只改 C# API。
- 手寫 public / protected API 必須具備雙語 XML 文件。generated DOM wrapper 可由 generator 層統一豁免或改善,不進行逐檔手改。
- 新 API 不得以
#pragma warning disable 1591規避文件要求。