C言語な感じとオブジェクト指向っぽい話 - ReDo

2013年10月25日

C言語な感じとオブジェクト指向っぽい話

オブジェクト指向とは、みたいな話をした際に基底クラスとか継承とか、車とスーパーカーとか、そういうのじゃなくて、C言語臭いJavaとそうでないJavaみたいなのがあって、できればJavaっぽくしてほしいなぁ、という曖昧な何かを必死に具体化してみました。

○仮定

以下のようなデータを取り扱うシステムを開発するとします。

NAME:山田太郎
SEX:男
YEAR:4
ORG:開発部
HISTORY:2013;検討S
HISTORY:2012;プロジェクトD
HISTORY:2011;プロジェクトB
HISTORY:2010;試作X
NAME:鈴木花子
SEX:女
YEAR:2
ORG:営業部
HISTORY:2011;プロジェクトB
HISTORY:2010;プロジェクトA

最終的にはファイルだったりどっかからとってきたり○xcelとかからインプットされたりしますが、きっと初期値はコードに書いてふるまいをざっと組んでみたりしますよね、C言語な人がJavaで書くとどうなるのでしょう、順番に具体例を並べてみることにします。

○Lv.1

まずCからJavaに来るとこうなります。「mallocじゃないんだー!」「文字列リテラル直接書けるんだー!」

/**
 * Lv.1 C言語っぽい配列の羅列
 */
public static void level1() {
    String[] nameList = new String[2]; // 2 members
    String[] sexList = new String[2];
    String[] yearList = new String[2];
    String[] orgList = new String[2];
    String[][] historyList = new String[2][];
    
    nameList[0] = "山田太郎";
    sexList[0] = "男";
    yearList[0] = "4";
    orgList[0] = "開発部";
    historyList[0] = new String[] {
            "2013;検討S", "2012;プロジェクトD", "2011;プロジェクトB", "2010;試作X"
    };
}

まぁ微妙です。次行きましょう。

○Lv.2

ちょっと経つと、StringとHashMap厨になります。僕もなりました。
キャスト検査とか無駄なコードが必要なJava1.4というものがかつて存在しました。今は存在しません。

/**
 * Lv.2 JavaっぽくMapを導入、データを示す変数が1つに
 */
public static void level2() {
    @SuppressWarnings("unchecked")
    HashMap<String, Object>[] memberList = new HashMap[2];
    
    memberList[0].put("name", "山田太郎");
    memberList[0].put("sex", "男");
    memberList[0].put("year", "4");
    memberList[0].put("org", "開発部");
    memberList[0].put("history", new String[] {
            "2013;検討S", "2012;プロジェクトD", "2011;プロジェクトB", "2010;試作X"
    });
}

ここではサボってますが、keyをstatic final Stringにちゃんと追い出してもまだイケてません。


○Lv.3

この次あたりに、配列とかArrayListじゃなくて「Collection言え」厨になりました。

Iteratorは配列indexインクリメントよりはマシですがなんだかんだ言ってコードが方向リストっぽくなって臭くてたまりません。ポインタとか構造体とかアロー演算子なC言語臭いアレです。

/**
 * Lv.3 配列は増減にindexを意識するのが煩わしいのでCollection化
 */
public static void level3() {
    List<Map<String, Object>> memberList = new ArrayList<Map<String, Object>>();
    
    {
        Map<String, Object> member = new HashMap<String, Object>();
        member.put("name", "山田太郎");
        member.put("sex", "男");
        member.put("year", "4");
        member.put("org", "開発部");
        member.put("history", new String[] {
                "2013;検討S", "2012;プロジェクトD", "2011;プロジェクトB", "2010;試作X"
        });
        memberList.add(member);
    }
}

ArrayList<HashMap<String, Object>>で全てが済ませられると思っていました。若かった。

○Lv.4

やっとこのあたりでMVC厨になります。Modelクラスつくりたくてたまらない病です。ここから先、なんでもnewでインスタンス作る厨とstaticなUtil厨に分岐します。僕はstaticおじさんになりました。今でもちょっとそうです。

    /**
     * Lv.4 Modelクラスを作成。
     */
    public static void level4() {
        List<Member> memberList = new ArrayList<Member>();
        
        {
            Member m = new Member();
            m.setName("山田太郎");
            m.setSex("男");
            m.setYear(4);
            {
                Project p = new Project();
                p.setYear(2013);
                p.setName("検討S");
                m.getProjectList().add(p);
            }
            {
                Project p = new Project();
                p.setYear(2012);
                p.setName("プロジェクトD");
                m.getProjectList().add(p);
            }
            {
                Project p = new Project();
                p.setYear(2011);
                p.setName("プロジェクトB");
                m.getProjectList().add(p);
            }
            {
                Project p = new Project();
                p.setYear(2010);
                p.setName("試作X");
                m.getProjectList().add(p);
            }
            memberList.add(m);
        }
    }

ビルドエラーをとるためだけにModelクラスらしきものを作ります。たまにgetter/setterを手動生成している人を見ます。そもそもデータ構造を示すクラスを手打ちしている時点で負けなのでイヤでイヤでたまらないぐらいになりたいのですがそこまでの域には達していません。
ここでは手抜きして書いていませんが、クラスヘッダとフィールドのJavadocを書くとすごい設計が進んだ気になって安心してしまいます。

public class Member {
    private String name;
    private String sex;
    private int year;
    private List<Project> projectList = new ArrayList<Project>();
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    public int getYear() {
        return year;
    }
    
    public void setYear(int year) {
        this.year = year;
    }
    
    public List<Project> getProjectList() {
        return projectList;
    }
    
    public void setProjectList(List<Project> projectList) {
        this.projectList = projectList;
    }
    
    public static Member parse(String memberString) {
        // TODO: impl.
        return null;
    }
}
public class Project {
    private int year;
    private String name;
    
    public int getYear() {
        return year;
    }
    
    public void setYear(int year) {
        this.year = year;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

○Lv.5

こっそりparseとかメソッドが居ましたね。

いくら必要な初期値だからってリテラルでデータ構造打ってたらソースの可読性が落ちまくりです。別のところに切り出すべきです。ステップ数が増えて見た目(笑)の生産性が上がるので喜ぶ人が居るかも知れません。

すいません、近くに居ます。知らないふりをしました。

/**
 * Lv.5 Javaっぽい何か
 */
public static void level5() {
    List<Member> memberList = new ArrayList<Member>();
    
    {
        Member parsed = Member.parse(MEMBER1);
        if (parsed != null) {
            memberList.add(parsed);
        }
    }
}

じゃああとはパーサガリガリ書けば綺麗にカプセル化できて後々幸せだよね...?

○Lv.6

/**
 * Lv.6 ええと、実際のところこうだよね
 */
public static void level6() {
    // あのな、独自フォーマットなんてきょうび流行んねーんだよ。
    Members members = (new Gson()).fromJson(MEMBERS_JSON, Members.class);
}

んなわけないです。車輪の再開発イクナイ、シリアライズぐらい誰かに任せましょう。

こういうことを考えながら、json1つ書くことはプログラミングしてるのと同等である、というあたりがまわりになかなか伝わりません。
余計なExcelとコード書いてぐるぐるprintfデバッグしたがる人たちをどうにかしたいです。

コメントする