Goでフォルダ構成/アーキテクチャをどうするか問題について〜interface編〜
interface について少し語る
Table of contents
author: tagupoyo
はじめに
Goには明確なアーキテクチャスタイルはないです。よくあるレイヤードアーキテクチャだったりが正であるわけではないです。 また、Goの Standard Go Project Layoutは公式が発表しているものではないため注意してください。
今回はinterfaceについて触れていきます。
Go の嬉しさ
tagupoyoはGoで一番うれしいものはinterfaceだと思っています。
Goのinterfaceはメソッドを定義し、それらのメソッドを実装しているとinterfaceを満たしていることになります。
type UserRepository struct {
//DBアクセスのフィールド
}
func (ur *UserRepository) Get(id string) (model.User ,error) {
//取得処理
return model.User{}, nil // 例としてダミーの戻り値
}
Client構造体はuserRepository interfaceを満たしているのが大切です。
type userRepository interface {
Get(id string) (model.User ,error)
}
type Client struct {
userRepository userRepository
}
func NewClient(userRepository userRepository) *Client {
return &Client{
userRepository: userRepository,
}
}
func (c *Client) getUser(id string) (model.User, error) {
return c.userRepository.Get(id)
}
userRepository := UserRepository{}
client := NewClient(&userRepository)
client.getUser("1")
Goでは暗黙的にinterfaceが満たされてます。
Javaではインターフェースを明示的に実装する必要があるため、たとえClient側で不要なメソッド(例: Saveメソッド)であっても、インターフェースに定義されていれば実装が必要になる場合があります。
例えば、Client側で保存は不要なのにSaveメソッドが実装されているなど。
interface 勘所
Goの作者の1人であるRob Pike氏も以下のように発言しています。
The bigger the interface, the weaker the abstraction.
インターフェースが大きくなるほど、抽象化は弱くなります。
Don’t design with interfaces, discover them.
インターフェースを設計するのではなく、インターフェースを発見してください。
interfaceが大きければ大きいほど抽象が弱くなる。たとえば、以下のようなものです。
type ProductRepository interface {
// 引数、返り値は省略
Get()
Update()
All()
Delete()
}
上記のように特定の者に特化した大きすぎるinterfaceは抽象ではなく、もはや具象クラスなのでは?とは思っています。 なので、interfaceは使用者側に持たせて適切な粒度で抽象にすべきです。 ちなみに、このようなinterfaceはJavaに大きく見られると著者は思っています。
インターフェースを設計するのではなく、インターフェースを発見してください。
interfaceは理由がない場合に使用しないほうがいいです。
interfaceを使用して、テストがしやすくなるなど明確な目的がある場合に実装してください。
たとえば、ロジックのテストがしたいのでDBは抽象に依存させるなどです。
まとめ
- interfaceはテストがしやすい。
- interfaceは良い抽象に依存する。
- SOLID原則のDIPが満たせそうですね。
- 良いinterfaceを設計するためになんのために意識を常に持つ。
次回について
次回はフォルダ/パッケージ構成についてみていきます。
参考ページ
※本記事は、ジーアイクラウド株式会社の見解を述べたものであり、必要な調査・検討は行っているものの必ずしもその正確性や真実性を保証するものではありません。
※リンクを利用する際には、必ず出典がGIC dryaki-blogであることを明記してください。
リンクの利用によりトラブルが発生した場合、リンクを設置した方ご自身の責任で対応してください。
ジーアイクラウド株式会社はユーザーによるリンクの利用につき、如何なる責任を負うものではありません。