Software Engineering Lecture 6/13

Menu Menu


先週の復習


ユースケース

ユースケースはユーザが、対象とするシステムで何をするかを説明する文書である。

Card.pm を使って、マルチユーザ・カードゲームを作る時のユースケース一つを取り出し、記述してみよ。


図の書き方

UML などの図は、専用のエディタを作ることも多い。Java で記述されたツールや、C++ で記述されたものある。しかし、コンピュータ上で記述することは必須ではない。特に、UMLは手書きでも使えるように設計されている。

PC Unix上で、UMLを記述するのには、Tgif が便利だろう。Idraw も使えるが、残念ながら、一部のPostScript Printer (Oki 600PS)などでは日本語がうまく出力されないようである。琉大のパッチをあてた Tgif ならば、そういう問題は生じない。(逆に言えば、Tgif でも Oki 600PSではパッチが必要になる。不幸なことである...)

Tgif/Idraw は、Draw 系ツールと呼ばれ、回路図やUML、あるいは、論文で使うような説明的な図に向いてる。Gimp/Xpaint などは、Pictrue系あるいはPaint系などと呼ばれ、画像の処理や、お絵書きに向いてる。Draw 系のツールは、出力が可読形式になっていることが多い。 ( Windows や Mac では、そのようなことは、めったにない。それは、単に絵を書くだけの知能しか持たないユーザを対象にしているからだろう....)

Draw系の出力を処理することにより、例えば、UML図から、プログラムを生成することなどが、Perl などを使って簡単に実現できる。


問題

前回のCard.pm の概念図を Tgif を使って記述し、Perl のプログラムを生成するPerl のプログラムを作成してみよ。

参考: Tgif のobj ファイルから Idraw のファイルを生成するプログラムがある。これ を使ってみよう。


図のメールでの送り方

図を送るには、MIME (Multipurpose Internet Mail Extensions) を使う。

図は、Tgif の obj ファイルなどを送っても、可哀想な Windows ユーザは見ることができないだろう。PostScript に変換すれば、GhostScript などを使って見ることができるかも知れない。しかし、もともとのWindows には、そんなものは入っていないので、GIF などに変換する必要があるかも知れない。しかし、GIF にしてしまうと、画面の解像度などに強く影響されてしまう。解決策は、もちろん、Windows なんか使わないというのが一番であるが、馬鹿に合わせることも、世の中では必要であろう...

なので、ここでは PostScript で送ることにする。PDF という PostScript のサブセットを使うことも出来るが、PDF を生成するプログラムは、Windows 上では有料である。Free のものも若干存在するようである。

Tgif から PostScript を生成するには、print command を使えば良い。Idraw からは、生成する必要さえない。もともと Idraw は、PostScript を構造化したファイル形式を使っているからである。しかし、PostScript は、フォントなどの設定から、(特に Level 3から)互換性が落ちているので、メールでやりとする際には気を付ける必要がある。

Unix から MIMEのメッセージを送る方法はいくつかある。しかし、どれもめんどくさいことも確かである。tar + uuencode のような形式で送る、あるいは、shar という shell script を生成して送るような方法もある。

(shar を使って、コンピュータ・ビールスのようなものを送ることもできるが、Unix では、そのまま見えてしまうので、ださださなものになってしまう。しかし、最近流行った、I LOVE YOU のメール経由のビールスは、本質的にはそのようなものである。しかし、それらは、Visual Basic などに隠されているので、Windows などでは脅威となりうるらしい。そんなシステムを君達は本当に使うのか? それはともかく...)

MIME を送る方法は、

	mailto (metamail コマンド)
	mhn (MH の MIME comamnd)
	mnews

などがある。metamail は、RSI (琉大標準インストール)には入ってないかも知れない。mnews が MIME に対応してるかどうかは version によるらしい。mhn を使う方法が直接的なので、それを使ってみよう。

comp で手動でメールを作成したあと、

    #<text/plain;charset=iso-2022-jp;encoding=7bit
    #image/gif [photo] test.gif

という形の文をいれておく。本文は、JIS にしておこう。これを、
	edit mhn

とすることにより、MIME 形式に展開される。正しいことをざっと確認して、送信すれば良い。こういうプログラム も便利らしい。

(MIMEで、Word などの文書を送ることは慎むべきだろう。理由は何故か?)


概念モデルの実装

Perl では、参照関係は、無名ハッシュを使って実装する。概念モデルでは、対応は様々である。以下の関係を実装するオブジェクトは、Perl の無名配列への参照を使うことにより簡単に実装できる。


継承関係

もう一つの関係は、オブジェクトの性質に関連する。これは、クラスの参照関係でもある。クラスは、オブジェクトのメタな性質を表していると言うことがある。meta というのは、
	高階記述(Higher Order)	手続きそのものではなくて、手続きの変更などの記述
	実装記述(Implementation)	手続きそのものではなくて、手続きを他の(多くの場合、より基本的な)機構により記述すること

を指すことが多い。

継承関係は、オブジェクトの持つ手続きの間の相互関係なので、メタな関係である。

Perl では、継承関係は、無名ハッシュの共有と、複数パッケージの手続き(サブルーチン)を結びつけることで実現されている。


単一継承と多重継承

オブジェクト指向プログラミングでは、プログラムの再利用ということが言われる。これは実際のプログラム技術としては、継承というメカニズムを使って行なわれる。このメカニズムには、大きく分けて二つの方法がある。一つは、継承できるclass は一つしか無いというものであり、もう一つは、複数のclassを継承することを許す方法である。

単一継承では、プログラムのコードの共有は単純であり再利用は上位のclass の変更と言う形で行なわれる。個々のメソッドの基本的なものは上位のclass で決めるのが普通である。これを逆に利用して、上位のclassにはわざと実装を記述しないと言う方法もある。このようなclassを抽象class (abstract class)という。これは、このclassを継承するオブジェクトに必要なプロトコルを規定していると考えることもできる。単一継承にはインスタンス変数のオフセットを簡単に決めることができるという実装上の利点もある。

多重継承では、個々のclassを部品として構成することが多い。必要な部品を集め、それぞれの機能を利用してプログラムを作りあげる。この方がコードの再利用率は高くなる。その一方で、それぞれの部品の整合性を取ることは難しくなる。また、単一継承の場合と異なり、インスタンス変数のオフセットを単純に決めることができない。また、多重継承は、インスタンス変数に部品となるオブジェクトを格納しておき、必要な時に、そのオブジェクトに処理を委託するという方法で実現することもできる。これは委譲(delegate)と呼ばれる。

多重継承でも抽象クラスを使うことができるが、抽象クラスの役割だけを、取りだす方法もある。これはインタフェースとかプロトコルと呼ばれることが多いようである。例えば、単一継承のシステムで、受け入れられるメソッドの種類だけを記述する記述法を用意して、自分が使う変数に対して、インタフェースを指定するというように使う。


継承の単調増加性

もし、継承によりオブジェクトの属性や機能が増えるだけならば、それは単調増加であると呼ばれる。クラスの構造は、できるだけ、単調増加であることが望ましい。

しかし、それが可能でない場合もでてくる。例えば、鯨は哺乳類だが、足がない。哺乳類のクラスに足を属性として入れてしまうと、鯨にも足が必ずあることになってしまう。

この場合、鯨のオブジェクトを生成する際に、足の属性を削除することもできるが、例えば、walk などのメソッドも一緒に削除する必要がある。これらは、メソッドを明示的に overwrite することにより実現する場合が多い。

オブジェクトの属性にアクセスする場合に、オブジェクトのインスタンス変数を直接参照する方法を使うと、このような制限を付けることはできなくなってしまう。したがって、オブジェクトの汎用性を上げたいならば、インスタンス変数に対するアクセスは、すべてメソッド経由で行なうべきである。


オブジェクトの属性とクラス

クラスはオブジェクトの属性でもある。SimpleCard.pm を、Visible Card と Hidden Card の二つのクラスに分割して実装することを考える。

Perl による実装を継承を用いて記述し、この方法の利点と欠点を考察せよ。


抽象クラスとインターフェース

もし、あるクラスの記述が実装を持たないならば、それは、そのクラスが持つべきメソッドの集合を示す枠組となる。このようなクラスを抽象クラス (Abstract Class)と言う。抽象クラスは、属性値の集合を定義した、データベース・レコードとして使う場合がある。ある特定の抽象クラスを継承していれば、そのデータベースとしての性質を持っていると期待できる。この場合、属性値が継承によって削除されてしまうことは、望ましくない。したがって、抽象クラスの継承は、単調増加性を保証すべきであると考えられる。この単調増加性を保証するため、抽象クラスは単一継承されるのが普通である。(本当か?)

一方で、あるオブジェクトが持つ 機能(APIやメソッド) の集合 を確認したい場合がある。それが明確になれば、安心して、そのオブジェクトにアクセスすることができる。直接的には、コンパイラなどにより、実装されていないメソッドなどの呼出しを検出することができる。特に、分散オブジェクトなど、他の環境化での実装を、オブジェクト定義時に参照できない場合には、これが重要である。このメソッドの集合を規定したものをインターフェースと呼ぶ。

インターフェースは、抽象クラスを使って記述することも出来る。しかし、それらは、まったく別なものであることを理解する必要がある。Java やObjective-C では、インターフェースはクラスの継承とは別な構文として用意されている。C++ では、特別な構文がないので、抽象クラスを多重継承することにより、実現することが多い。

抽象クラスでは属性は必ず単調増加的に継承される必要がある。しかし、インタフェースは、あくまでもメソッドの集合だけを記述しているので、属性の内容には立ち入らない。インタフェースは属性値を増やさないので、多重継承しても実装上の問題は生じないと言う利点がある。


単一継承、多重継承の Perl での実装

Perl では、@ISA という特殊変数にパッケージを複数記述することにより、単一継承、多重継承を実現することができる。


問題

ファイルに対する操作には、block I/O, sequential I/Oがある。Unix では、それらは、write/read と seek によって実現される。また、これに対してbuffering を使った、fwrite, fread, fgetc, fputc、そして、入出力をstdioに限定した、getchar, putchar がある。これらをclass として実現するとしよう。可能な多重継承による構成と、単一継承による構成を考えて、それぞれの利点と欠点について考察せよ。

これらを、Perl のオブジェクトを使用して実装してみよ。多重継承や単一継承の利点と欠点は、Perl のオブジェクトでは、どのように現われたかを考察せよ。

以上の構成で、どのクラスが抽象クラスであり、インタフェースであるべきかを考察せよ。


宿題

解答は、kono@ie.u-ryukyu.ac.jp まで、来週までにメールで送ること。Subject には、
   Report on Software Engineering Lecture 6/13

を付けること。


Shinji KONO / Tue Jun 13 14:14:03 2000