フィールド命名と可視性ルールをどう設計・レビューすべきか

Goでは構造体のフィールド名が大文字で始まる場合は外部からアクセス可能(エクスポート)小文字で始まる場合は内部専用(非エクスポート)となる。
この仕様は非常にシンプルで直感的だが、フィールドの設計意図・初期化戦略・カプセル化・テスト戦略などに広く影響する。

この記事では、技術仕様としての可視性を出発点に、レビューアーとしてその設計意図の妥当性をどう読み解き、指摘すべきかを解説していく。


1. 構造体フィールドの可視性と設計意図の整合

type User struct {
    ID   string // 外部からアクセス可能
    name string // 内部専用
}

Goの仕様上、IDは外部から直接アクセス可能な設計となり、nameはパッケージ内でのみ利用される。

可視性を付ける=アクセスを許容する=依存関係を増やす、という設計的選択になる。
その意図があいまいなままフィールドをエクスポートすると、構造の変更が将来的に困難になる。

type User struct {
    ID string
}
@Reviewer
`ID`がエクスポートされていますが、パッケージ外部での利用が前提ですか?もし内部のみで完結する場合、非公開に変更すべきです。

2. JSONタグと非エクスポートフィールドの非整合

type User struct {
    id string `json:"id"`
}
@Reviewer
`json`タグを指定していますが、フィールドが非エクスポートのため `encoding/json` によるシリアライズ対象になりません。大文字に変更するか、構造そのものを見直しましょう。

encoding/jsonyaml などのマルシャリング系ライブラリは、可視性(大文字)を前提に動作する
タグの有無ではなくフィールドのエクスポート状態が実際の対象可否を決める。

改善後:シリアライズ対象として意図を明示
type User struct {
    ID string `json:"id"`
}

3. フィールド名に込められた責務が伝わるか

type User struct {
    Name string
    Info string
}
@Reviewer
`Info` という名前が抽象的すぎます。何の情報なのかが構造体から読み取れず、責務が曖昧になります。より具体的な命名に変更しましょう。

「Email」「PhoneNumber」「Profile」など、ドメインに即した語彙を用いることで、構造体の意図が読み取りやすくなる。

改善後:語彙による責務の明示
type User struct {
    Name    string
    Profile string
}

4. テスト容易性と可視性のトレードオフ

type config struct {
    secret string
}
@Reviewer
フィールドが非エクスポートになっていますが、ブラックボックステストや外部依存の分離に支障が出ないか検討してください。

Goでは、同一パッケージ内の_test.goファイルからは非エクスポートフィールドにもアクセス可能。
しかし将来的にモジュールが別パッケージに分離された場合、非公開設計がテストの足かせになるケースがある。

設計時には「テストの粒度」と「再利用範囲」の両面から、可視性を判断する必要がある。
セキュリティ上の理由など、非公開である妥当性をコメントで明示することでレビュー判断がスムーズになる。


5. 初期化と可視性:New関数の必然性

type Config struct {
    port int
}

func NewConfig(p int) *Config {
    return &Config{port: p}
}

非エクスポートのフィールドは、構造体リテラルで初期化できない。
代わりにNew関数を通じて制御された初期化を強制する設計が定石となる。

非公開フィールドによるカプセル化と、New関数による制御された初期化の組合せは、意図と構造が一致しており理想的。

改善後:初期化ロジックと責務の一致
type Config struct {
    port int
}

func NewConfig(port int) *Config {
    // ポートのバリデーションなど初期化処理が可能
    return &Config{port: port}
}

6. 可視性・命名のレビュー観点チェックリスト

観点 チェック項目
エクスポート設計 公開フィールドに正当な理由があるか?利用側が想定されているか?
JSON等タグとの整合 タグだけ付けて実際は非公開になっていないか?
命名の粒度 語彙が抽象的すぎないか?構造の責務が読み取れるか?
テストと公開範囲 パッケージ分離・再利用を想定して、可視性が適切に設定されているか?
初期化と責務 非公開設計の場合に New 関数など初期化ロジックが準備されているか?

あとがき:フィールド命名と可視性が構造の“真意”を語る

構造体のフィールド定義は、「このデータは誰がどのように使うのか?」という設計上の会話そのものである。
単なる構文の都合でエクスポートしたり、便宜的に名前をつけるといった設計は、将来的に保守性と再利用性を大きく損なう。

レビューアーは、次のような観点を意識する必要がある:

  • このフィールドは本当に外部からアクセスされるべきか?
  • 名前から構造体の責務と設計意図が読み取れるか?
  • フィールドの可視性とテスト・初期化・利用範囲が整合しているか?

フィールド命名と可視性の設計は、構造の「外形」ではなく「意図」を言語化する行為である。
その意図を読み取り、設計の矛盾をレビューで解きほぐせるかどうかが、レビューアーの腕の見せ所となる。