K.Maebashi's BBS

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

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

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

[757] Re:感謝状
投稿者:本多
2007/02/20 02:13:25

>>前略 前橋様 > いつものmanybookの本多さんにこういうことを書かれたとすればさすがにこそばゆいので。 いや、いつもの本多ですが...(^^;) そっか、新しい掲示板はメールアドレスないんですよね。 感謝状なので、わざわざ 丁寧な書き方してみましたが、 こそばゆかったっすか...(^^;) じゃあ次からは丁寧に書かないようにしますわ(^O^)/ >>で一念発起、C言語で書けるようにコンパイラ(もどき)を作ることにしました。 > 正直、機械語を生成するCコンパイラだと、せいぜい構文解析までしか役に立たな >かったのでは、と思いますが、多少なりともお役に立てたのでしたらよかったです。 なにせ、コンパイラを作ろうなどと考えたこともなかったので 構文解析やらなにやらと、全く知らなかったので勉強になりました。 何よりソースコード付で、そのコードを丁寧に説明してあるのが わかりやすくて良かったです。 crowbar中のeval_...とか、execute_...って関数をwrite()文の羅列に置き換えたので、 たぶんcrowbarを簡単にしただけです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[756] Re:感謝状
投稿者:(ぱ)
2007/02/20 02:13:25

>前略 前橋様  はじめまして…でいいですよね?  いつものmanybookの本多さんにこういうことを書かれたとすればさすがにこそばゆいので。 >有益なページの提供に心から感謝します。  や、ありがとうございます。 >で一念発起、C言語で書けるようにコンパイラ(もどき)を作ることにしました。  正直、機械語を生成するCコンパイラだと、せいぜい構文解析までしか役に立たな かったのでは、と思いますが、多少なりともお役に立てたのでしたらよかったです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[755] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25

[750] への追補。 > 設計手順としては、まず常識的な is-a を使って継承関係を考えてみた > 上で、それを LSP で検証すればいいんですよ。検証に通らない場合には、 > たとえ常識的なis-a 関係であっても、継承関係にはしません。検証に通 > れば、もちろん継承関係にします。 「常識的な判断」が悪いとは思いません。 ところで、「常識」と「真理」は違います。 日本人の常識とアメリカ人の常識が異なるのと同じように、販売支援ソフトと画像処理ソフトの設計常識が同じはずがありません。要するに、常識ってのはいっぱいあります。 その中から、今回作りたいソフトに適する常識を選ぶ必要があります。 経験に基づいて「常識的な設計手法は、適した設計である可能性が高い」と言うのであれば、俺が言う「いくつもの方法の中から、適したものを選べ」というのと、全く変わりません。 ですから、それを否定する kit さんは、「常識的な設計」すらすることができません。 > これも繰り返しになりますが、「照らすまでもなく」のような暗黙の知識は、 > 法則としては役に立たないんですよ。 では「常識」は暗黙の知識ではなく、明文化されているのですか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[754] 感謝状
投稿者:本多
2007/02/20 02:13:25

前略 前橋様 有益なページの提供に心から感謝します。 最近、自社製の小さなハードウエアに搭載するためのアセンブラプログラムを作る仕事をすることになったんです。 規模がそれほど大きくない(200~300ステップ)のですが、アセンブラはやっぱり大変です。 で一念発起、C言語で書けるようにコンパイラ(もどき)を作ることにしました。 連載「プログラミング言語を作る」の前橋さんの説明とcrowbarソースコードを繰り返し読むことで なんとか2日ででっち上げることに成功しました。 さすがにcrowbarとは欲しい機能とは大分違うのでソースコードをそのまま利用することはしてません(できません)が、このページのおかげで大分楽に作ることが出来ました。 しょせん、ハードウエアの制限でポインタとか文字列とか浮動小数点とか多くの機能が実装しない超簡単コンパイラですし、当面私しか使わないし、出来たコードをデバッグしなくちゃいけないのは変わらないのですが...(^^;) 勉強になりました。どうも ありがとうございます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[753] Re:分析と設計
投稿者:CES
2007/02/20 02:13:25

>>ただ、この手法を更に推し進めるとインターフェイスの多重継承の山になりかねないので要注意でしょう。 >>struct fooable { virtual void do_foo()=0; }; >>struct barable { virtual void do_bar()=0; }; >>struct bazable { virtual void do_baz()=0; }; >>struct hoge : fooable, barable {...}; >>struct piyo : barable, bazable {...}; > >推し進めるというか、どこかで一歩飛んでいる気がします。 >FlyingAnimal は(あるいは、飛行機を統一的に扱おうとしてさらに上位に定義した FlyingObject でさえ)、IFlyable とは一線を画したものであるような気がします。 >なぜそう思うのかは、いまのところ「直感」としか言いようがないのですが。 失礼。 今回は既に bird からしてインターフェイスでしたね。 Java や C# が言うところの「インターフェイス」の意味づけが、自分の中でよくできていない感じです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[752] Re:分析と設計
投稿者:CES
2007/02/20 02:13:25

>ただ、この手法を更に推し進めるとインターフェイスの多重継承の山になりかねないので要注意でしょう。 >struct fooable { virtual void do_foo()=0; }; >struct barable { virtual void do_bar()=0; }; >struct bazable { virtual void do_baz()=0; }; >struct hoge : fooable, barable {...}; >struct piyo : barable, bazable {...}; 推し進めるというか、どこかで一歩飛んでいる気がします。 FlyingAnimal は(あるいは、飛行機を統一的に扱おうとしてさらに上位に定義した FlyingObject でさえ)、IFlyable とは一線を画したものであるような気がします。 なぜそう思うのかは、いまのところ「直感」としか言いようがないのですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[751] Re:分析と設計
投稿者:774RR
2007/02/20 02:13:25

>「こうもり」を派生したくなった時点で、名前をflying_animalとかに変更するのが筋では? 御意。それは大いにありだと思う今日子の頃です。 今回のこの案件A’A”では、それでうまく行きそうです。みな幸せ。 ただ、この手法を更に推し進めるとインターフェイスの多重継承の山になりかねないので要注意でしょう。 struct fooable { virtual void do_foo()=0; }; struct barable { virtual void do_bar()=0; }; struct bazable { virtual void do_baz()=0; }; struct hoge : fooable, barable {...}; struct piyo : barable, bazable {...}; とてもまともに分析したとは思えない醜い設計です。 抽象度は増したのかもしれませんが、実用度が薄すぎます。まともに使いこなせるとはとてもとても。 # 自己反省をかねて age
[この投稿を含むスレッドを表示] [この投稿を削除]
[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関係)が成り立つ。従って、同じふるまいを持つから > と言って、意味的に無関係なクラス間に継承関係を持たせるのは適切でない > 場合が多い。 だそうですよ。
[この投稿を含むスレッドを表示] [この投稿を削除]