OOSC 3章 演習問題E3.1 Javaはモジュール性の基準と原則をどの程度満たすか

OOSC読書つづき。

昨日は3章まで読んで、演習問題E3.1(p.82)について会話したので、そのメモを書きます。その節はありがとうございます m(_ _)m >身近な方

E3.1 プログラミング言語のモジュール性

どのプログラミング言語でもいいから良く知っている言語のモジュール構造を調べて、この章で説明した基準と原則がどの程度満たされているかを評価せよ。

「言語のモジュール性」を評価するとはどういうことなのか、最初は意味が分かりませんでした。ある言語で書かれたソースコードのモジュール性を評価しなさい、という話なら理解できるのですが。

ここでは、言語自体の特徴や標準APIの仕様などに着目して考えればよいようです。

というわけで、Javaについて考えてみます。

5つの基準

p.50から引用。

「モジュール性がある」と呼ぶ価値のある設計手法は、(略)5つの基本的な必要条件を満たしていなければならない。

Javaが、次の5つの基準をどの程度備えているかを考える。

モジュールの分解しやすさ

Javaでは、1つのクラスのmainメソッドに全部の処理を書こうと思えば書けてしまう。これは極端な話だが、そう考えると、Javaでは分解しやすさがそれほど担保されていないといえる。

一方で、Javaではすべての処理が、何らかのクラスに属する。処理がクラスに分割されうるという意味では、分解しやすさを備えているといえる。

また、Javaは、グローバルなセットアップを最初にしなければ動かないような言語機構ではない(そういうフレームワークはあるかもしれないが、言語標準の機能ではない)。部分を分離独立させることができるという意味で、分解しやすさを備えているといえるだろう。

モジュールの組み合わせやすさ

「もともと開発されたのとは全く異なる環境においても、互いを自由に組み合わせ」られるかどうかについて。

Javaは、JVMさえあれば、開発環境と異なる場所でも動かすことができる。別の環境で開発されたライブラリを持ってきて、一緒に使うこともできる。

モジュールの分かりやすさ

Javaは、シグネチャを見るだけで、戻り値や引数の型、数が分かる。これは分かりやすさのひとつの形といえる。

また、標準APIの一部では、よく知られたデザインパターンが使われていて、そのものずばりの名前がついている(たとえば、java.nio.file.FileVisitor)。これも、分かりやすさを支援しているといえる。

Javaの例ではないが、たとえばExcelの関数名は、AVGは平均を取得する関数だとか、MAXは最大値を取得する関数だとか、見れば機能が大体分かる。これも、分かりやすさの一例といえる。

モジュールの連続性

「連続性」だけだと、あとで意味が分からなくなりそうなので、定義を引用しておく。(p.56)

ある手法によって生み出されたソフトウェアアーキテクチャ内で、問題の仕様に小さな変更が生じた際に1つまたは少数のモジュールの変更しか引き起こされない場合、その手法は「モジュールの連続性」を満たしている。

連続性とは、発生した変更を個々のモジュールで吸収できる性質のこと。

定数を宣言して使用できることは、連続性を向上させることに貢献するらしい。もちろん、Javaでは定数を定義できる。

モジュールの保護性

エラーの影響を局所的に抑える性質について。

Javaは、様々なエラーをより上位(呼び出し元)にthrowできる。標準APIも、例外の処理は利用者まかせで、なにか起きると例外を投げて寄越す。そのため、Javaのこの性質に関する評価は低いと考える。

エラーの発生を伝達することを目的とした大域脱出を許す言語は、どれも同じと考えてよいかもしれない。

5つの規則

この演習では触れないが、5つの基準から導かれる「守らなければならない5つの規則」は、次のとおり。

  • 直接的な写像
  • 少ないインタフェース
  • 小さいインタフェース
  • 明示的なインタフェース
  • 情報隠蔽

情報隠蔽は名前が分かりづらい。「公開情報にのみ依存せよ」と言い換えて理解するとよいかもしれない。

情報隠蔽という言葉は、「隠蔽する側」のモジュールについて話しているように感じるが、実際はその外側にあるモジュールに関する話だ。情報隠蔽は、「あるモジュールAを利用する顧客モジュールBは、Aの公開された部分にだけ依存すること」を指す。

5つの原則

5つの基準と5つの規則から導かれる「5つの原則」がある。

Javaが、次の5つの原則をどの程度守っているかを考える。

言語としてのモジュール単位

これも、あとで意味が分からなくなりそうなので、定義を引用しておく。(p.67)

モジュールは使用される言語の構文単位に対応していなければならない。

ちょっと難しい。本文には、オブジェクト指向を直接サポートしない言語で、オブジェクト指向の設計や実装をしようとすると、この原則に反する、というようなことが書いてある。これを具体的に考えてみる。

たとえば、C言語オブジェクト指向のような書き方をしようと思ったとする。その場合、(想像だけれども)クラスを擬似的に表現するために構造体を使ったり、プリプロセッサを多用するのではないか。そういった無理のある書き方が、モジュールと言語の構文単位が対応していない結果を引き起こす、といえるのだろう。

では、Javaの構文は、Javaのモジュールに対応しているか? 「モジュール」の明確な定義が、ここまでで登場していないので、よく分からない。保留とする。

自己文書化

Javaは、Javadocというドキュメントジェネレータを持っているので、がんばっているといえるでしょう。

統一形式アクセス

表記の話と考えるなら、Javaでは、メンバーにアクセスするための表記が、プロパティに対するそれとメソッドに対するそれで異なる。プロパティの場合、プロパティ名だけでよいが、メソッドの場合、メソッド名の後にカッコ(と引数)が必要だ。そのため、Javaは、統一形式アクセスをあまり守っていないと考える。

また、シンタックスシュガーとして、クラスのメンバーへのアクセスに複数の表記を提供する言語がある。これも、統一形式アクセスの原則には従っていないといえる。

開放/閉鎖の原則

Javaでは、継承の機構を使って、後から機能を足すことができるので、開いているといえると思う。

また、自分のコードの他のクラスや、他のライブラリのクラスをimportして使うことができるので、閉じているといえると思う。

単一責任選択

Javaを使って、単一責任選択を意識したコードを(熟練者なら)記述することができる。しかし、Javaを使うだけで、誰でも必ずできるとは限らない。言語のサポートに関してはそんな感じなので、回答に迷うところ。何か考え方があれば知りたいです。

今日はここまで。