⏱ 読了目安: 約5分
- ゆめみが公開した「declscope」は、Goのフラットパッケージ内にファイル単位のprivateスコープを導入する静的解析ツールである。
- AIエージェントが生成するコードの越境を検知し、//declscope:package等のディレクティブで明示的な共有を強制する。
- エンジニアは既存のパッケージ構造を維持したまま、AIによる負債の蓄積をコンパイルレベルで防ぐことが可能になる。
AI時代のGoコード品質と「フラットパッケージ」の限界
Go言語は「誰が書いても同じようになる」という素朴さを美徳としてきた。三項演算子もメタプログラミングも排除し、if err != nilを繰り返すそのスタイルは、人間が手で書く時代には冗長という代償を伴っていた。しかし、AIエージェントがコードの大部分を生成する現在、この「素朴さ」は強力な武器へと変貌を遂げた。生成されたコードが読みやすく、差分が追えるという性質は、AIが既存のコードベースから書き方を推測する上で極めて重要だからだ。
だが、ここで我々シニアエンジニアが直面するのは、AIには解決できない「大局的な整理」の問題である。Goにおいてコードを整理する唯一の道具はパッケージだが、Goのパッケージは「少なく、大きく」というフラットな構成が推奨されることが多い。このフラットパッケージ思想は、循環参照を避け、依存関係をシンプルに保つための知恵だが、同時に「ファイル単位のprivate」が存在しないという致命的な弱点も抱えている。結果として、パッケージ内のすべてのunexportedな宣言は、パッケージ内の全ファイルからアクセス可能となってしまう。
AIエージェントは、この「パッケージ内ならどこからでもアクセス可能」という仕様を、規約を無視して最大限に活用する。CLAUDE.mdにどれほど厳格なルールを記述しても、それは確率的にしか機能しない。エージェントは目の前に見えているAPIを素直に呼び出すだけだ。その結果、本来は特定のファイル内だけで完結すべきヘルパー関数が、パッケージ全体に散らばり、意図しない依存関係がスパゲッティのように絡み合う。この負債の蓄積速度は、人間が書くスピードを遥かに凌駕する。我々が今必要としているのは、自然言語の規約ではなく、コンパイラやLinterによって強制される「決定論的な境界」なのである。
declscopeによる境界の強制とAIへの処方箋
ゆめみが公開した「declscope」は、まさにこの「AIによる越境」を物理的に防ぐためのツールだ。このツールは、パッケージをフラットに保ったまま、ファイル単位で名前空間(namespace)を定義し、その境界を越えたアクセスを検知する。使い方は極めてシンプルで、go install後にdeclscope ./...を実行するだけだ。これにより、AIが生成したコードが本来触れるべきではないprivateな関数やフィールドにアクセスした際、即座に警告が発せられる。
declscopeが提供する主なルールは以下の通りである。
| ルール | 概要 | 既定値 |
|---|---|---|
| boundary | namespace間のアクセス制限 | ON |
| qualify | シンボル名へのnamespace包含確認 | OFF |
| surplus | 共有宣言の必要性チェック | strict |
| unused | 不要なディレクティブのチェック | strict |
特に重要なのはboundaryルールだ。例えば、user_repository.goで定義されたnormalizeEmail関数が、order_repository.goから呼び出された場合、declscopeは「privateな関数がnamespaceを越えて使用されている」と警告する。この時、エンジニアには二つの選択肢が提示される。一つは呼び出しをnamespaceの内側に移すこと、もう一つは//declscope:packageディレクティブを用いて、意図的に共有物として宣言することだ。この「意図的な共有」というプロセスこそが、AI時代におけるコードベースの健全性を保つ鍵となる。
また、qualifyルールをONにすることで、外部メソッドに対してnamespaceの名前を含めることを強制できる。これにより、AIが勝手に命名した関数名が、どのコンテキストに属するものかを明確に定義させることが可能だ。これは単なる命名規則の強制ではなく、コードの可読性と保守性を担保するための「設計の強制」に他ならない。AIにコードを書かせる際、我々エンジニアが担うべき役割は、AIが守るべき「境界線」を設計し、それをツールによって強制することにシフトしているのだ。
エンジニアが明日から取るべき実践的対策
declscopeの導入は、単なるLinterの追加ではない。それは、AIエージェントとの協働における「ガバナンスの再定義」である。多くのエンジニアは、AIが生成したコードをレビューする際、機能的な正しさにばかり目を奪われがちだ。しかし、真に恐ろしいのは、機能は正しくとも、将来的な変更を困難にする「境界の崩壊」である。declscopeをCIパイプラインに組み込むことで、AIが生成したコードがプロジェクトの設計思想を逸脱した瞬間に、それを検知し、修正を促すことができる。
明日からあなたが取るべきアクションは明確だ。まず、既存のGoプロジェクトに対してdeclscopeを適用し、現在のコードベースがどれほど「越境」しているかを可視化することだ。おそらく、多くのプロジェクトで驚くべき数の警告が吐き出されるはずである。次に、それらをすべて修正しようとするのではなく、重要なドメインロジックから順に//declscope:namespaceや//declscope:packageを付与し、境界を明示的に定義していく。これは、AIに対する「教育」であると同時に、人間である我々自身が、コードの構造を再認識するプロセスでもある。
最後に、我々エンジニアに突きつけられた問いを考えたい。AIがコードの大部分を生成する未来において、我々が守るべき「エンジニアリングの価値」とは何だろうか。それは、複雑なアルゴリズムを実装することではなく、システム全体の「境界」を設計し、その整合性を維持し続けることではないか。AIは規約を破るのではなく、見えているAPIを素直に使っているに過ぎない。ならば、規約を破れないように設計することこそが、シニアエンジニアの責務である。declscopeのようなツールを使いこなし、AIという強力なエンジンを、我々が定義した境界線の中で走らせる。その準備はできているだろうか?


コメント