基本的に、Interface の名前を I(名前) とか、(名前)Interface とかするのやめよう。

皆さん命名規則守ってますか？
分かりやすいコードを書くためには必要ですよね。

今回は命名規則の中でも、`Interface`について考えてみましょう。

※タイトルでは言い切ってますが、結局自分たちが書きやすい方法が正解です。
一つ、規約について考えるきっかけにしてみてくださいな。

# 本題の前に、よく見るサンプルの書き方

多くのプログラミング言語で使用される`Interface`ですが、
皆さんどのように名前つけてますか？

## `I`とか`Interface`をつける書き方

例えば`Hoge`というクラスがあったとして、このクラスにつける`Interface`を作るとすると、

```java:例1
public class Hoge implements IHoge {
    public void doSomething() {
        // 何かする
    }
}

public interface IHoge {
    void doSomething();
}
```

とか、

```java:例2
public class Home implements HogeInterface {
    public void doSomething() {
        // 何かする
    }
}

public interface HogeInterface {
    void doSomething();
}
```

とか、こんな感じですかね？
(サンプルは`Java`で書きます)

`Hoge`クラスにつけるインタフェースですから、

- 頭に`I`をつける
- おしりに`Interface`をつける

のどちらかをして、インタフェースだと分かるようにしておきましょうと。

まぁこれはいいでしょう。特に文句ないですね。

## `I`とか`Interface`をつける書き方その２

ではこれだとどうでしょう？

```java:例3
public class Dog implements DogInterface {
    public void walk() {
        // 歩く
    }

    public void run() {
        // 走る
    }
}

public interface DogInterface {
    void walk();
    void run();
}
```

あぁっ!? さっきと同じなのに、なんか気持ち悪い！
となりますよね？なりませんか？

では、こう書いたらどうでしょう？

```java:例4
public class Dog implements Animal {
    public void walk() {
        // 歩く
    }

    public void run() {
        // 走る
    }
}

// 同じ機能を持った猫も作れる！
public class Cat implements Animal {
    public void walk() {
        // 歩く
    }

    public void run() {
        // 走る
    }
}

// Interfaceの名前を、より適切にする
public interface Animal {
    void walk();
    void run();
}
```

`Interface`の名前を`Animal`にしたことによって、
`Cat`のクラスに継承しても違和感が無い状態になりました。

# 問題の書き方

ここまで納得いただけたでしょうか。
では、次に今回問題にしたい書き方。

```java:例5
public class Dog implements AnimalInterface {
    public void walk() {
        // 歩く
    }

    public void run() {
        // 走る
    }
}

public class Cat implements AnimalInterface {
    public void walk() {
        // 歩く
    }

    public void run() {
        // 走る
    }
}

// 末尾に Interface をつける
public interface AnimalInterface {
    void walk();
    void run();
}
```

一つ目と二つ目のハイブリッドみたいな形ですね。
この書き方はどうでしょうか。

特に問題なさそうですか？
ではこの`AnimalInterface`を実際に呼び出してみましょう。

```java:例6-1
// メソッドだけ抜き出し
public void doSomething(){
    AnimalInterface dog = new Dog();
    dog.walk();
}
```

```java:例6-2
public interface Cage(){    // カゴ（檻）ですね
    void add(AnimalInterface animal);    // カゴに動物を追加
}
```

どちらの例にしても、ここで欲しいのは動物です。
それが`Interface`であるかどうかは、呼び出し側からしてみれば「どうでもいい」情報です。

そうではなく、

```java:例7-1
// メソッドだけ抜き出し
public void doSomething(){
    Animal dog = new Dog();
    dog.walk();
}
```

```java:例7-2
public interface Cage(){
    void add(Animal animal);
}
```

このほうが見通しが良い訳です。
それに（こっちの方が重要ですが）呼び出し側が、呼び出すものが`Interface`かどうかなんて気にしなくてすみます。
ですから、`Interface`名に`I(名前)`とか、`(名前)Interface`とするのは、
基本的に余り良くないだろう、と言う事です。


# `HogeInterface`の書き方は本来の`Interface`の書き方ではない？

そもそも、なぜ`Interface`とかをつけるとかつけないとか、そんな話になったのでしょうか。
そうです。最初に挙げた、`Hoge`クラスに対して`Interface`をつける場合、
クラスとインタフェースを区別するために`HogeInterface`とします、というお話からです。

そもそも、`Interface`は、ある事象に対して、それが実装するべき内容を定義するためのものですから、
ある一つのクラスの為だけに`Interface`が作られるという事自体が稀な事なのかもしれません。

例えば`Dog`という実装を書く場合`Interface`として`Animal`を定義する事と、`DogInterface`を定義する事は、明らかに別の事になります。
どちらも今回は`Dog`クラスの為に定義されているものの、

- `Animal`: 扱うべき存在の抽象概念についての定義
- `DogInterface`: `Dog`クラスという具体的存在についての定義

であり、定義している内容に違いがあると言う事です。

`Interface`の本来の役割から考えると、扱う存在の抽象概念を定義する使い方の方が、この場合、より適切でしょう。
よって、`Hoge`という具体的なクラスが存在する前提で作られている`HogeInterface`は本来の使い方から少しずれた使い方なのです。

# `I`とか`Interface`を、つけてはいけないのか？

では、`IHoge`とか`HogeInterface`のような書き方はあり得ないのでしょうか？

いえ、これが必要になるパターンがありますね？

そうです。`DI`です。

`DI`する場合には、互いの依存を切り離すために、`Interface`を介してやりとりする場合がほとんどです。
この時、注入されるべきは明らかに`Dog`である部分に対して`Animal`インタフェースを使ってしまうと`Cat`クラスを注入されてしまう可能性があります（Dogにしかないメソッドを実行させたい場合などは、そもそもコンパイルが通りませんね）。

よって、このような場合では`DogInterface`を介してやりとりさせることで、確実に`Dog`が入ってくることを保証できます。


# まとめ

- 基本的に`Interface`を作る際には`I(名前)`とか`(名前)Interface`の形にしない
- `Interface`名は扱うべき抽象概念を表した名前をつける
- `DI`など、確実にクラスと1:1で紐付いた`Interface`が必要な場合は、この限りでない


## ちなみに

色々書きましたが、`Java`を使ってる方なら`List`インタフェースとか思い出してもらったら分かりやすいですよね。
後半で`Interface`とは何か？みたいな話に突っ込んでるので、異論等々あるかと思います。
その場合は心の中で（こいつアホだな）と思うだけでなく、出来ればコメントで教えて下さい。