程式 repo 結構檢查與第一版實作範圍盤點
1. 文件目的
本文件整理進入 MySqlSchemaInspector Query Builder / Row Mapper 第一版實作前,對程式 repo 的實際結構、既有 contract、測試位置與停止線的檢查結果。
本次只做結構盤點與範圍確認,尚未修改程式 repo,尚未新增套件,尚未修改 .csproj,尚未連線 MySQL,也尚未讀取真實 information_schema。
2. 檢查基準
| 項目 | 內容 |
|---|---|
| 程式 repo | hs-device-control-template |
| 分支 | poc/nmodbus-tcp |
| 檢查版本 | ac52376 接入 Schema Initializer ConsoleHost DryRun 顯示 |
| 工作區狀態 | 檢查時為乾淨狀態 |
| 文件 repo | hs-device-control-template-docs |
| 本次性質 | 文件盤點,不修改程式碼 |
3. 已確認的程式結構
目前 Schema Automation 相關程式集中在 src/HS.DeviceControl.Core/Schema。
| 區域 | 既有內容 | 判斷 |
|---|---|---|
| Schema model | SchemaDefinition、TableDefinition、ColumnDefinition、IndexDefinition | 已足夠承接真實 DB metadata snapshot |
| Attribute parser | DbTableAttribute、DbColumnAttribute、DbIndexAttribute、SchemaDefinitionParser | 已能從 C# class 產生 expected schema |
| SQL generator | MySqlSchemaSqlGenerator、MySqlSchemaSqlGeneratorOptions | 已能產生 create / alter / dry run SQL |
| Inspector abstraction | ISchemaInspector、SchemaInspectRequest、SchemaInspectResult | 已有抽象介面與 mock inspector |
| Dry run / initializer | SchemaDryRunPlanner、SchemaInitializer | 已能用 expected schema 與 inspected schema 產生 dry run 結果 |
| 測試專案 | tests/HS.DeviceControl.Core.Tests | 已有 Schema parser、SQL generator、inspector、dry run、initializer 測試 |
| Infrastructure project | 尚未存在 | 第一版不應新增 Infrastructure project;若要新增需另行確認 |
4. 已確認的既有 contract
4.1 Inspector 介面
目前 inspector contract 已固定為:
SchemaInspectResult Inspect(SchemaInspectRequest request);
第一版 Query Builder / Row Mapper 不應修改此簽章。
4.2 Request 已具備的資訊
SchemaInspectRequest 已包含:
| 欄位 | 用途 |
|---|---|
DatabaseName | 指定要檢查的 database / schema |
ExpectedTables | 限定要讀取的 table 清單 |
IncludeIndexes | 是否讀取 index metadata |
IncludeComments | 是否讀取 table / column comment |
CorrelationId | 追蹤本次檢查 |
第一版不需要新增 request 欄位。
4.3 Result 已具備的資訊
SchemaInspectResult 已包含:
| 欄位 | 用途 |
|---|---|
Success | 是否成功 |
Schema | 實際讀到的 schema snapshot |
Warnings | metadata 不完整或需人工檢查的提醒 |
Error | 標準錯誤資訊 |
TimeTakenMs | 耗時 |
Source | 來源,例如 Mock 或未來 MySQL |
第一版不需要修改 result contract。
5. 可安全實作的第一版範圍
若使用者確認可進入程式 repo 實作,第一版建議仍維持「不依賴真實 DB 的純程式元件」。
| 元件 | 建議位置 | 職責 |
|---|---|---|
MySqlSchemaInspectorQueryBuilder | src/HS.DeviceControl.Core/Schema | 產生 information_schema table / column / index 查詢字串與參數名稱 |
MySqlSchemaQuery | src/HS.DeviceControl.Core/Schema | 保存 SQL 與參數名稱,方便測試 |
MySqlTableMetadataRow | src/HS.DeviceControl.Core/Schema | 承接 table metadata row |
MySqlColumnMetadataRow | src/HS.DeviceControl.Core/Schema | 承接 column metadata row |
MySqlIndexMetadataRow | src/HS.DeviceControl.Core/Schema | 承接 index metadata row |
MySqlSchemaMetadataMapper | src/HS.DeviceControl.Core/Schema | 將 metadata row 轉成 schema model |
MySqlSchemaSnapshotAssembler | src/HS.DeviceControl.Core/Schema | 將 table / column / index row 組合成 SchemaDefinition |
建議測試放在:
| 測試檔 | 驗證重點 |
|---|---|
MySqlSchemaInspectorQueryBuilderTests.cs | SQL 限制 TABLE_SCHEMA = @DatabaseName、table filter 參數化、排序穩定、不產生 DDL |
MySqlSchemaMetadataMapperTests.cs | MySQL 5.6.2 欄位型態、nullable、comment、primary key metadata mapping |
MySqlSchemaSnapshotAssemblerTests.cs | table / column / index row 組裝、missing table warning、index 欄位排序 |
6. 需先確認的實作策略
這次盤點後發現,第一版實作最大的決策點不是 SQL 內容,而是「helper class 要用 public 還是 internal」。
| 方案 | 優點 | 風險 |
|---|---|---|
方案 A:helper class 設為 public | 測試最直接,不需新增 assembly metadata | 會擴大 public API surface,後續較難收斂 |
方案 B:helper class 設為 internal,並使用 InternalsVisibleTo | 對外 contract 較乾淨,符合不擴大 public API 的方向 | 需要新增 assembly metadata;雖不改 .csproj,仍屬專案層級設定,建議先確認 |
方案 C:全部藏在 MySqlSchemaInspector private method | public API 不擴大 | 測試粒度差,之後導入真實 DB 時風險較高 |
建議採用方案 B:internal helper + InternalsVisibleTo。
但因這會新增 assembly metadata,建議在正式實作前先取得使用者確認。
7. 不建議現在做的事情
| 不做項目 | 原因 |
|---|---|
新增 MySqlConnector | 會修改套件依賴與 .csproj,需另行確認 |
| 新增 Infrastructure project | 會改變專案結構,需另行確認 |
| 連線 MySQL | 涉及真實環境、帳密與網路設定 |
讀取真實 information_schema | 需要 DB 連線與套件 |
| 執行 DDL / ALTER TABLE | 會修改資料庫,必須另行確認與備份策略 |
修改 ISchemaInspector public method 簽章 | 會改變既有 contract |
| 修改 ConsoleHost 啟動方式 | 屬於專案啟動方式變更,需另行確認 |
8. 目前判斷
目前程式 repo 結構可以支援下一步進入「不連 DB 的 Query Builder / Row Mapper / Snapshot Assembler 第一版實作」。
但若要同時維持 public API 乾淨與可測試性,建議先確認是否接受新增 InternalsVisibleTo。若不接受,則需改採 public helper 或降低測試粒度。
9. 建議下一步
建議下一步先由使用者確認 helper class 策略:
- 採用方案 B:
internal helper + InternalsVisibleTo,再進入程式 repo 實作。 - 若不想新增 assembly metadata,採用方案 A:public helper,但需接受 public API surface 增加。
- 若希望最保守,先只實作 Query Builder public class,不做 mapper / assembler。
建議選擇方案 B,因為它最符合「不任意擴大對外 contract」的方向,也最利於後續維護。