前提条件を破った場合、どのような挙動をするのか? - 都元ダイスケ IT-PRESSで言及をもらったので
現代は4つのアクセスレベルでの可視性制御の限界が囁かれていて、打破するためにいろいろ模索しているところ
はてなブックマーク - Nagiseのブックマーク / 2009年12月24日
についてちょっと具体的な話をしておこう。
このブックマークコメントは可視性と公開APIと非公開(内部)APIと - 都元ダイスケ IT-PRESSに対してつけたものだった。このエントリは設計する際にJavaの4つのアクセスレベルをどう使い分けるかを書いた良エントリだと思う。
privateで困る例:自動テスト
JUnitといった自動テストコードを書くことを考えてみよう。クラス内だけで再利用される冗長コードをprivateメソッドとして括り出した。このメソッドが単体独立で動作検証が可能なのであれば、そのI/Oを自動テストで検証できるようにしておきたい、と考えるのは自然な出来事だろう。
しかし、privateアクセスレベルだと都合が悪いので、実用上はパッケージプライベートにアクセスレベルを広げておくことになる。しかし、これは実用上の妥協の産物であって、そのメソッドは本質的には外からアクセスされないことを想定した設計なのだ。
ここに、自動テストのフレームワークには特権的にアクセスさせたいが、本質的には外部からアクセスをさせたくないというシチュエーションが生まれる。
非publicで困る例:DIコンテナ
DIコンテナをどのような視点で捉えるか、というのは多説あるところだろう。
ひとつの見方、という断りの上でだが、木構造を持つなど比較的複雑なインスタンスの構築を宣言的に行える、という視点でDIコンテナを利用するケースがある。
宣言的に、というのがいささか専門用語的か。たとえば木構造のような階層を持つデータを作るというのに手続き型言語というのは向いていない。順番に流れて処理が行われる、なんてのはどうでも良くて、どのフィールドにどの値が入るかさえ宣言できれば事足りる。というか、余計なものがあるとむしろ見にくい。
XML形式とかJSON形式とかは階層構造を持つデータを表現する手段としてはベターな手法だ。プログラムでいちいちsetterでデータを投入するのに比べればとても見通しがよい。
で、クラスのインスタンスを構築するのに、こうした宣言的な表現が使えれば良いのだけど、今現在のプログラム言語ではこうした宣言型というパラダイムはまだ本格的に取り入れられておらず、過渡期にあると言えよう。その代替としてのDIコンテナ、という見方がある、というお話。
そんなDIコンテナだが、インスタンスを構築するのに、まずはnewしてインスタンスを生成してsetterなりフィールドへの直接アクセスなりで下位のデータを投入するといったことをしなくてはならない。この際に、アクセスレベルがpublicでないと困る。
データの構築という特例だけ特権的にアクセスレベルを緩めたいが、通常外からは変更出来ないであって欲しい、というフィールドが存在する。
新しい解決案:スーパーパッケージ
現在提案されている改善案としては、スーパーパッケージというものがある。http://journal.mycom.co.jp/column/jsr/037/index.htmlあたりを参照して貰うとよいだろう。
- パッケージや他のスーパーパッケージとそのタイプの集合
- 明示的に"Export"されたメンバのみ外部からアクセスできる
- "Export"されていないメンバは、同じスーパーパッケージ内の他のメンバからのみアクセスできる
- Javaソースファイルによって定義し、Javaコンパイラによってコンパイルできる
これによって、あるパッケージを公開するか隠蔽するかを、パッケージごとに制御することが可能になる
http://journal.mycom.co.jp/column/jsr/037/index.html
といった代物だ。これが決定打になるとは考えていないが、いくらかは改善されるだろう。
2010年代にはどのようなパラダイムでプログラム言語が進化して行くのだろうか。