これはコーディングコンベンションのレベルの話じゃなくて、言語機能の正確な把握のレベルのお話です

本屋にふらっと言ったら、内容が8割くらい同じ本が別の会社から出ていてびっくりした。
あまりに驚いて、よく確認したくて両方買っちゃった orz
ISBN:9784774145471
ISBN:9784822296070
Java でのコーディング規約の例の本なのだが、どうやら絶版っぽい元の本があって、その改訂版っぽい。
しかし翻訳でもない本で、ここまで同じ内容で出版されちゃうのも珍しいと思う。


話は変わるけどその中で、非常に悪いサンプルがあった。
数年前、職場でわけのわからない事を言う人がいたんだけど、どうやらこれの元の本をみて鵜呑みにしたんだろうなと思う。


Java ルールブックのほう、『2.1.1 オブジェクトの参照にはインターフェイスを利用する』のサンプルがすこぶるまずい。
サンプルコードを一部修正して引用。


違反例(とされている)

public class BadSample {
    public static void main(String[] args) {
        ArrayList<String> sampleList = new ArrayList<String>(); // 1. この本ではここが違反とされている
        sampleList.add("bad_sample");
        BadSample badSample = new BadSample();
        String ret = badSample.badMethod(sampleList);
        System.out.print(ret);
    }
    
    private String badMethod(ArrayList<String> input) { // 2. ここは確かに違反かもね(要件による)
        return input.toString();
    }
}


修正例(とされている)

public class GoodSample {
    public static void main(String[] args) {
        List<String> sampleList = new ArrayList<String>(); // 1. これは改悪じゃん?
        sampleList.add("good_sample");
        GoodSample goodSample = new GoodSample();
        String ret = goodSample.goodMethod(sampleList);
        System.out.print(ret);
    }
    
    private String goodMethod(List<String> input) { // 2. ここは確かに良くなったかもね
        return input.toString();
    }
}


えっと、1. のほうは元のコードで全然悪くないです。 new している時点で具体的な型名を書いてしまっているので、それを受け取る変数名の型を抽象度高くしても意味なくて無意味に不便なだけなんです。
この例の 1. の所で本当に抽象化の恩恵にあやかりたい場合、オブジェクトの生成部分を抽象化して、該当部分から具象クラスに対する知識を取り除いてください。


修正例(ただし元のサンプルに意味がなさ過ぎて有用性も伝わりづらい)

public class ActuallyGoodExample {
    public static void main(String[] args) {
        List<String> sampleList = createList(ListImplType.ARRAY_LIST); // これでやっと List<String> で受け取る意味が出てきました。
        sampleList.add("actually_good_sample");
        ActuallyGoodExample goodSample = new ActuallyGoodExample();
        String ret = goodSample.goodMethod(sampleList);
        System.out.print(ret);
    }
    
    private static List<String> createList(ListImplType listImplType) {
        switch (listImplType) {
            case ListImplType.ARRAY_LIST:
                ArrayList<String> result = new ArrayList<String>();
                // ここでは List<E> になくて ArrayList<E> にだけあるメソッド等を使って
                // 精一杯インスタンスの初期化を頑張ってよい(ArrayList である事は保障されているのだから)
                return result;
            case ListImplType.HOGE_LIST:
                // 別の実装クラスのインスタンスを生成することもありうる。
                return new HogeList<String>();
        }
    }
    
    private String goodMethod(List<String> input) {
        return input.toString();
    }
}


そこに変な自己規制は無用です。
これはコーディングコンベンションのレベルの話じゃなくて、言語機能の正確な把握のレベルのお話です。


この二冊、良い原則もたくさん書いてあるけど『Java の標準規約ではそうです』『著者たちの好みです』っていう隠れた但し書きが必要な所もいっぱいあるので、未熟な人が鵜呑みにするのは良くないと思う。でももっとこういう本には出てきて欲しいと思う。