【Go初学】プロジェクトレイアウト
概要
kubernetes などのGoリポジトリを見ていると見慣れないフォルダがたくさんあり、他のリポジトリでも似たようなレイアウトとなっている。RailsやLaravelなどでは矯正・強制的なレイアウトのルールが敷かれているが、Goでもそのようなものがありそうなので確認してみた。
Standard Go Project Layout
そのタイトルの通り、Goの標準的なプロジェクトレイアウトが記述されている。Go開発チームの公式というわけではないためあくまでレイアウト案を紹介というところだが、世界的に大規模なプロジェクトで広く採用され事実上の標準となっているもよう。
ここからたくさんの学びがあるが、中でも特に気になった点がいくつかある。
▼internal
他のプロジェクトレイアウトでは(恐らく)見てこなかった制約を持った特殊な階層。「内部」を意味し、そのプロジェクトでのみ使用可能なプログラムを配置する。
プロジェクトのみというのは internal という名前で単に視覚的に「内部」を意味するのではなく、外部パッケージからのインポートを Go ビルドシステムで受け付けないというレベルで制約がある。
外部から使用できないということは外部が知る必要がないということで、あるパッケージの実装を探り、効率的に把握するためのサインを示すことができる。
ここへはアプリケーション固有のプログラムを責務の単位でパッケージとして閉じ込め、アプリケーション本流からインポートして使う。
インターネットへの公開を前提とした制約のように見え、小さなパッケージを組み合わせて構築するという触れ込みのGoらしさというのが感じられる。
▼pkg
「パッケージ」を意味し、外部からインポートして使用可能なプログラムを格納する階層。恐らくアプリケーションに固有ではない普遍的な、一般的なプログラムをここに格納すると思われる。
ただ、この階層をどう捉えてよいのか自明ではない。外部に公開したい場合は当然ここに含めるが、アプリケーション固有ではないからといって特に公開したいわけではないものも含めるのか気になった。
外からどう見えるかというより、中(開発者の間)でアプリケーションに依存していないプログラムであることを示すために配置するということだろうか。
▼パッケージ志向アーキテクチャ
Goのチュートリアル的なものを触っている時から何か違和感があったが、これらを読むとレイアウトがどうあるべきかますます分からなくなった。
責務毎のレイヤーをベースに考えると、MVCではコントローラーやビジネスロジックを処理するサービス、ドメインを閉じ込めたモデルとそれぞれがレイヤーのように分かれているが、コントローラーをXやY,Zのドメインに関する操作を行う「コントローラーパッケージ」とまとめるのかと思うとどうもしっくりこない。特定の問題ドメインに対する解決策は持っておらず、コントローラーの責務しか実装がなく断片化された機能のように思え、ユーザー(開発者)が「コントローラーパッケージ」で何か解決できるように思える設計と感じられない。
XやYのパッケージに全ての責務を含める形にすればそれでよいのかというと各パッケージ毎に独立し過ぎているような気がして、しかし気がしているだけでよいか悪いか自明ではない。
▼試す
自分で学習用にGoプロジェクトを作り少し試してみた。まだ試し中ではあるがpkg階層必要無いよなと作らなかったり、Controller/Service/Modelというパッケージ分けになっていたりで、やっている最中は何か違う感が漂っていた。
こちらのパッケージ志向の設計についての方でも、「model 」フォルダを非推奨に追加していた。
※中国語→日本語へ翻訳が上手くいかない場合、一度英語翻訳したものを日本語翻訳すると読めるようになる
※【追記】リンクを参考にプロジェクトレイアウトを修正
・APIリソース毎にパッケージを分ける
・リソースパッケージはルーティングメソッドのみ公開し、その他の
構造体や関数を全てパッケージ内にカプセル化
・アプリケーション固有の処理を internal/platform へ配置
あとがき
自分のおもちゃプロジェクト程度では確かにレイアウトはこうあるのが望ましい、という需要が分かりづらく正しさを求めると不必要に消耗してしまうかもしれない。しかし公式のベストプラクティスではなくコミュニティでも意見が統一していない現状、各々のプロジェクトで適した設計を都度検討する必要があるのかなと思う。
この記事が気に入ったらサポートをしてみませんか?