初めに
ロバート・C・マーチン氏の「アジャイルソフトウェア開発の奥義」が大変面白かったのでまとめる。
*本書とは順番が異なります。
依存性逆転の法則
SOLID原則のD、英語でDependency Inversion。
これは以下の2文で説明できる。
- 上位のモジュールは下位のモジュールに依存してはならない。どちらのモジュールも「抽象」に依存すべきである
- 「抽象」は実装の詳細に依存してはならない。実装の詳細が「抽象」に依存すべきである
今までの誤解。
自分はJava,Springをやってきたので、「あーDIのことか」と思っていた。
まず、これは間違い。逆転(Inversion)であって、注入(Injection)じゃない。
だが、自分はDIを利用すればDはクリアした気になっていた…
だが、一番の勘違いはDIするときのInterface設計だった。
多分多くのSpring経験者は書籍の中で「ServiceInterafceを作る」というようなサンプルコードを見てきただろう。例えば、こんなの。
//Userの実装は略。
public interface UserInterface {
public void login(User user);
}
@Service
public class UserService implememnts UserInterface{
/*(中略)*/
}
@Controller
public class LoginController{
@AutoWired
private final UserInteface user;
/*RequestParamなどは省略 */
public void Login(String userId,String password){
user.login(new User(userId,password));
}
}
そして、パッケージ構成はこうではなかっただろうか。
これに違和感を覚えず、丸呑みして使っていた。だが、依存性逆転の法則にしたがうと、このUserInreface
はcontroller
パッケージにあるべきなのである。
本書の中では「影響が伝達しやすい依存関係」だと指摘している。
Controllerを直せば、Serviceが、そして恐らくあるであろうRepositoryにまで影響すると。
最初は理解できなかったが、アジャイルソフトウェア開発の本なので
「テストファースト」で考えるとよくわかる。
テストが意味をなさなくなる依存関係
まず、どういう変更が考えられるか。
実はこのUserInterface
には(意図的に)足りないものが一つある。そう、logoutだ。
では、UserInterfaceにlogoutを実装しよう。大体のWEBサービスではログアウトはセッションにあるユーザー情報のリセットだろう。これをコード上で書く場所はUserServiceに他ならない。
セッションならcontollerだろと書いてしまうと大変危うい。もしかしたらSpring SessionでDBも使うかもしれない。たとえ今はそうでなかったとしても。
そして、テストはserviceプロジェクトにかかれる。
修正漏れがないようにこの仕事ではカバレッジが90%だったとしよう。
他に修正はなくてもガバレッジはクリアしているので、serviceプロジェクトの修正が終わればリリースできてしまう。
そして、多分1日目にしてこういうクレームが来る。
「ログアウトしてない」
なぜか、画面から呼び出されるはずのcontrollerにlogoutがないからだ。
「いやいや、そんなのテストでわかるよ」
もちろん、そうであるはずだ。大事なのは、こう言った初歩的なミスはテストコード、いわば「単体テスト」を書いてる時点で気づくべきだ。
もしかしたら、「こんなの半日で終わりますよ」と高を括っていってしまったがために、テストは行われてないかもしれない。このプロジェクトにはガバレッジが設定されているから大丈夫だと。
だがそうはならなかった。
これがこのパッケージの依存関係が生む大きな弊害である。
どうすべきか
簡単である。UserInterfaceをcontrollerパッケージに書けばいい。
そうすればcontrollerプロジェクト担当者はcontrollerにlogoutを書き忘れることはない。
そして、このインターフェースはserviceプロジェクトが実装しているので、ガバレッジをクリアしても最終的なプロジェクトのコンパイルでエラーになる。なので、実は実装されてないなんてこともなくなる。
controllerとservice、両方が修正され初めてリリースできるという望ましい形になる。
これで、PMもお客さんもニッコリ(*´ω`*)
あなたの仕事は多分しばらくは安泰だろう。
まとめ
依存性逆転の法則に従うなら、インターフェースは「実装する側」ではなく「依存している」側に書くべき。