
知史さん

航祐君
新人の航祐(こうすけ)君とそのチューターの知史(さとし)さんの会話です。
どうやら航祐君、Javaのプログラミングで悩みがあるようです。
航祐
「知史先輩、こんにちは」
知史
「おお、航祐君か。 どうだい新人教育はうまくいっているかな」
航祐
「それがちょっと行き詰まっているんですよ」
知史
「ほー。 どんなところ?」
航祐
「実は、この前のプログラム演習で出た課題なんですが…」

「僕は次のように書いたのです」

「答えもちゃんと出ました」

知史
「うんうん、なるほど。 プランを数字の1か2で識別しているところは、ちょっと良くないが、まあまあのできだね」
航祐
「でしょう、でしょう。 でも、先生は『実務で使うにはこのようなプログラムではなく、オブジェクト指向のプログラムにしなければならない』と言うんですよ。 このプログラムのどこが悪いのか判りません」
知史
「うん、確かにこの課題だけに限ればこのプログラムで十分だと言えるね。 しかし、実際に業務で使うプログラムとしてはこれではダメなんだ。 先生の言うとおりだね」
航祐
「え~、どうしてですか」
知史
「悪いところは拡張性がないことさ。 通常の業務プログラムでは1回作ればそれで終わりであることは少なく、機能の拡張が要求されるんだ。 航祐君もプロのプログラマーをめざすなら、将来の拡張性を考えたプログラムを作れねばならない。 この課題プログラムではどんな拡張性が要求されるか考えてごらん」
航祐
「え~と、今はプランが楽々と得々の2つだけですが、今後はさらに増えるかも知れません」
知史
「そうだね。 追加されるプランは、基本料金や単位時間当たりの通話料が変わるだけでなく、通信相手や時間帯でも変わるかも知れないぞ。 いまの携帯電話サービスを見るとよく判るね」
航祐
「その他にも、固定電話との料金や特定の相手だけ安いなんてプランもあります」
知史
「そうだ。 この構造のままでは料金計算メソッドのcharge( )の部分がどんどん膨らんでしまう。 しかし、C言語などの非オブジェクト指向言語では、航祐君のプログラムのようにしか書けなかったんだ。 だからソースを印刷すると、ロジック部分が延々と何ページにもわたって書かれているプログラムも珍しくなかった」
航祐
「へ~、そうなんですか」
知史
「複雑なロジックも書いているときは記憶が鮮明なのでよく判る。 しかし、ちょっと時間がたつと、自分で書いたものでも、どこに何があるのかさっぱり判らなくなってしまうんだ。 熟達者はコメントやインデントなどを駆使して、見た人が判りやすいようにいろいろ工夫するが、しょせんプログラム自身に何の構造も無いので限界があるんだ」
航祐
「ふ~ん」
知史
「航祐君のプログラムもこのままではそうなってしまうぞ。 せっかくオブジェクト指向言語で書いている意味が無くなってしまうんだ」
航祐
「なるほど、判りました」
知史
「さらには携帯メールサービスや集金状況の管理もしてくれと言われるかも知れないぞ。 拡張の要件を整理してみよう」
航祐
「はい。 こんなところでしょうか」
知史
「うん、いいね。 ではこのような拡張性を意識してプログラムを書いてみよう。 その前にちょっとオブジェクト指向言語の復習をするぞ」
知史
「まず、Javaのプログラムは『クラス』という単位で構成されていたね。 クラスの構成要素にはどんなものがあったかな」
航祐
「はい。 変数とメソッドです」
知史
「そう。
クラスはデータを格納する領域である『変数』と、処理を記述する『メソッド』から構成されている。
航祐君の例から離れるが個人の名前と年齢を管理するPersonと言うクラスを考えてみよう」
航祐
「メソッドなんて、ヘンな名前ですね」
知史
「うん。 オブジェクト指向言語の元祖と言われているSmallTalkと言う言語で使われた名称だね。 メソッドは1つのまとまった機能を実現するためのプログラムだ。 COBOLで言えばサブルーチン、Cを知っている人は関数だと思えばよい。 ところで、変数とそれを処理するメソッドを1つのクラスにまとめておくことを何と言うのかな」
航祐
「カプセル化です」
知史
「そうだね。
変数とそれを処理するメソッドとをまとめて扱うことで、独立性を高め外部からの干渉や誤用を減らすことができる。
この考え方をカプセル化と言うのだ」
航祐
「独立性が高いことがそんなに重要なんですか」
知史
「うん、非常に重要なことなんだ。 航祐君は開発者の数が多くなればなるほどプログラムの生産性が落ちることは知っているよね」
航祐
「はい。 遅延したプロジェクトにいくら人を投入しても効果がないと言う話を聞いたことがあります」
知史
「そうだね。
その話には別の要素もあるが、一般にシステムの規模が大きくなると、プログラムの相互の関係が複雑になり、生産性はどんどん落ちる。
200人月相当の100Kstepのプログラムが完全に独立な50Kstepのプログラム2本に分割できたとする。
サイズが小さくなればstep当たりの生産性は向上するので、全体として必要な工数は減少する。
プログラムを互いに独立な部分に分けることができれば、生産性は大幅に改善されるんだ」
航祐
「なるほど、そうですね」
知史
「実際には完全に独立にはならないまでも、独立性を高めれば、その分だけ生産性が改善される。 具体的なカプセル化の効果は外部利用者が内部の構造を知らずに操作できることだ。 逆に内部の開発者は、外向けの仕様さえ守れば内部を自由に作成、改変することができる。 カプセル化が大切なことが判ってもらえたかな」
航祐
「はい。 うまくカプセル化すれば、小さなプログラムの集合になり、全体の生産性が上がります」
知史
「そうだね。 プログラムをいかにうまく独立した機能に分割できるかが勝負だ。 その分割単位がクラスだね。 航祐君のプログラムは、少なくとも3つのクラスに分割できると思うよ」
航祐
「え~。 どういう風に分けるんですか」
知史
「うん。
メインクラスと、Userクラスと、Planクラスだね。
Planクラスはさらに楽々プランクラスと得々プランクラスに分解できる。
後でプログラムを作ってみよう」
航祐
「わ~。 ありがとうございます」
知史
「ところで、カプセル化はオブジェクト指向の三大機能の一つだね。 あとの2つは知っているかな」
航祐
「え~と、継承と…」
知史
「多態性だ。
ポリモーフィズムの訳だね。
オブジェクト指向プログラミングを実現するには、(1)カプセル化、(2)継承、(3)多態性、この3つの機能の活用がポイントだ」
航祐
「難しそうですね」
知史
「そうだね。 しかし、ここを理解しないとオブジェクト指向プログラミングは書けないぞ。 頑張ってやってみよう」
航祐
「はい。 よろしくお願いします」
知史
「それでは第2の機能である継承だ。 航祐君は継承は知っているよね」
航祐
「はい、継承を使うと、親のクラスの変数やメソッドを子のクラスで引き継いで使えます。 さらに子のクラス固有の機能を付加することができます」
知史
「そうだね。
次のコードはさっきのPersonクラスを継承してStudent(学生)クラスとBusinessmanクラスを定義する例だ。
Studentクラスでは変数としてgrade(学年)、Businessmanクラスではsection(所属)が定義されているだけだ。
しかしPersonクラスを継承しているので、Personクラスで定義した変数やメソッドは、ここに書かなくても、書いたのと同じ効果があるのだ」

知史
「継承の原語であるinheritance(インヘリタンス)には遺産とか相続の意味がある。 継承とは、まさに親の遺産をそっくり受け継いで、最初から自分が持っていたかのように利用することだ。 航祐君のプログラムでも継承を使ってみよう」
航祐
「え~。 こんな小さなプログラムでも継承が使えるんですか」
知史
「さっき言った楽々プランクラスと得々プランクラスは、Planクラスを継承して作るとうまくいくと思うよ。 これも実例を後で示そう」
航祐
「はい。 楽しみです」
知史
「最後に多態性だ。 これは簡単に言えば、あるものが状況によって異なる機能を果たすと言うことだ。 別のものに同じ名前を付けると言ってもよい。 これによって、やはりプログラムの関係が薄まり独立性が増すのだ。 多態性も実例を使って後で話そう」
航祐
「おもしろそうですね」
知史
「オブジェクト指向言語のポイントを説明したが、判ったかな。 今日はもう遅いので、プログラムの作成はまた明日にしよう」
航祐
「はい。 ありがとうございました。 よろしくお願いします」