GolangGolangを使い始めてinterfaceでDIPっぽいことをしようとするとたしかに湧きがちな疑問のひとつ。結論から言うと、interfaceはそれを使う側のパッケージに所属させるのがセオリーらしい。GitHubなぜかせっかくなので理由を考えてみた。以下はJSONやXMLなど複数のフォーマットでログを出力できるロガー・アプリケーションのクラス関係図の例。このアプリケーションの設計は、中核となるLoggerクラスと具体的なXMLやJSONなどへのシリアライザ実装がそれぞれISerializerインターフェースという抽象に依存している典型的なDIP(依存性逆転)だ。LogParamsクラスは、ログとして出力するデータの内容を保持しているものとする。それぞれ、黒矢印は「利用」、白矢印は抽象に対する「実装」、点線の矢印は「依存」を表している。このアプリケーションにおいてserializerパッケージというのは「どのように出力するか?」のHowが所属するレイヤであり、一方でmainパッケージはアプリケーションのビジネスロジックとして「なにをするのか?」のWhatが所属するレイヤにあたる。考えると、具体的な実装を持たないinterfaceであるISerializerが、「出力の方法」を責務として所属させるべきserializerパッケージにいるというのは違和感がある。interfaceは単なる「使い方」を示すだけのものであって具体的な実装を持つものではないのに、Howが所属するパッケージにいるからだ。このような理由で、interfaceはそれを使う側に配置するのがよい、というプラクティスに合点がいく。(ちなみにではあるが、そもそもこの関係図だとmainパッケージとserializerパッケージが双方向依存になっているため、Golangではコンパイルの時点でエラーになってしまう)ということでISerializerをmainパッケージに所属させる。パッケージ内での依存関係はいくら循環していようと構わないので、これは問題なく動作する。ISerializerインターフェースが実装先のパッケージから切り離された。これで正しく「使う側」に所属させることができた。今回のISerializerに当たる部分が、DDDでいうところのリポジトリであると考えてみる。考えると、リポジトリはドメイン層のインターフェースに当たる部分なので、リポジトリの具体的な実装のパッケージにそれが所属するのは解せない、というのがしっくりくる。(8)はてなブログをはじめよう!IzumiSyさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。