インタフェース分離の原則とは
クライアントに、クライアントが利用しないメソッドへの依存を強制してはならない
以前投稿した以下の内容で問題なさそうなので、こちらを参照してください。
【ボブおじさんのClean Architectureまとめ】オブジェクト指向
Go言語で見るインタフェース分離による恩恵
具体的に分離することでどういった恩恵が得られるのかを見ていきます。
実装例として文章をファイルに保存する方法を以下の3つのパターンで見ていきます。
・シンプルな方法
・インタフェースを用いた方法
・適切なインタフェースを用いた方法
方法1 シンプルな方法
func Save(f *os.File, doc *Document) error
第一引数に保存先のファイル、第二引数に文章を受け取るようにしています。
あとは内部で保存する処理を書けば良さそうです。
しかし保存先をファイルでなくクラウドストレージやDBに保存したいと要件が変わった場合どうしますか?
新しくクラウドストレージ用、DB用のSaveメソッドを増やして行くのが最善の策でしょうか?
また、保存出来ることのテストはどのようにすれば良いでしょうか?
実際にファイルを作成し、ファイルに文章が書き込まれていることを確認すればできます。
文字のチェックなど確認事項が多くなってしまいそうです。
シンプルな方法での問題
一度シンプルな方法を使った場合の2つの問題点をまとめておきます。
・保存先を変える際の呼び出し側に影響がでる
・テストを実施することが難しい
方法2 インタフェースを用いた方法
func Save(rwc io.ReadWriteCloser, doc *Document) error
// ReadWriteCloser is the interface that groups the basic Read, Write and Close methods.
type ReadWriteCloser interface {
Reader
Writer
Closer
}
保存先をファイルからインタフェースに変更しました。
ReadWriteCloserインタフェースを実装している構造体(ファイルでもDBでも...)ならば第一引数で受け入れられますので、使う側に変更による影響がなくなりました。
また、テストの際にReadWriteCloserインタフェースを実装したモックを作れば、テストも簡単に実施することができます。
よってシンプルな方法で挙がっていた以下の問題を解決できました。
・保存先を変える際の呼び出し側に影響がでる
・テストを実施することが難しい
しかし、 ここで1つ質問です。
保存するだけなのに、保存先の情報をReadしたり、保存後にCloseをする必要があるでしょうか?
Saveメソッドの利用者は保存(Write)したいだけです。
ここでインタフェース分離の原則を思い出してみましょう。
クライアントに、クライアントが利用しないメソッドへの依存を強制してはならない
つまり分離の原則に従うならばCloserとReaderに依存を強制しないようにすべきです。
インタフェースを用いた方法での問題
・CloserとReaderが不要
・利用しないメソッドへの依存を強制
方法3 適切なインタフェースを用いた方法
func Save(w io.Writer, doc *Document) error
type Writer interface {
Write(p []byte) (n int, err error)
}
Writerインタフェースは保存先に保存(Write)することだけを提供します。
よってインタフェースを用いた方法で挙がっていた以下の問題を解決できました。
・CloserとReaderが不要
・利用しないメソッドへの依存を強制
最後に
インタフェース分離の原則による恩恵についてまとめました。
重要な以下のことを学びました。
・適切なインタフェースを用いること
・目的に応じてインタフェースを分離すること
他にもSOLIDの原則をまとめています。