K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[750] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

kit さんへのまとめ。 俺は当初、kit さんは「オブジェクトの is-a など問題にしなくてよい。LSP のみが確かな判断基準となる」と言っているのだと思っていました。 理由は、 > 設計手順としては、まず常識的な is-a を使って継承関係を考えてみた > 上で、それを LSP で検証すればいいんですよ。検証に通らない場合には、 > たとえ常識的なis-a 関係であっても、継承関係にはしません。検証に通 > れば、もちろん継承関係にします。 これを [715] まで言わなかったことです。 しかし、実態は上記の通り、kit さんも、LSP を適用する前に、オブジェクトの is-a での判断を行っています。 そして、俺が [722] で書いた > 結局、この文献は「どんなものを継承関係にすべきか」という指針には、一言も言及していないのです(「どんなものを継承関係にしてはいけないか」は、LSP を用いて言及しています。<以下略>)。 これは、kit さんにも当てはまります。 上記の [715] の文章は、まさにこれだからです。 LSP で検証したことによって、最初に下した「常識的な判断」が正解だったか間違いだったかは確かに分かりますが、その「常識的な判断」は LSP を用いて下したものではありません。 kit さんも、「どんなものを継承関係にするのが正解か」は、LSP を用いて判断していないのです(判断しているのは「結果的に正解だったか」です)。 > これも繰り返しになりますが、「照らすまでもなく」のような暗黙の知識は、 > 法則としては役に立たないんですよ。 「照らすまでもなく間違いと分かる」のは「まるで神に囁かれたかのごとく、なんとなくわかる」のではありませんよ。「LSP など適用しなくても、分析をしっかりとやることによって、きちんと根拠付けて導かれる」のです。 もっとも、kit さんが求める「分析というステップをすっ飛ばして、『LSP に照らすまでもなく』正解が分かる、設計のお手本」から見れば、これでさえ暗黙的に見えるかもしれませんけれど。 kit さんの求めるものとは、「多くの場合に適用できる(が、たまには失敗することもある)、常識的な設計パターン」さえ超越した、「常に成功を約束された設計パターン」なのでしょう。すなわち、「あるクラスAは、どのような案件であるかによらず、常に、他のクラスの子クラスではないか、あるいは、Bの子クラスであるかのどちらかである」という保証(と、AとBの一対一の対応表)ですね。なぜなら、kit さんは「案件によって、Aの親はBが適切な場合も、Cが適切な場合もある。それは案件を分析してみるまで分からない」というのではダメだとおっしゃるからです。 そのようなパターンが本当に存在するのなら、それは素晴らしいことでしょう。 しかし、もしそれを実践したとすると、失敗するケースの方が多いように思えてなりません。 > むしろこういう説明は、 > この説明に沿って機械的に作業していけば、「オブジェクト指向設計」ができるんだ。 > という印象を与えかねないという点で有害だと思います。 > 確かに、ソフト屋は常に一定以上の品質のプログラムを供給しなければならないものであり、その意味では、「機械的にやっていけば誰でもちゃんとした設計ができる」という手法があるのならば大変結構なことです。しかし、残念ながら、オブジェクト指向設計はそこまでいっていないと私は思っています ※4。 > ていうか正直私は、こういうことは、未来永劫、決して「機械的にできる」ようにはならないと思います。 「疑り深いあなたのためのオブジェクト指向再入門/なぜわからなくなってしまうのか?」より抜粋。 わかってらっしゃるじゃないですか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[749] Re:分析と設計
投稿者:タイガー
2007/02/20 02:13:25

>>もしくは、間違ってfly()させちゃいけないのなら >>例外を投げるのもありかなと思います。 >これは LSP 違反だと思うのです。 >http://www2.ocn.ne.jp/~yamagu/object/LSP-J.pdf >の Rectangle と Square の例[本当の問題]と同等な問題を内在させることになりそうです。 >さて、こういう場合に「そもそも同一視すべきだったか」を私は問いたいのです。 ここで、前提条件として以下のものを考えます。 「struct bird { virtual void fly()=0; }; に対し、birdを継承したbat(こうもり)クラスの実装も クライアント側の処理もうまくいった。 ここで新たにpenguin(ペンギン)クラス(処理)を追加する必要が 生じた。」 この時の設計として、penguinクラスとbatクラスを 同一視(例えば、両方ともbirdから継承)すべきかどうかを考えてみます。 私の前回の発言のように、penguinクラスとbatクラスを 同一視して、penguinのfly()の実装で例外を投げようとすると、 birdを扱うクライアント側の処理でbatとpenguinを 同一扱いできないので、LSPに違反します。 つまり、penguinクラスのfly()の実装でどうしても例外を 投げたいのであれば、明らかに設計ミスで、birdクラスで 例外を投げるように設計しておかなければなりません。 しかし、penguinのfly()を、batクラスのfly()とクライアント側で 同一視できるように実装しておけば問題ありません (例えば、fly() {}のような空実装など)。 すなわち、774RRさんが、[745]の2でおっしゃってるように、 既に実装されているクライアント側の処理にマッチするように penguinのfly()を実装すれば問題ありません。 しかし、現実的には全てのクライアント側の処理を調べるのは 現実的ではないので、LSPを頼りに、 「penguinのfly()の振る舞いがbatのfly()の振る舞いと同等である」 という「常識的な」判断ができれば、クライアント側でbatとpenguinが 同一視できると判断しても妥当と言えるかもしれません。 また逆に、LSPに違反した継承を行った場合でも、 クライアント側で両方に共通した使い方のみで実装してあげれば 問題ありません (もちろん、その後、LSPに違反するような実装をクライアント側の 処理で行う実装を追加すれば問題が起きるので設計としては かなり危険な設計ですが)。 また、774RRさんの[743]での以下の疑問 >さて、こういう場合に「そもそも同一視すべきだったか」を私は問いたいのです。 は、「既に存在するクライアント側の処理がどうなっているか」と 「penguinのfly()の実装をどうしたいか」の両方に依存しているので 常に正解の設計方法論はないと私は思います (クライアント側の処理をあらかじめ規定するには、Design by Contractとかに 類する機能が必要だと思います)。 ここで、私の出た結論としては、私自身かなり混乱しているのですが、 つまり、penguinクラスをbirdから派生させてbatと同一視すべきかどうか という設計を迫られたとき、これがLSPに当てはまるかどうかを 考えようとして、 「penguinのfly()の振る舞いが、batのfly()の振る舞いと同一か」 という疑問を持ったとき、 penguinのfly()を実装しようとした時に、どう転んでも クライアント側の実装がbatのfly()と同一視しかできない実装になっている のであれば、全く問題ない訳で、 クライアント側の実装により、少しでも同一視できない可能性があるなら そういう設計すべきでない訳で、 つまり、それをどう判断できるかと言うと、クライアント側のコードの 予想がつかないため、そんなに単純にLSPで判断できないような気が してきました(クラスが単純ならできる場合もありそうです)。 ここでは、fly()関数1つのみを考えている訳ですが、実際は、クラスは 複数の関数を持つ場合がほとんどなので組み合わせるともっと複雑になるし。 結局、同一視すべきかは、LSPはかなり参考にはなるが、 どんな局面でも通用する設計方法は存在せず、「実装依存」な気がします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[748] Re:分析と設計
投稿者:CES
2007/02/20 02:13:25

>bird 派生クラスは全て「飛べる」必要があり、飛べないものをこいつから派生したらダメ。 >1.だから、この bird からダチョウクラスを派生させるのはダメ。 >2.もしダチョウクラスを bird から派生させたいのであれば bird の実装を再検討。 >ではどのような bird にすればよいか、は要件に応じて再分析が必要。 >その再分析の際に「特定の設計原理(銀の弾丸)」ってものはありえない。 >ただその分析の結果の実装は LSP に則るべし。 鼻血が出るほど同意。
[この投稿を含むスレッドを表示] [この投稿を削除]
[747] Re:分析と設計
投稿者:CES
2007/02/20 02:13:25

概ね、皆さんに同意ですね。 >struct bird { virtual void fly()=0; }; このクラス設計が意味するところは簡単で「鳥は飛べる」ただこれだけです。 論理学風の言い方をすれば「鳥ならば飛べる」。 >Q1.案件B(あるいはA’と言い換えても)では「こうもり」を扱う必要が生じた。 >基底クラスを書き換える/書き換えない?派生クラスの実装をどうする? 「飛べるならば鳥である」ではありませんから、コウモリを鳥のサブクラスにすることはできません。 どうしても統一的に扱いたいのならば、Flying-Animal クラスでも導入すべきです。 >Q2.案件C(あるいはA”)では「ダチョウ」「ペンギン」を扱う必要が生じた。 >基底クラスを書き換える/書き換えない?派生クラスの実装をどうする? これは、前提条件が崩れているわけですから、理想的には一からやり直すべきです。 鳥クラスの下に「飛べる鳥」クラスと「飛べない鳥」クラスを設けて、fly メソッドは飛べる鳥クラスに移動する…と、既存の bird.fly メソッドを使っているコードは動かなくなりますね。 コスト的にやり直しが許されないのならば、飛べない鳥クラスの fly メソッドは、何もしない空実装にするのも手かもしれません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[746] Re:分析と設計
投稿者:のぐー
2007/02/20 02:13:25

>struct bird { virtual void fly()=0; }; オブジェクト指向ぜんぜん分かってない者ですがひとつだけ。 そもそも、birdって言う名前をつかうこと自体、おかしくないですか? 「こうもり」を派生したくなった時点で、名前をflying_animalとかに変更するのが筋では? そしたら「ダチョウ」を派生できないことは明らかなはずで。
[この投稿を含むスレッドを表示] [この投稿を削除]
[745] Re:分析と設計
投稿者:774RR
2007/02/20 02:13:25

んと、他人の意見だけ募集して自分の意見を出さないのはアレげなので私の見解。 LSP=同一基底クラスから派生したオブジェクトは、振る舞いが同一であると契約する 契約=派生クラス実装者と基底クラス利用者の間で取り決め ってことなので、そもそも struct bird { virtual void fly()=0; }; って設計した以上 bird 派生クラスは全て「飛べる」必要があり、飛べないものをこいつから派生したらダメ。 1.だから、この bird からダチョウクラスを派生させるのはダメ。 2.もしダチョウクラスを bird から派生させたいのであれば bird の実装を再検討。 ではどのような bird にすればよいか、は要件に応じて再分析が必要。 その再分析の際に「特定の設計原理(銀の弾丸)」ってものはありえない。 ただその分析の結果の実装は LSP に則るべし。 ってことなんですけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[743] Re:分析と設計
投稿者:774RR
2007/02/20 02:13:25

>ダチョウ、ペンギンを例外にするのは良くないので、 >上記の実装なら同一扱いできるので良いと思います。 そこまでは限りなく同意なのですが >もしくは、間違ってfly()させちゃいけないのなら >例外を投げるのもありかなと思います。 これは LSP 違反だと思うのです。 http://www2.ocn.ne.jp/~yamagu/object/LSP-J.pdf の Rectangle と Square の例[本当の問題]と同等な問題を内在させることになりそうです。 さて、こういう場合に「そもそも同一視すべきだったか」を私は問いたいのです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[742] Re:分析と設計
投稿者:タイガー
2007/02/20 02:13:25

面白そうなので勝手に考えてみました。 初期の設計として私なら以下のように考えます。 >Shapeにdraw()を付けたら、その時はうまくいったとして。 > >Q1-1)機能拡張でShapeをグループ化できるようにしたとき、ShapeGroupクラスは > どこに位置づけるべきか? > >Q1-2)機能拡張で「補助線」機能を付けた。補助線は、描画中にだけ使用する機能で、 > 後工程に回らないからデータとしてファイルに保存しない。 > >A1-1(前橋版) >ShapeGroupをShapeのサブクラスにして、draw()をオーバーライドしてその >グループに含まれているShapeのdraw()メソッドを再帰的に呼んでやれば >描画はできますが、それはやっぱりアレなのでShapeのスーパークラスとして >Visibleとかの抽象クラス(またはインタフェース)を作り、ShapeGroupとShapeは >そのサブクラスかなあ。 >たとえば「color」というフィールドは、ShapeGroupには要らないだろうし。 これは、私も(ぱ)さんと同様にします。 つまり、ShapeGroupとShapeを共にVisibleから継承させて、 ShapeGroupにVisibleのリストを持たせます。 そうすればCompositeパターンになり、描画するときは、 トップからつながってるShapeを全て描画できます。 >A1-2(前橋版) >補助線がShapeのコレクションに入らないとすれば、完全に別扱いかなあ。 >もちろんVisibleを導入し、Visibleのコレクションを作って、Shapeは >ShapeコレクションとVisibleコレクションの両方から参照される、という >構造でもいいけど、両方のコレクションをメンテするのも面倒だし。 Visibleのサブクラスとして補助線クラス(AuxLine)を追加します。 AuxLineには、Visibleを集約させて(持たせて)、実際はShapeクラスを 持ちます。必要な機能をShapeから委譲させます。 結局、新たなクラスをShapeのサブクラスにするのは、 結合度が強すぎてガチガチになるので、 ゆるやかな結合で設計しておいた方が良いのかと思います。 これだけの情報だと情報量が少ないですが、 もっとうまい設計があったら教えて欲しいです。 >>Q2.案件C(あるいはA”)では「ダチョウ」「ペンギン」を扱う必要が生じた。 > >具体例が思いつきませんが、「描画されないShape」ですよね。 > >void draw() {} ダチョウ、ペンギンを例外にするのは良くないので、 上記の実装なら同一扱いできるので良いと思います。 もしくは、間違ってfly()させちゃいけないのなら 例外を投げるのもありかなと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[741] Re:分析と設計
投稿者:(ぱ)
2007/02/20 02:13:25

>Q1.案件B(あるいはA’と言い換えても)では「こうもり」を扱う必要が生じた。 >基底クラスを書き換える/書き換えない?派生クラスの実装をどうする? 鳥とかこうもりではあんまり具体的でもないと思うので、私は、例によって ドローツールっぽいものを考えるとします。 Shapeにdraw()を付けたら、その時はうまくいったとして。 Q1-1)機能拡張でShapeをグループ化できるようにしたとき、ShapeGroupクラスは  どこに位置づけるべきか? Q1-2)機能拡張で「補助線」機能を付けた。補助線は、描画中にだけ使用する機能で、  後工程に回らないからデータとしてファイルに保存しない。 A1-1(前橋版) ShapeGroupをShapeのサブクラスにして、draw()をオーバーライドしてその グループに含まれているShapeのdraw()メソッドを再帰的に呼んでやれば 描画はできますが、それはやっぱりアレなのでShapeのスーパークラスとして Visibleとかの抽象クラス(またはインタフェース)を作り、ShapeGroupとShapeは そのサブクラスかなあ。 たとえば「color」というフィールドは、ShapeGroupには要らないだろうし。 Shapeのグループ is a Shape と言って言えないことはないけど、苦しいし。 A1-2(前橋版) 補助線がShapeのコレクションに入らないとすれば、完全に別扱いかなあ。 もちろんVisibleを導入し、Visibleのコレクションを作って、Shapeは ShapeコレクションとVisibleコレクションの両方から参照される、という 構造でもいいけど、両方のコレクションをメンテするのも面倒だし。 >Q2.案件C(あるいはA”)では「ダチョウ」「ペンギン」を扱う必要が生じた。 具体例が思いつきませんが、「描画されないShape」ですよね。 void draw() {} でよさそうな… 以上、べたべたに実装よりの解答でした。
[この投稿を含むスレッドを表示] [この投稿を削除]
[740] 分析と設計
投稿者:774RR
2007/02/20 02:13:25

盛り上がっているのは良いのですが、なんだか飽きて^H^H^Hわからなくなってきたので、 長すぎるスレにつながずに新規発言してみるテスト。 こんな場合、皆様ならどのように対処なさるでしょうか?ご意見拝借。 ある案件Aにおいては、こーいう設計が適切だと分析したので、以下のように書いた。 struct bird { virtual void fly()=0; }; そして現実にうまく行った。 Q1.案件B(あるいはA’と言い換えても)では「こうもり」を扱う必要が生じた。 基底クラスを書き換える/書き換えない?派生クラスの実装をどうする? Q2.案件C(あるいはA”)では「ダチョウ」「ペンギン」を扱う必要が生じた。 基底クラスを書き換える/書き換えない?派生クラスの実装をどうする? 抽象論だけだと理解しきれないのは俺だけ?なんか具体的な例が欲しくなったのです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[739] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>実はオブジェクト指向に限らず、ジェネリックプログラミングとも >通じる真理だと思うんですが… ジェネリックプログラミングに通じるのはわからなくもないですが、だから何です? ジェネリックプログラミングがそうだからといって、オブジェクト指向プログラミングもそうだという理由にはなりません。 >Webで公開されている文書であっても、原文の方で確認をすれば > then S is a subtype of T. >と書かれていますから、後者の意味であることは明らかなんですけどね。 なるほど。 件の本はまだ読んでいませんが、であるにしても、長方形と正方形の例をあのように用いているのであれば、どれほど信用が置けようか、という気はしますね。 >「完全に互換性のある属性と振舞いを示すのであれば、それは一見関係ないよ >うに見えても、実は関係があるのだ」というのが正解でしょう。 >CES さんは、この考え方を、一貫して拒否されているようですが… 属性や振る舞いに互換性があろうがなかろうが、何らかの関係はあります…と言うのも語弊がありますね。 関係は「ある」のではなく「作る」のです。作ろうと思えば、どんな関係だろうと作ることができます。これは、その気になればいくらでも互換性を持たせることができる、とも言えます。互換性は「示す」のではなく「持たせる」のですから。 問題は、その関係をプログラム上に表現することにメリットがあるのかどうかです。 そして、メリットがない関係は「関係ない」としても問題ありません。むしろ、そのような関係を徒に表現することは無駄であり害悪でしょう。 >> 俺は「LSP に照らすまでも無く、継承関係にしてはいけない場合がある」 >> と言う。 > >これも繰り返しになりますが、「照らすまでもなく」のような暗黙の知識は、 >法則としては役に立たないんですよ。だからこそ、明文化された LSP に >意味があるわけです。 俺は法則の話はしていません。 kit さんは「どういう関係を継承関係にすればいいのかという法則」を欲しているようですが、そんなものはありませんから。 LSP は満たすべき継承関係の指針ですが、使うべきところが違うと思うのです。 一応言っておくと、経験を否定しているわけではありません。 特定の案件に直面した時、「過去の経験から、こうすればうまく行くと思う」という提案は(最適ではなかったとしても)有意義です。 そのような場合でも「最適な選択肢は毎回違うのだから、経験などに頼らず、一から分析しなおすべきだ」と発言するのはバカです。 しかし、そのような特定の場面に依存しない、普遍的なガイドラインはない、と言っているのです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[738] Re:オブジェクト指向「初」入門
投稿者:kit
2007/02/20 02:13:25

「オブジェクト指向における is-a の関係は、オブジェクトの振舞い によって定義される」というのが、件の文献が言ってることなわけ ですが、どうも CES さんには受け入れられないみたいですね。 実はオブジェクト指向に限らず、ジェネリックプログラミングとも 通じる真理だと思うんですが… どうも CES さんとの溝は埋められそうにないわけですが、一応、 直接的な疑問には答えておきます。 > 件の文献も言っているではありませんか。 > 「サブタイプならば同じ振る舞いをすべきである」と書かれています。 > 「同じ振る舞いをするならサブタイプである」とは書かれていません。 訳が分かりづらくて、CESさんを誤解させてしまったのかもしれませんね。 Robert C. Martin の「アジャイルソフトウェア開発の奥義」をお持ちだ そうですから、そちらの該当箇所を参照されてみてはどうでしょうか。 144ページから引用します。 ここで望まれるのは、次に述べるような置換可能な性質である。 S型のオブジェクト o1 の各々に、対応するT型のオブジェクト o2が1つ存在し、Tを使って定義されたプログラムPに対して o2の代わりにo1を使ってもPの振る舞いが変わらない場合、 SはTの派生型であると言える。 Webで公開されている和訳では、確かに > 「サブタイプならば同じ振る舞いをすべきである」 と書かれているように読めるかもしれませんが、本当は > 「同じ振る舞いをするならサブタイプである」 と書かれているんです。Web の和訳のこの部分は誤訳に近いですね。 Webで公開されている文書であっても、原文の方で確認をすれば then S is a subtype of T. と書かれていますから、後者の意味であることは明らかなんですけどね。 > あるクラスと互換性のある属性と振る舞いを持つクラスは、そのクラスと何 > らかの関係があるクラスと見るべきです。 ここまでは合意します。 > 逆転させて言えば「関係の無いクラスに、互換性のある属性と振る舞いを持 > たせるべきではありません=継承関係にすべきではありません=LSP が成立 > してはいけません」となるのではないでしょうか。 違いますね。 「完全に互換性のある属性と振舞いを示すのであれば、それは一見関係ないよ うに見えても、実は関係があるのだ」というのが正解でしょう。 CES さんは、この考え方を、一貫して拒否されているようですが… > 小文字の is-a ってどこで使ってますか? ひょっとして原文? > 提示された日本語版には見当たらないのですが… ええと、小文字ではじまるのは「is-a」ではなく、「名詞」です。 また、ここで書いているのは原文の話です。日本語版を読んでいるだけでは、 何のことをさして書いているのか、分からないと思います。 > 俺は「LSP に照らすまでも無く、継承関係にしてはいけない場合がある」 > と言う。 これも繰り返しになりますが、「照らすまでもなく」のような暗黙の知識は、 法則としては役に立たないんですよ。だからこそ、明文化された LSP に 意味があるわけです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[737] Re:プログラミングの入門用言語
投稿者:(ぱ)
2007/02/20 02:13:25

>えーと、以前の言及には気づいていませんでした。 ちょっと検索してみました。 # この掲示板には検索機能はないですが、今のところ # http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&range=800 # とかやると過去の全発言が表示されるのでブラウザ内検索。 # もっと発言が増えてくると破綻しますが… そのうちガードをかけないと… 「一度や二度ではない」は言い過ぎだったようです。2回ですね。 このへんとか。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=372&range=1 >私はゲームプログラミングにはうといのですが、Javaで「継承やオー >バーライドやインタフェースやスレッドを知らなければならない」 >というのは、 > > * やろうとしていることが実は複雑である > * Javaの提供するモデルとやろうとしていることが合ってない いくらなんでもボールがマウスを追いかけるくらいが複雑だとは思えないので、 Javaに関して言えば、「Javaの提供するモデルとやろうとしていることが合ってない」 のだと思います。もちろんこれは用途次第で、ダイアログを使うビジネスアプリケーション ならJavaのモデルでよいわけです。 ただ、Javaの場合、もともとWebページの飾り付け用の言語として世間に投入された はずで、にもかかわらずこのモデルはどうよ? とは思います。これは言語ではなく ライブラリの問題ですけど。 また、Javaの場合、たかがhello, worldでも、classとかpublic static void mainとか System.outとかの謎の言葉が出てきます。これはライブラリでなく言語の問題でしょう。 これを見ておっかなく思う初心者はいるかもしれません。が、実は「決まり文句」と 思っておけば済むことかもしれませんし、クラスがあってもhello, worldを1行で 書ける言語は可能です(Rubyのように)。 たとえばクラスが難しいものだとしても、初心者にクラスが見えないのなら、 初心者向け言語からクラスを外す理由にはなりません。その点で、[731] のyuyaさんの 指摘は的を射ていると思います。 ということで、私もおおむね説得されているわけですが、 a)初心者だからといって入門書を最初から順番にやっていくだけとは限らない。  雑誌に載っていたりネットに転がっているコードを読むこともあるだろう。 b)初心者だってライブラリは使うしマニュアルも読む。 ということは言ってよいと思います。Javaでhello, worldを書くとき、System.outは 決まり文句と思っていればよいかもしれませんが、これを決まり文句と思っている間は APIリファレンスが引けません。 また、C++だと入門書の最初のページでcoutとか使ってるかもしれませんが、 これをちゃんと理解するには演算子のオーバーロードを知らなきゃいけませんし、 ちょっとコレクションを使おうとするとSTLが出てきてtemplateを知らなくては いけなくなったりします。STLでなく(危険を承知で)Cの配列を使おうと決心したと しても、既存の、ゲームを作るのにすごく便利なライブラリが、引数にSTLの vectorを要求してたりして。 そういえば、話としてはずれますが、最初にCを勉強したときには (c = getchar()) != EOF がおっかなく見えたことを思い出しました。 >「削ることによってわかりやすくなる」という意見はよく聞きます >が、実際は「適切なモデル(or 機能)を提供することによってわか >りやすくなる」のであって、削ることだけが能じゃないと思います。 もちろん、なんでもかんでも削ればよいと思っているわけではないです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[736] Re:プログラミングの入門用言語
投稿者:まつもと
2007/02/20 02:13:25

>書き込みありがとうございます。正直、ちょっとびっくりです。 ># ていうかここでMatzにっきにリンクしたのは一度や二度ではないのですが、 ># この話題で書き込みいただけるのはびっくりというか。 えーと、以前の言及には気づいていませんでした。 >> * サンプルで扱おうとしている概念そのものが難しい >> * サンプルの作者が難しく表現してしまった >> >>のいずれかで、それを言語のせいにするのはどうかと思います。 > >たとえば、私が[719]で書いた「マウスを追いかけるボールのプログラム」には、 >初心者がおっかなく思う機能はそんなにないと思います。「サンプルで扱おうと >している概念そのものが難しい」わけではないのではないでしょうか。 >でも、同じことをJavaでやろうと思ったら、継承やオーバーライドやインタフェースや >スレッドを知らなければならないわけです。以下のページは、そういう意図で >書きました。 私はゲームプログラミングにはうといのですが、Javaで「継承やオー バーライドやインタフェースやスレッドを知らなければならない」 というのは、 * やろうとしていることが実は複雑である * Javaの提供するモデルとやろうとしていることが合ってない のいずれかなのではないのですか。だとすると、検討すべきことは 初心者におっかない機能を取り除くことではなく、もう一歩踏み出 して、やろうとしていることを簡潔に記述できる高レベルなものを 提供することではないでしょうか。それが文法なのかライブラリな のかは知りませんが。 >という意見が出ていますが、「とりあえずオブジェクト指向は要らんな。」 >「構造体も要らん。」「変数は全部グローバル。」という意見には賛同しないものの、 >初心者にとっておっかない機能を除きつつ、それなりに実用に使える「落としどころ」 >は、どこかにあるんじゃないかと私は思っているわけです。 「削ることによってわかりやすくなる」という意見はよく聞きます が、実際は「適切なモデル(or 機能)を提供することによってわか りやすくなる」のであって、削ることだけが能じゃないと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[735] Re:「投稿」ボタン
投稿者:(ぱ)
2007/02/20 02:13:25

>プレビュー画面で >「『投稿』ボタンをクリックすると、投稿されます。」 >と言いつつボタンが「送信」になってますね(^^;)  修正しました。ついでに、前から気になっていた、「ちゃんと改行を入れたかどうかチェックしてください」という文言を削除しました。  以前の仕様では、<pre>で囲んでいたので改行を入れないと困ったことになりましたが、今は<tt>で囲んでいるので、改行を入れる必要はなくなったためです。 # 引用しにくい気はしますが、画面幅が不明なとき、改行は入れない方がよいという # 面もあるので、今後はそのへんは投稿者にお任せしますです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[734] Re:プログラミングの入門用言語
投稿者:(ぱ)
2007/02/20 02:13:25

>であって、前橋さんが問題としている >(2)「初心者向きでない機能を使わないと初心者向けのサンプルが書けないこと」 うむむ。確かにそうですね。Javaで、ちょっとしたゲームを作るのが大変なのは 「初心者向きでない機能を使わないと初心者向けのサンプルが書けないこと」の方に 相当します。 私自身、考えがまだまとまっていないのですが、 「初心者向きでない機能があると、それは相当な高確率でプログラムに  顔を出す。たとえその機能を使わずともプログラムが書けたとしても」 というのでなければ、初心者向きでない機能を言語から外す理由にはなりませんね。 問題はこの命題が真かどうかですが。初心者向きでない機能があるが、それを使わずとも 初心者が満足する程度のプログラムが書ける言語を仮定して、 a)初心者向けの本などのサンプルプログラムで、わざわざ初心者向きでない  機能を使っているとしたら、その本の著者がアホ。 b)初心者がベーシックマガジンの投稿プログラムを解読しようとするケースはどうか。  これだと、初心者向きでない機能が使われていることもありそう。 c)ライブラリとかで初心者向きでない機能が使われていて、それを知らないと  重要なライブラリが使えない、とか。 b), c)みたいなケースもあるかなあ、とも思いますが… 現状のJavaScriptプログラマの大半は、たとえばクロージャを知らなくても 幸せにやってるわけで、確かにいらん心配のようにも思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[733] Re:正規表現関連の関数の質問
投稿者:タイガー
2007/02/20 02:13:25

>私のお勧めサイトというと、ここの参考URLですかねえ。 >http://kmaebashi.com/programmer/devlang/array.html ありがとうございます。 1回は既に読んでいたのですが、頭に入っていなかったので 何回も読み直してみます。 >あと、紙ものの資料では、大昔の情報処理学会誌に「ごみ集めの基礎と最近の動向」 >というのがあって、とてもよかったのですが、現在では入手不能だと思います。 >私はというと会社で該当の情報処理学会誌が捨てられる直前に気が付いて、 >コピーしておいたのですが、その後数回の引越しで現在行方不明です…だめだめ。 もったいないですね。でも今回の記事に生かせているのでは ないでしょうか。 >>以下の本を購入しようと思ったのですが、(ぱ)さんは読んだことありますか? >> >>http://www.amazon.co.jp/exec/obidos/ASIN/0471941484/qid=1136566955/sr=1-1/ref=sr_1_10_1/250-0589622-2949018 > >すみません、読んでないです。 有名らしいのですが、読んでなかったのですね。 GCに関してあまり勉強せずにできているなんてすごいですね。 また、投稿します。ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[732] 「投稿」ボタン
投稿者:yuya
2007/02/20 02:13:25

ひさしぶりに投稿してみて初めて気づいたんですが、 プレビュー画面で 「『投稿』ボタンをクリックすると、投稿されます。」 と言いつつボタンが「送信」になってますね(^^;) つまらんこと言ってすみません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[731] Re:プログラミングの入門用言語
投稿者:yuya
2007/02/20 02:13:25

こんにちは。 まつもとさんが「あまり問題にならない」と書いているのは (1)「言語が初心者向きでない機能を持つこと」 であって、前橋さんが問題としている (2)「初心者向きでない機能を使わないと初心者向けのサンプルが書けないこと」 とは別なのではないでしょうか? 私自身は(1)はまつもとさんと同様に「問題にならない」と思いますし、 (2)は前橋さんと同様に「そりゃ問題である」と思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[729] Re:プログラミングの入門用言語
投稿者:(ぱ)
2007/02/20 02:13:25

書き込みありがとうございます。正直、ちょっとびっくりです。 # ていうかここでMatzにっきにリンクしたのは一度や二度ではないのですが、 # この話題で書き込みいただけるのはびっくりというか。 >>これにはいまいち賛同しかねるんですよねえ。サンプルで見かけるプログラムで >>「初心者向きでない機能」が使われていると、おっかなく思う初心者は大勢いそうです。 おっかなく思う初心者がいるから言語からその機能を抜くとすれば、以下の問題が 発生すると思います。 a)おっかなく思うような難しい概念を抜きにして、ゲームとかを作りたいと思う  初心者が達成したい要件を実現できるかどうか。 b)おっかなく思うような難しい概念を抜きにして、上級者の要件を満たせるかどうか。 おっかない機能を抜いても、a), b)の両方を満たしているのであれば、文句なしだと 思います。そりゃ本当の上級者は別の言語を使ったほうが「よりよい」かもしれませんが、 そういう「よりよい」言語との間に十分な「のりしろ」があるなら、初心者も シームレスに移行できるのではないでしょうか。 >>こちらにある、「「初心者(だけ)のための言語」ってのは駄目だと思っている」 >>という意見にも賛成します。 これ↑に矛盾すると思われるかもしれませんけど、要は程度問題で、いずれツールの 移行を余儀なくされるとしても、その時の抵抗が少ないのであれば、許容されるのでは ないでしょうか。HSPやN88BASICはこのへんが… # と言いつつ、HSPやN88BASICで苦労した経験は、その後他の言語のありがたみを # 理解するのに有用かもしれない、とも思ったりもします。この苦労を知らずに # 大人になると、「グローバル変数が便利だったから、あちこちで使った。」に # なりかねないわけで。 > * サンプルで扱おうとしている概念そのものが難しい > * サンプルの作者が難しく表現してしまった > >のいずれかで、それを言語のせいにするのはどうかと思います。 たとえば、私が[719]で書いた「マウスを追いかけるボールのプログラム」には、 初心者がおっかなく思う機能はそんなにないと思います。「サンプルで扱おうと している概念そのものが難しい」わけではないのではないでしょうか。 でも、同じことをJavaでやろうと思ったら、継承やオーバーライドやインタフェースや スレッドを知らなければならないわけです。以下のページは、そういう意図で 書きました。 http://kmaebashi.com/zakki/zakki0027.html#lang イベントリスナを実現するために内部クラスや匿名クラスを使うのは 「サンプルの作者が難しく表現してしまった」のかもしれませんが、それ以外の点に ついては、Javaでは避けようがないでしょう。 >それに初心者がおっかなく思う危険のある機能を取り除いた言語っ >てのは、結局実務に役立たずで学ぶ価値のない言語になりそうです。 まつもとさんも、Cが「実務に役立たずで学ぶ価値のない言語」とは思いませんよね? 現状でCが難しいのは、実行時のチェックがないためとんでもないバグが出ることと、 宣言の構文やポインタと配列の妙な交換性にあると私は思っています。 前者は多少効率を犠牲にすれば回避できる話ですし、後者は単なる言語のバグです。 こういう点を改良したCもどきは作れると私は思っていて、crowbarは、ある意味 その実装のひとつのつもりです(型無しだったり、プロトタイプベースだったり、 クロージャがあったりするのはアレですが)。 こちらにも、 http://www.rubyist.net/~matz/20040925.html#c05 | 文字列型が違和感なく扱えて、便利そうな関数がもっと多くて(?)、引数が常に値渡しであるC言語最強、と思う。 という意見が出ていますが、「とりあえずオブジェクト指向は要らんな。」 「構造体も要らん。」「変数は全部グローバル。」という意見には賛同しないものの、 初心者にとっておっかない機能を除きつつ、それなりに実用に使える「落としどころ」 は、どこかにあるんじゃないかと私は思っているわけです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[728] Re:プログラミングの入門用言語
投稿者:まつもと
2007/02/20 02:13:25

>ただ、 >| 初心者と言えども言語の全ての機能を一度にマスターする必要はない。 >| よって言語が初心者向きでない機能を持つことは、あまり問題にならない。 > >これにはいまいち賛同しかねるんですよねえ。サンプルで見かけるプログラムで >「初心者向きでない機能」が使われていると、おっかなく思う初心者は大勢いそうです。 「おっかなく思う」かもしれませんが、その原因は * サンプルで扱おうとしている概念そのものが難しい * サンプルの作者が難しく表現してしまった のいずれかで、それを言語のせいにするのはどうかと思います。 それに初心者がおっかなく思う危険のある機能を取り除いた言語っ てのは、結局実務に役立たずで学ぶ価値のない言語になりそうです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[727] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

この人たちは、どんなソフトウェアかによらず適用できる、万能の分析手法でも求めているんだろうか… そんなものがありゃ誰も苦労しねぇっつうの。
[この投稿を含むスレッドを表示] [この投稿を削除]
[726] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>CESさんいわく > >>「is-a である関係が、LSP を満たすように作れ」と言っているのです。 > >それじゃあ「CESさん言うところのis-a」がLSPを満たすのは当たり前ですわな。 >そう定義したんだから。 「LSP を満たす関係が is-a である」とは言っていませんよ(そう言っているのは kit さんです)。 結果的にはそうなりますが、それは is-a の定義ではありません。 じゃあ is-a の定義は何なんだって話になりますが、言い換える言葉が見つかりませんね。is-a は is-a です。「A is-a B」は「AはBの一種」です。これがもっともシンプルかつ的確ではないですか。 以前に、ソフトウェアは「分析→設計→実装」の3段階で作られると言う話をしました。 俺の言う「is-a」の関係を決めるのは分析段階、LSP を満たすように作るのは設計段階の話です。 それで設計段階になって、LSP がどうしても満たせなくなったらどうするか? LSP を捻じ曲げて is-a を固持しろなんていってません。分析からやり直すのです。 ちょっと古い投稿を引用すが… [658] > 設計を見直す=分析のしなおし、だよん。って。 その通りではないですか。 あるプロジェクトに直面した時、「AはBの一種である」とも「AはBの一種ではない」とも、どちらの考え方もできます。 どちらが適切なのかを選ぶのが「分析」というプロセスですよ。 >我々は、設計段階で、どういう継承関係にすればうまくいくかを知りたい >ため、設計原則を求めているわけです。 そこで機械的に従えばいいガイドラインを求めるのは、分析プロセスの放棄ですよ。 >>1:オブジェクトが is-a であると仮定した。 >>2:LSP に照らし合わせたらうまく行かなかった。 >>  (照らし合わせるまでも無く判断できる場合もある) >>3:実はオブジェクトは is-a じゃなかったんだ。だから継承関係にはしない。 > >こちらも同様です。is-aの定義が「うまくいくかどうか」で決定されるんなら、 >「うまくいくようにやりなさい」と言ってるだけのことで、結局何も言って >いないのです。 そうですよ。 「どうすればうまく行くのか」は、その場合に応じて変わるのですから、それ以外に言いようが無いではありませんか。 こんな記事見つけました(Wikipedia - 「継承」) http://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF > 一般的に、AがBを継承する場合、A is a B. (AはBの一種である)という > 意味的な関係(is-a関係)が成り立つ。従って、同じふるまいを持つから > と言って、意味的に無関係なクラス間に継承関係を持たせるのは適切でない > 場合が多い。 だそうですよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[725] Re:オブジェクト指向「初」入門
投稿者:(ぱ)
2007/02/20 02:13:25

あんまりkitさんに押し付けておくのも申し訳ないのでちょっとだけ書きますが。 >>ところが、CES さんは、「継承してうまく動くような関係が is-a である。 >>したがって、継承してうまく動くような関係に対して、継承を当てはめれ >>ば良い」と言ってるに過ぎないわけです。これは見て分かるようにトート >>ロジーに過ぎず、設計の指針としては、全く役に立たないわけです。 このkitさんの言葉がすべてだと思いますがね。 >違います。 >「どういう関係が is-a であるか」については言及していません。 だから、それが問題なんだってば。既に指摘されているじゃないですか。 [715] >なぜなら、CES さんは、is-a という関係が具体的にどうあるべきかを一切述べ >ていないからです。 CESさんいわく >「is-a である関係が、LSP を満たすように作れ」と言っているのです。 それじゃあ「CESさん言うところのis-a」がLSPを満たすのは当たり前ですわな。 そう定義したんだから。 >1:オブジェクトが is-a であると仮定した。 >2:LSP に照らし合わせたらうまく行かなかった。 >  (照らし合わせるまでも無く判断できる場合もある) >3:実はオブジェクトは is-a じゃなかったんだ。だから継承関係にはしない。 こちらも同様です。is-aの定義が「うまくいくかどうか」で決定されるんなら、 「うまくいくようにやりなさい」と言ってるだけのことで、結局何も言って いないのです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[724] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

あといくつか、最初の方の書き込みに対するレス。 俺が「オブジェクトの is-a は LSP よりも優先されるべきだ」と言ったのは、「まずオブジェクトの is-a で判断し、次に LSP で判断すべきだ」という意味です。 その結果、最初に「is-a」とした判断が誤っていたというケースがあるのは既に言っています。 そのような場合でも、LSP を捻じ曲げて、断固、最初の「is-a」に固執すべきだと言った覚えはありません。 そして、まず「(常識的なオブジェクトの)is-a で判断する」のは、kit さんも同じであると [715] で書かれています。しかし、そう書かれたのはここが初めてです。 俺はてっきり「オブジェクトの is-a は問題にしなくていい。LSP だけで継承関係を判断すればいい」のだと思っていたのですが。 [713] では > なぜ、オブジェクト自身の is-a 関係が継承関係の設計に使えない > 場合があるのか、そのことを説明しているのが LSP です (ただし、 > 正方形や円のケースでは、LSP 以外にも、メモリ効率という別の理 > 由もあります)。継承関係の設計において、オブジェクト自身の > is-a 関係は使えない場合がある弱い判断基準なわけですが、LSP > は常に使える絶対的な判断基準なわけです。実はLSP(オブジェクト > の振舞いに関する is-a) の方が、オブジェクト自身のis-aよりも > むしろ本質的な原則なわけです。 と書かれています。 > オブジェクト自身の is-a 関係が継承関係の設計に使えない場合がある のは事実です。 しかし、そういう「場合がある」のであって、「常に使えない」とは書かれていません。 事実、[715] では > たとえば、「常識的に考えた is-a 関係に対して、継承を当てはめれば良 > い」というのは、正方形と長方形の例のようにうまくいかない例外もあり > ますが、かなり使える原則です。 と書かれています。「is-a の関係は使えないわけではない」のですね。 にも関わらず、[713] では「is-a は役に立たない。LSP こそ基準にすべきだ」と書かれているように見受けられます。 そう読んでしまうのは、俺の読解力不足ですか? [715] を境に、そちらの主張が切り替わっているような気がするのですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[723] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

要点抽出。 >議論が空転している気がするんです。整理しましょう。 >まず(常識的かどうかは置いておくとして)「オブジェクトの is-a」で大まかな関係を作るというのは、どちらも同じことを言ってますね。 >kit さんは、その上で「LSP に照らして破綻したら、継承関係にはしない」と言う。 >俺は「LSP に照らすまでも無く、継承関係にしてはいけない場合がある」と言う。 >結局、どの段階で、最初の「is-a」が間違えていたかを判断するのかが違うだけで、大差ないでしょう。 >問題は「LSP に照らさないと、間違いかどうか判断できないケースはあるのか」だと思うんですよ。 >そのへんどうです? 1:オブジェクトが is-a であると仮定した。 2:LSP に照らし合わせたらうまくいった。 3:継承関係を結んだ。 これに異論を差し挟む余地は無いでしょう。 問題は、そうでないケースですね。 kit さんの場合 1:オブジェクトが is-a であると仮定した。 2:LSP に照らし合わせたらうまく行かなかった。 3:オブジェクトは is-a なんだけど継承関係にはしない。 俺の場合 1:オブジェクトが is-a であると仮定した。 2:LSP に照らし合わせたらうまく行かなかった。   (照らし合わせるまでも無く判断できる場合もある) 3:実はオブジェクトは is-a じゃなかったんだ。だから継承関係にはしない。 結局、違うのは、過程3の前半だけなんですよね。 だから、[712] ではこう書いているんです。 > is-a と LSP をどうしても両立させられない例を一つでも出していただけませんか。 俺の方法ではうまく行かないケース、つまり 「どこからどう見ても疑念を挟む余地無く is-a なんだけど、LSP に照らし合わせたらうまく行かないから、LSP を優先するケース」 があるのか、ということなんです。俺が度々言う「is-a と LSP が矛盾するケース」ってのはこういうことなんです。 「常識的な is-a と LSP が矛盾するケース」ではないですよ。「どこからどう見ても」ってのは、「あらゆる非常識な関係も考慮に入れて」ってことです。 こういう場合があると言えますか? 俺は「あらゆる角度から見る」ことが不可能であるため、そのようなケースは存在しないと思うのですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[722] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

>「is-a の意味は常識的なものとは限らない。場合によって、適切なもの >を選べ」というのは、実のところ、まったく意味のない言明です。なぜな >ら、CES さんは、is-a という関係が具体的にどうあるべきかを一切述べ >ていないからです。 どう言えばいいですかねぇ。 「クラスはオブジェクトの集合である」と考えた時、「ある集合Aと、その部分集合Bがあったら、B is-a Aである」でいいですか? もっとも、「どのような基準に従ってオブジェクトを集合に分類するか」には、結局、唯一解がないのは同じことなんですが。 >我々は、設計段階で、どういう継承関係にすればうまくいくかを知りたい >ため、設計原則を求めているわけです。 そんな話は今初めて聞きましたがねぇ… >たとえば、「常識的に考えた is-a 関係に対して、継承を当てはめれば良 >い」というのは、正方形と長方形の例のようにうまくいかない例外もあり >ますが、かなり使える原則です。 それでいいと思いますよ。 我々の社会常識が「大多数にとって都合がいい見方」であるように「多くの場合に都合がいいケース」はあってもおかしくありません。 ただし、それがたまたま成り立たないからといって、それだけを槍玉に挙げないでいただきたい。 ちなみに、件の文献の、長方形と正方形の関係の誤りは、LSP を持ち出すまでも無く「間違いだ」と判断できるものです(まぁ、LSP を考えてみて判断しても構わないのですが。別にそれでも is-a と LSP の矛盾は指摘できませんから)。 オブジェクトの is-a よりも LSP を優先すべきだという根拠にはなりません。 >また、「LSPに従うオブジェクト同士に対して、継承を当てはめれば良い」 >というのは、常に利用可能な原則です。 >ところが、CES さんは、「継承してうまく動くような関係が is-a である。 >したがって、継承してうまく動くような関係に対して、継承を当てはめれ >ば良い」と言ってるに過ぎないわけです。これは見て分かるようにトート >ロジーに過ぎず、設計の指針としては、全く役に立たないわけです。 違います。 「どういう関係が is-a であるか」については言及していません。 「is-a である関係が、LSP を満たすように作れ」と言っているのです。 件の文献も言っているではありませんか。 > あるところで、何か、置き換えが必要なところがあるとする。 > 型Sのオブジェクトo1 と、型Tのオブジェクトo2があって、 > プログラムが既に型Tのオブジェクトを使うように構築されているとする。 > o1がo2で置き換えられても、SがTのサブタイプであるならば、 > Pは同じ振る舞いをするべきである。 「サブタイプならば同じ振る舞いをすべきである」と書かれています。 「同じ振る舞いをするならサブタイプである」とは書かれていません。 結局、この文献は「どんなものを継承関係にすべきか」という指針には、一言も言及していないのです(「どんなものを継承関係にしてはいけないか」は、LSP を用いて言及しています。しかし、それは LSP を用いなくても指摘可能であることは度々述べています)。 >> 全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。 >> これは、「LSP が成り立つならば is-a も成り立つ」と言い換えることもできます。 > >一つ目の文章は正しいと思います。 >しかし、一つ目の文章から二つ目の文章を導くことはできません。 突っ込まれるかなーと思っていました。 ちょっと拡大しましょう。 全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。 そして、あるクラスと互換性のある属性と振る舞いを持つクラスは、そのクラスと何らかの関係があるクラスと見るべきです。 逆転させて言えば「関係の無いクラスに、互換性のある属性と振る舞いを持たせるべきではありません=継承関係にすべきではありません=LSP が成立してはいけません」となるのではないでしょうか。 >なお、Martin 氏の文章を読み返してみて、私がこれまで説明で使って >用語法が、Martin 氏の用語法と異なっているのに気づきました。 >私がこれまで >1. オブジェクトの振舞いに関する is-a >2. オブジェクト自身に関する is-a >という二つの言葉で区別してきたことを、Martin 氏は >1. 振舞いの is-a == オブジェクト(CamelCase にした名詞)の is-a >2. 物(子文字で始まる名詞)の is-a >と呼んでいますね。 >まあ、独立に読んでいれば意味は通じると思いますが、併せて読むと >混乱するのであまり良くありませんね。どうも申し訳ない。 小文字の is-a ってどこで使ってますか? ひょっとして原文? 提示された日本語版には見当たらないのですが… >設計手順としては、まず常識的な is-a を使って継承関係を考えてみた >上で、それを LSP で検証すればいいんですよ。検証に通らない場合には、 >たとえ常識的なis-a 関係であっても、継承関係にはしません。検証に通 >れば、もちろん継承関係にします。 >簡単でしょう? >本来無関係のオブジェクト同士うんぬんなどと悩む必要はありません。 議論が空転している気がするんです。整理しましょう。 まず(常識的かどうかは置いておくとして)「オブジェクトの is-a」で大まかな関係を作るというのは、どちらも同じことを言ってますね。 kit さんは、その上で「LSP に照らして破綻したら、継承関係にはしない」と言う。 俺は「LSP に照らすまでも無く、継承関係にしてはいけない場合がある」と言う。 結局、どの段階で、最初の「is-a」が間違えていたかを判断するのかが違うだけで、大差ないでしょう。 問題は「LSP に照らさないと、間違いかどうか判断できないケースはあるのか」だと思うんですよ。 そのへんどうです? >なお、もし本来無関係だと思っていたオブジェクト同士にLSPが成り立つ >のであれば、実はそのオブジェクト同士は、たぶん無関係じゃないんですよ。 本当に無関係でないのなら構いませんが、「たぶん」というのはいただけません。 実のところ、「本当に無関係か」を判断することはできません。どうにかして関係を見出すことはできます。 しかし、その関係は、設計者の意図した関係で無い可能性が大きいでしょう。 そのような関係に、LSP を成り立たせることは、メリットがあるとは思えません。 >しかし、通常のソフトウェア開発で、そういう発見を必要とすることは >あまりありませんから、無関係だと思うオブジェクト同士について、 >いちいちLSPを検証してみる必要はありません。 LSP は「たまたま成り立っちゃう」ものではなくて「意図して成り立たせる」ものであると考えます。 であるならば、先のようなデメリットを考えた時に「意図して崩す」ことも、当然ありえる話です。 それをせず、「たまたま成り立っちゃう」のを放置しておくのは、バグの温床になりませんか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[721] Re:プログラミングの入門用言語
投稿者:(ぱ)
2007/02/20 02:13:25

>processingのmouseXの代わりに、get_mouse_x()という関数を用意しました。 get_mouse_x()も、ウインドウ内の座標を返すのですから、ウインドウごとにしないと まずいですね。このへん考えるべきことはいろいろありそうですが、まあ方向性として。 ついでに補足しますけど、私は、HSPに関しては「もう21世紀なのにこの言語はないだろう」 というまつもとゆきひろさんの意見に賛成します。 http://www.rubyist.net/~matz/20040827.html#p01 こちらにある、「「初心者(だけ)のための言語」ってのは駄目だと思っている」 という意見にも賛成します。 http://www.rubyist.net/~matz/20040925.html#p02 ただ、 | 初心者と言えども言語の全ての機能を一度にマスターする必要はない。 | よって言語が初心者向きでない機能を持つことは、あまり問題にならない。 これにはいまいち賛同しかねるんですよねえ。サンプルで見かけるプログラムで 「初心者向きでない機能」が使われていると、おっかなく思う初心者は大勢いそうです。 crowbarはどうでしょうか。クロージャは、[717]を見るとわかるように、言語の作者の 私でさえ使いこなせていない。とほほほほ。 しかし、それはそれとして、オブジェクトの概念自体は必要だと思うし、初心者に わからないものでもないと思います。 w = open_window(800, 500); と書いてウインドウが開くのなら、そしてopen_window()を実行するたびに 何個でもウインドウが開けるのなら、そのウインドウに丸を描くのに w.fill_circle(x, y, 10); と書かなければならないのは、いくら相手が初心者でも、自明じゃないのかなあ。 別にfill_circle(w, x, y, 10); でもいいけど。 んで、シューティングゲームを作るのに敵をたくさん出したければ、自分でクラスっぽい ものを作らざるを得ないし、そのmove()メソッドをオーバーライドすることで、 ポリモルフィズムも自然に利用できるんじゃないかと思うんですけど、どうでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[720] Re:プログラミングの入門用言語
投稿者:(ぱ)
2007/02/20 02:13:25

> if (get_mouse_x() < x) { > x++; あ、条件式逆だった…
[この投稿を含むスレッドを表示] [この投稿を削除]
[719] Re:プログラミングの入門用言語
投稿者:(ぱ)
2007/02/20 02:13:25

>てなことを書かれておられましたが、Processing(http://processing.org/)はどう >でしょうか? 情報ありがとうございます。ちょっと見てみました。 ExamplesのStructureを一通り見ただけですが、 ・やっぱりイベントドリブンなのか。(mouseXという謎の変数が出てきてますが) ・ウインドウをふたつ開くことはできるのか? あたりが感想(と疑問)です。イベントドリブンは、処理が分断されるので、 ゲームとかを作りたい人にはわかりにくいのではないか、と私は思っています。 >これは、言語はJavaそのものですが、IDEによって、クラス定義などの >初心者にとって面倒そうな部分をうまく隠蔽してあって、単なる手続き型言語のように >使えます。これなら初心者にとっても比較的とっつきやすいんじゃないかと思います。 うーん。とっつきやすいかとは思いますが、結構用途が限定された言語にも見えます。 draw()は言語仕様に組み込まれているんでしょうか? たとえば現在私が作っているcrowbarをベースに、ライブラリ関数を追加して、 以下のようなプログラムは作れるようになるのではないでしょうか。 processingのmouseXの代わりに、get_mouse_x()という関数を用意しました。 # マウスを追いかけるボールのプログラム。 w = open_window(800, 500); # 引数はウインドウのサイズ x = 0; y = 0; prev_x = x; prev_y = y; for (;;) { # 直前のボールの消去 w.set_color(BLACK); w.fill_circle(prev_x, prev_y, 10); # 中心のx, y, 半径 if (get_mouse_x() < x) { x++; } elsif (get_mouse_x() > x) { x--; } elsif (get_mouse_y() < y) { y++; } elsif (get_mouse_y() > y) { y--; } w.set_color(WHITE); w.fill_circle(x, y, 10); prev_x = x; prev_y = y; wait(100); # 100msec待ちつつイベントを拾う。最後のイベントで上書き。 } 私が件の雑記で書きたかったのは、「ベーシックマガジン向けプログラミング言語」が あったらいいなあ、ということなんですけど、これぐらい書けたら、汎用性を保ちつつ、 それなりに達成してないでしょうかね? もちろん、fill_circle()だけでなく、 イメージを指定された場所に表示する関数とかも必要ですけれど。 wait()あたりの一等地の名前を使うことについては、名前空間で対処するとして。 でも、processingは、Javaアプレットとして実行できるのはいいと思います。 ゲーム作ったらやっぱり友達に自慢したいと思うので。
[この投稿を含むスレッドを表示] [この投稿を削除]