Skip to content.

Sections
Personal tools
You are here: Home » コミュニティ » masarl memorial » homepage3.nifty.com » masarl » article » nifty-logs » Niftyの過去ログ集 - インターフェイスと Uniform Access Principle

Niftyの過去ログ集 - インターフェイスと Uniform Access Principle

Document Actions

インターフェイスと Uniform Access Principle

Java ですっかり有名になったインターフェイスですが,インターフェイスとクラスを別々のネーミングルールにする(例えば,インターフェイス名の先頭には I をつける)ということが多いようです.最近はそうでもなくなりましたが,当時は抵抗がありました.

01588/01588 BYI20012  まさーる         インターフェイスの概念
( 6)   98/08/17 00:31  01587へのコメント

田中 祐 さん、こんにちは。

>ちなみに、UML でもそうです。従来だったら、「インターフェイス」は単なるモ
>ジュールだとかクラスのインターフェイスといった、なにかどこかに従属する要
>素でしたが、COM とか Java とかのこういった最近の考え方ではインターフェイ
>スという概念そのものを独立させて特別扱いにするというのがはやりといって良
>いのではないでしょうか。このあたりは、「分散処理」がそういった考え方を必
>要としているからだと考えています。もっとも、先日まさーるさんが東京に来た
>ときに会って(けっこう濃い)話をしちゃったりなんかしたんですが、それと逆行
>する意見などもあるそうでまだまだ議論の余地が多いというところもあるようで
>す。

先日はどうもでした.そのときは時間切れでしたので続けましょう(笑).

意味的にクラスとインターフェイスを区別すると,

・クラス <---> 名詞
・インターフェイス <---> 形容詞

という対応になると思いますが,C++では

・クラス <---> 名詞
・Mix-inクラス <---> 形容詞

という風にして多重継承ベースにするのが僕のスタイル(というか目標)でした.
僕が特別扱いしない,というのはこの影響があるのかもしれませんね.C++では
両方ともクラスで実装されているから.

究極的には,オブジェクトを生成する側だけが名詞であることを知っていて,オ
ブジェクトをアクセスするユーザはもっぱら形容詞としてアクセスできるのが理
想だと思います(という意味で区別なのかな?).でも現実はそう組めるわけは
ないでしょう.

クラスとインターフェイスじゃないですが,MeyerはUniform Access Principle
というのをモジュールやクラスが満たすべき性質の一つとして挙げています.そ
れはオブジェクトのプロパティにアクセスするとき,

y = x.property;
y = x.property();

のようにそのプロパティがメンバ変数なのかメンバ関数なのか,呼び出し側が区
別しなければならないのはよくない,というものです.

これと同じことがクラスとインターフェイスにいえるのではないかと思うわけで
す.少なくともユーザの側からネーミングルールなどでクラスとインターフェイ
スを無理矢理区別するとUniform Access Principleを守れないからだめだと思う
のです.

うーん,でも以上の話は全然「分散処理」等を考慮してないのであまり今の風潮
とは合わないのかもしれませんね.この分野はよくわかってないもので.

                                     98/08/17(月) まさーる(BYI20012)

Uniform Access Principle にひっかけて,呼び側はインターフェイスかクラスか区別しないようにしたい,というのが僕の主張です.

01594/01594 BYI20012  まさーる         RE^2:インターフェイスの概念
( 6)   98/08/18 01:31  01589へのコメント

田中 祐 さん、こんにちは。

>次こそは八重洲ブックセンターと神保町を案内いたしましょう。

実は次の日の夜,時間が空いたので八重州ブックセンターに行ってみました.あ
そこはいいですねえ.

>》・クラス <---> 名詞
>》・インターフェイス <---> 形容詞
>形容詞ですか…、うーむ。たしかにいわれてみれば、そうではありますね。例え
>ば、「人間:まさーる」オブジェクトは「社員」インターフェイスによって形容
>されているというわけですね。現実的にはふつうは人間でない社員は考えないで
>すから「社員」を持ち出すとミスリーディングで、例としては不適当かもしれま
>せんが。

クラスは名詞,インターフェイスは形容詞のネーミングが適当な場合が多いです.
形容詞といっても able で終わるものとかですね.うーん,やっぱり区別してる
やん,とつっこまれちゃいますね(^^;.

田中さんが不適当といった「人間」と「社員」の例はこっちにとっては好都合か
もしれません.この場合,実際の開発では「社員クラス」を作るのが普通でしょ
う.その後「人間クラス」が必要になり,社員クラスは「社員インターフェイス」
として扱う方がいい,というように後から変更するというプロセスになるが自然
だと思います.

このとき,もしクラスとインターフェイスを区別しない立場でプログラムを作っ
ていたら,社員クラスを利用していたモジュールはほとんど修正せずに社員イン
ターフェイスに移行できるんじゃないでしょうか.そういう意味でUniform 
Access Principleなわけです.


>ちなみに、UML1.1 で定義されているのは次の通りです。

UMLの定義は初めてみましたが,無難なところをついているようですね.

ちょっと話しそれるかもしれませんが,

>|    Synonym: class [OMA]. 

の[OMA]ってなんでしょうか? なんでSynonymなのに同じ単語なんでしょう?


>これはもっぱらオブジェクトを利用する側での考えですが、一方でオブジェクト
>を提供する側でも、けっきょくインターフェイスを分離する必要があることを意
>味しています。利用者が幸せになるためにはできるだけインターフェイスのみで
>オブジェクトを把握したい、そして、提供者は利用者の幸せのためにはインター
>フェイスを分離しておいてあげないといけない、というところです。

そうですね.オブジェクトからインターフェイスを分離するだけじゃなく,場合
によってはインターフェイスそのものも複数に分離する必要がありますね.利用
者は必要なインターフェイスのみを見ていたい,不必要なインターフェイスは知
らん,と.


>》のようにそのプロパティがメンバ変数なのかメンバ関数なのか,呼び出し側が区
>》別しなければならないのはよくない,というものです.
>インターフェイスの話題からはちょっと離れてしまいそうですが、これには同感
>です。私はこれについては、C/C++ のように引数が無いときには空のパラメータ
>を "()" で指定しなくてはいけないほうが、なんか違うのではないかなぁと思い
>ます。これはそれぞれの言語に特有の癖であるといってしまえばそれまでの話で
>はありますが(Ada なんかこんなときには "()" は付けなかったと思う)。

いえ,言語の統一性とかそういったことより,Uniform Access Principleはもっ
と現実的な話だと思いますよ.これを満たす言語として一番ポピュラーなのが
Visual Basicでしょう.これが便利なのは,とりあえずメンバ変数として与えて
おいて,後からこっそりメンバ関数にできますから(Property Let,Property 
Getというやつです).一般にOOPではパブリックなメンバ変数はよくないという
ルールがありますが,Uniform Access Principleを満たす言語ではそれほど気に
しなくていいというメリットがあります.


>なんか、先日私とまさーるさんとでやきとりを食べながら話した内容って、反芻
>してみると、この利用する側と提供する側の立場が私とまさーるさんとで交錯し
>ていただけに過ぎないような気もなきにしもあらずですね(私のほうは酒が入って
>ましたし)。

ですね.

話が飛びますが,このあたりの話って古典数学と現代数学の違いに似ていると思
うんですよね.古典数学(って単語あるんかいな)は計算そのものを扱う側面が
強いのに対して,現代数学は「〜を満たすもの」という形式的な側面が強い.

「〜を満たすもの」はそのままインターフェイスと解釈できますが,現代数学の
場合はそれが現実にある「もの」であるかのように扱っています.群の公理を満
たす,という本来インターフェイスであるものが,群という,もの,名詞,クラ
スとして扱われている.一概にクラスなのか,インターフェイスなのか区別でき
ない,というか... 

うーん自分でもわけわかんなくなってきた(^^;.ごめんなさい.

                                     98/08/18(火) まさーる(BYI20012)

当時(っていっても2年前か)はリファクタリングなんて全然注目されてなかったのですが,一応クラスをインターフェイスにするっていうリファクタリングを意識してました(ちょっと手元にその本がないので,載ってたかどうか忘れました).クラスではなくいきなりインターフェイスというのは考え方の順序としては難しいと思うんですよね.

インターフェイスについて考えるとき,どういう思考パターンになっているかを書いたのが次の発言です.

01601/01601 BYI20012  まさーる         RE^4:インターフェイスの概念
( 6)   98/08/20 00:20  01597へのコメント

田中 祐 さん、こんにちは。

>なるほど。とすると、実は、「パブリックなメンバ変数はよくない」のではなく、
>メンバ変数を直接アクセスすると多くのオブジェクト指向言語では暗黙的にメン
>バーにアクセスする関数がよばれてしまうからよくない、ということなんでしょ
>うか。

多くのオブジェクト指向言語では暗黙的にメンバーにアクセスする関数を呼ぶこ
とができないからよくない,ですよね?

>》話が飛びますが,このあたりの話って古典数学と現代数学の違いに似ていると思
>》うんですよね.古典数学(って単語あるんかいな)は計算そのものを扱う側面が
>》強いのに対して,現代数学は「〜を満たすもの」という形式的な側面が強い.
>》
>》「〜を満たすもの」はそのままインターフェイスと解釈できますが,現代数学の
>》場合はそれが現実にある「もの」であるかのように扱っています.群の公理を満
>》たす,という本来インターフェイスであるものが,群という,もの,名詞,クラ
>》スとして扱われている.一概にクラスなのか,インターフェイスなのか区別でき
>》ない,というか... 
>あっちのほうでは抽象的な思考過程をワンクッション置きながらすすめていくこ
>とを強制されるからわけがわからなくなってしまうのですよね。やっぱ、これか
>らはカテゴリーっすか?

ひー,そこでカテゴリーを出されると余計わかんなくなるじゃないですか(^^;.
集合論で行きましょう.

普通,クラスを考える際にはまず

人間クラス:  まさーる,田中さん,小林さん, T's-Nekoさん,...

と実体から考えるんですが,その後

人間クラス: 頭,胴体,手,足,...からなる

人間クラス: 歩ける,話せる,食べれる,歌える,...

という2通りの考え方になるんじゃないかと(ちょっと青木淳さんの本を参考に
しました).

実際にはこの2つが組み合わさっているのが普通でしょうが,どちらかというと
後者の方がOO的だと思います.もっというと,現代数学の考え方では,完全に逆
転して「歩ける,話せる,食べれる,歌える」そのものが人間になってしまうん
ですが,これと同じことがOOにもいえるのではないかと.

つまり,人間に属するものであった性質を逆に人間の定義にしてしまえ,という
ことで,性質の方が主,実体が従になってしまったということですよね.

このあたりの話は,Robert MartinのDependency Inversion Principleにも通じ
るところがあって,多分このPrincipleの意味的な解釈になっていると思います.

インターフェイスを考えるとき,こういう思考パターンになっているような気が
します.でもこれはインターフェイスがそれほど注目されていなかったクラスそ
のもの,とくに親クラス,抽象クラスなどを考えるときに有効だったことで,別
にクラスかインターフェイスかで区別して考えるようなことはあまりしてないん
です.

                                     98/08/20(木) まさーる(BYI20012)

最後に,上の発言でもちょっとふれた,Uniform Access Principle とオブジェクト指向の法則との関係についての発言です.前半は,集合論のノーテーションのお話なので無視してください.

01615/01618 BYI20012  まさーる         RE^6:インターフェイスの概念
( 6)   98/08/22 16:46  01607へのコメント

田中 祐 さん、こんにちは。

>もあります。私がよく引数のタイプが B で返り値のタイプが A の関数を A^B の
>要素などといった書き方をするのはこのあたりから来ているのですが、そこから
>先に進めないでいます。

多分,僕を含め,小林さんも混乱しておられる一つがこの A^B でしょうね(^^;.
(違ってたらごめんなさい>小林さん).

なぜ A → B への関数全体の集合をなぜ A^B と表すのか? 集合 A の B 乗って
どういうこと? という疑問が..(これは一般的な表しかたなんですか?).

想像するに,A^2 だと A の直積,つまり A×A という集合を表していてこれを
関数 {0,1} → A への関数全体と解釈できるということでしょうか.

つまり,A×A はペア(a0, a1) の集まりなので,ペアの一つをとって

  f(0) = a0
  f(1) = a1

という関数 f であるとみなせば A×A は {0,1} → A への関数全体を表すと.

B → A の関数の場合はこれを一般化した表記だということでいいですか?

>Uniform Access をインターフェイスの文脈に適応したとしても、クラスのとイ
>ンターフェイスを区別せずに、ということはならないと思います。これは、場合
>によって雑多なアクセス方法があるより単一の方法でできたほうが良い、という
>ことを言っていると思います。また、Dependency Inversion は抽象化と実装の
>分離の重要性を強調しているわけです。Robert Martin の一連の Principles で
>いったら、ほかにインターフェイスに関係していそうなものとしては Liskov 
>Substitution とか Interface Segration とかもありますが、これらは、実装に
>依存するなさせるな、余計なインターフェイスを強要するのはよくない、といっ
>ているわけで、私はやっぱり、「明確に区別せよ」といっているように解釈して
>しまいますが。

僕が言っているのはあくまで使う側の視点ですから....作る場合は田中さんの
おっしゃるとおり意識して区別すべきだと思います.

クラスやインターフェイスの設計って使う側の視点に重点を置いた方がいいと思
っているので,この重点の置き方が田中さんと僕とで違うだけです.だから結果
として田中さんと僕の言っていることは同じになってしまうでしょう(^^;.

Liskov Substitution Principleは,

"Functions that use pointers or references to base classes must be able 
to use objects of derived classes without knowing it."

ですが,これは使う側の関数が親クラスか子クラスか区別してはならない,とい
う意味ですよね.つまり,Liskovはクラスの継承関係についてのUniform Access 
Principleだといえます.

今回僕が言っているのは,クラスとインターフェイスの関係についてのUniform 
Access Principleです.あくまで使う側のみについていっています.作るときは
意識してインターフェイスを使って区別すべきでしょう.


それからDependency Inversion Principle (DIP)は,実装がインターフェイスに
依存する,ということですから分離を強調していますが,もっと深いことを言っ
ています.別に構造化プログラミングでもインターフェイスと実装の分離はでき
るわけです.関数で実装をラッピングすればいいですから.このとき,関数のシ
グニチャというインターフェイスは実装に依存しているわけですが,DIPだと実
装の方がインターフェイスに合わせるという意味で従来の考え方と大きく違って
きます.

だからOOPでは意識して依存関係を逆転させるというコペルニクス的転換が必要
なわけです.こう書くと反論するひとがいると思うので,もう少し書きますが,
もちろんOOは従来からある構造化手法なども含んでいます.だからこの文章はOO
のみにある差分を強調しているわけです.別に今までのプログラミング手法を否
定しているのではありません.使い分けたらいいということです.オブジェクト
指向は単なる道具にすぎないのですから(これはこの会議室の共通意見ですね).

                                     98/08/22(土) まさーる(BYI20012)

最後の共通意見っていうのは言い過ぎでちょっと反感をかってしまいました^^;.田中さんとは結局平行線をたどってましたが,多分考えてることは同じなんですよね.