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


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

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

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

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

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

IとかInterfaceをつける書き方

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

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

public interface IHoge {
    void doSomething();
}

とか、

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

public interface HogeInterface {
    void doSomething();
}

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

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

  • 頭にIをつける
  • おしりにInterfaceをつける

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

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

IとかInterfaceをつける書き方その2

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

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

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

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

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

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

例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のクラスに継承しても違和感が無い状態になりました。

問題の書き方

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

例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を実際に呼び出してみましょう。

例6-1
// メソッドだけ抜き出し
public void doSomething(){
    AnimalInterface dog = new Dog();
    dog.walk();
}
例6-2
public interface Cage(){    // カゴ(檻)ですね
    void add(AnimalInterface animal);    // カゴに動物を追加
}

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

そうではなく、

例7-1
// メソッドだけ抜き出し
public void doSomething(){
    Animal dog = new Dog();
    dog.walk();
}
例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とは何か?みたいな話に突っ込んでるので、異論等々あるかと思います。
その場合は心の中で(こいつアホだな)と思うだけでなく、出来ればコメントで教えて下さい。