2010年版インスタンス生成考

 2010年現在のアクセスレベルの限界 - プログラマーの脳みそではpublic, protected, private, パッケージプライベートという4つのアクセスレベルではうまく行かない事例という視点だったけど、例に挙げたDIコンテナ云々というのはアクセスレベルの不備というよりも、コンストラクタの不備と捉えるべきだ。

コンストラクタを使わないインスタンス取得

 Javaの場合、インスタンス生成はコンストラクタによって行われる。そのクラスの外部から、インスタンスを得ようとする場合の一番基本的なインスタンス取得方法は、new によってインスタンスを新たに生成する方法。

 しかし、たとえばGoFデザインパターンのSingletonであるとか、あるいはFlyweightであるとか、返すインスタンスが常にnewされるわけではなく、既存のインスタンスを使い回して返すような作りに使用とした場合、コンストラクタではお手上げなのだ。コンストラクタは新たに生成されたインスタンスしか返せない。new 演算子では常に新品のインスタンスが得られる。

 インスタンスを得たい、という場合にあるクラスはnewを使え、あるクラスはインスタンスを得るためのメソッドを使え、となってしまっているのが2010年現在のJavaの実態である。

宣言的なインスタンス生成

 GUIのプログラムをしたことがある人ならば階層構造を持つオブジェクトのインスタンスの生成の面倒くささはよく知っているのではないだろうか。JFrameを作って各種設定をし、JLabelを作って各種設定をしframeにadd、JTextFieldを作って各種設定をしframeにadd、JButtonを作って各種設定をしframeにadd…

 これを手続き型言語、まぁ今の場合はJavaなのだが、それで記述すると以下のような感じになる。

import java.awt.BorderLayout;
import java.awt.Font;

import javax.swing.*;

public class SwingSample {
	public static void main(String[] args) {
		JFrame frame = new JFrame("Swing!");
		frame.setSize(200, 120);
		
		JLabel label = new JLabel("Hello");
		label.setFont(new Font("Serif", Font.BOLD, 18));
		frame.getContentPane().add(label, BorderLayout.NORTH);
		
		JTextField field = new JTextField("type...");
		field.setFont(new Font("Serif", Font.PLAIN, 12));
		frame.getContentPane().add(field, BorderLayout.CENTER);
		
		JButton button = new JButton("OK");
		frame.getContentPane().add(button, BorderLayout.SOUTH);
		
		frame.setVisible(true);
	}
}

 近年のGUI向け言語はこのあたりを改善するために宣言型の構文を用意するなどしている。つまり、GUIコンポーネントの階層構造を組み立てるのに手続きは不要で、どこに何が入るという宣言さえあればよい。こうした特定の目的にあった構文を用意することで手続き型でコンポーネントを組み立てるよりはるかに可読性がよくなるし、プログラミングは楽になる。

 Flex/AIRActionScriptにおけるMXMLであるとか、silverlightXAMLであるとか、JavaFXでの宣言型構文とかがそれにあたる。さて、ここでは先のJavaのswingでのプログラムの元ネタ、JavaFX版のソースを見てみよう。

import javafx.ui.*;

var window = Frame {
    title:"JavaFX!"
    width:200
    height:120
    content:BorderPanel {
        top:Label {
            text:"Hello"
            font:new Font("Serif", "BOLD", 18)
        }
        center:TextField {
            value:"type..."
            font:new Font("Serif", "PLAIN", 12)
        }
        bottom:Button {
            text:"OK"
        }
    }
};

window.visible = true;
JavaFXによるGUIアプリケーションの作成 (2/3):CodeZine(コードジン)

 どうだろうか。GUIコンポーネントの組み立てで重要なのはどこに何が設定されたかであって、順番はさしたる意味を持たない。手続き型言語は順次処理という基本の基本があるのだけど、そんなものはどうでもいい。

 ちなみに、MXMLXAMLXML式の構文を採用している。XMLも階層構造を宣言するには手続き型よりもベターな表現だろう。

 ここでは2010年現在、比較的発達しているGUIの宣言型アプローチを例に挙げて見てみた。しかし、宣言型というのはGUIコンポーネントを構築するだけにとどまらない。自動テストなどで階層構造をもったオブジェクトのテストデータを宣言するのに辟易している人も多いだろう。そういうシチュエーションでも効果を発揮する。

 そういう点で、GUIコンポーネントの生成に傾きすぎていないJavaFXの宣言型構文は嬉しい。デザインの部分を別ファイルに括りだしたいという要望もあるだろうから、一長一短だとは思うが。

DIコンテナによるコンポーネントの管理

 さて、前置きが長くなったが、DIコンテナを宣言型のコンポーネント生成フレームワークとして捉える、ということができる。現行のJavaにはない機能をフレームワークで補おう、という泥臭い実務派の思想になっちゃうのだけど。

 さきにXMLでの階層構造の宣言は手続き型よりもベターだといった。だから、コンポーネントの組み立ての設計図をXMLにくくりだして、DIコンテナで生成するという手法がシチュエーションさえ揃えばメリットが出てくる。

 まぁ、回りくどい言い方をしたけど、メリットもデメリットもあるんで手放しに万歳というわけには行かなくて、結構シチュエーションを選ばなくちゃいけない。そういう意味で現行のDIコンテナというのは過渡期の技術だと思うわけ。いや、べつに宣言型だけがDIコンテナのメリットではないのだけど、宣言型構文とアスペクト指向が整備された言語があったなら、DIコンテナっていらなくね?って思うわけです。ええ。

インスタンス生成というメタな視点

 さて、ここまで

といったインスタンスの生成にまつわるものを見てきたわけだけど、これらを統一的に扱えるよりメタなコンストラクタ様の概念が必要だと僕は考えていて、あわよくばそこにアスペクト指向も織り込めたらいいなぁなんて妄想をめぐらせているところ。

 単純には特定クラスのインスタンスを返すものをすべて初期化子ってまとめちゃったらどうだろう?ってのはあるのだけど、まだそうした案の評価ができてない。

 2010年代の言語はこのあたりを解決して欲しいものだね。