K.Maebashi's BBS

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

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

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

[1270] >(ぱ)こと管理人さん
投稿者:SE
2009/05/19 16:21:52

>まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は >ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて >いただきたいです。 「マルチプルインスタンスがオブジェクト指向」と言う論理です。 マルチプルインスタンスと言うのが何を指すのがよく分かりませんが、 状態(内部の変数の値)の違う複数の処理群(クラス)と解釈しました。 >そこでわざわざ継承してクラスを作ったって、以下のような問題が起きるだけです。 >・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのかわからなくて危険。 引数の型を見れば分かると思います。 >・別の誰かがLowerStackを作ったら、いつかマージするの? もし別機能として作るなら、Stackを継承してLowerStackを作ります。 例えば大文字にした後に先頭に0を付加するような、UpperStackの処理結果に追加する物なら、 UpperStackを継承して作ります。 すでにLowerStackが出来てしまっているならマージしません。 >「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >ということにしたいのでしょうか? そうです。 >この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 >「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる >既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 既存コードはソースに手を入れないので、影響はないと思いますが。 新たに作るコードはどちらを使うか意識する必要はありますが。 >上のほうで『実のところ「要素を大文字に変換して返すスタック」がどんな時に >役に立つのか想像できません』と書きましたが、結城浩さんが「例は嘘をつかない」 >と書いておられるように、こういうところで現実のプログラムに即した適切な例が >出てこないなら、おそらくそれは考え方のほうが間違っています。 もう少し分かりやすい例をあげます。 --------------------------------------------------------------------- Map<String, String> mp = new HashMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } --------------------------------------------------------------------- 入力した順番に表示したい場合 --------------------------------------------------------------------- Map<String, String> mp = new LinkedHashMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } --------------------------------------------------------------------- ソート表示したい場合 --------------------------------------------------------------------- Map<String, String> mp = new TreeMap<String, String>(); mp.put("aa", "11"); mp.put("cc", "33"); mp.put("bb", "22"); for(String key : mp.keySet()){   System.out.println(key); } ---------------------------------------------------------------------
[この投稿を含むスレッドを表示] [この投稿を削除]
[1271] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/20 03:49:06

# どうもサーバの調子が悪いようで…… まずSEさんにお願いですが、投稿に返信を付ける際には各投稿の右上にある 「返信」リンクを使ってください。そうすることでスレッドがつながりますので [この投稿を含むスレッドを表示]をクリックすると関連する投稿をまとめて 読むことができます。 この掲示板の上のほうにある「スレッド順インデックス」をクリックすると、 他の投稿はちゃんとスレッドがつながっているのに、SEさんの投稿だけ 切り離されていることがわかるでしょう。 http://kmaebashi.com/bbs/thread.php?boardid=kmaebashibbs >>まあ、オセロの例で注記したように、マルチプロセスにはオブジェクト指向と似た面は >>ありますけど。「その論理で行くと」の「その論理」がどういう論理か、教えて >>いただきたいです。 >「マルチプルインスタンスがオブジェクト指向」と言う論理です。 >マルチプルインスタンスと言うのが何を指すのがよく分かりませんが、 >状態(内部の変数の値)の違う複数の処理群(クラス)と解釈しました。 「状態(内部の変数の値)の違う複数の"オブジェクト"」ですよね? まあ、クラスベースのオブジェクト指向ではオブジェクトの生成の雛形として クラスを使うわけで、「疑りぶかい~」ではクラスベースのオブジェクト指向の 話しかしていないわけですけれども。 実のところオブジェクト指向という用語は定義などないも同然なのですが、 「状態(内部の変数の値)の違う複数の"オブジェクト"を持てること」が たいていのオブジェクト指向の定義の必要条件である、ぐらいのことはたぶん 言ってもよいでしょう。 で、そうするとなぜ「マルチプロセスやマルチスレッドはオブジェクト指向になる」 のですか? 「DOSを乗っけたPCを2台もってこれば同時に複数のプログラムを動かせるので、 DOSはマルチプロセスだ!」という主張は誰もしないと思いますけど。 >>・Stackが引数かなにかで渡されたとき、本家StackなのかUpperStackなのかわからなくて危険。 >引数の型を見れば分かると思います。 void hoge(Stack s) { …… } というメソッドがあったとき、sがStackなのかUpperStackなのかは 「わからない」と思いますが? >>・別の誰かがLowerStackを作ったら、いつかマージするの? >もし別機能として作るなら、Stackを継承してLowerStackを作ります。 >例えば大文字にした後に先頭に0を付加するような、UpperStackの処理結果に追加する物なら、 >UpperStackを継承して作ります。 >すでにLowerStackが出来てしまっているならマージしません。 で、同一インスタンスのスタックに放り込んだデータについて、ある場所では 大文字で取り出したいし、ある場所では小文字で取り出したい、という場合、 どのクラスを使えばよいのですか? >>「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >>ということにしたいのでしょうか? >そうです。 だとすれば比較対象にget(boolean up)を持ってきているのはおかしいですね。 get(boolean up)を使う人は、大文字が欲しいとき、意識して引数にtrueを 渡さなければならないからです。 774RRさんへの返信に >ダウンキャストでなく、newするときに新しいクラスを使うと考えてください。 とありますが、(かなり離れた場所でnewされたかもしれない)Stackが UpperStackなのかStackなのかを意識しなければ、UpperStackのget()を 便利に使うことはできません。SEさんの主張は矛盾しています。 >>この改修により、プログラムにUpperStackという「異物」が実行時に紛れ込むわけで、 >>「Stackにputしたんだから、当然同じものがgetできるだろう」と思い込んでいる >>既存コード(Stackそのものを含む)にはおもいっきり影響を与えます。 >既存コードはソースに手を入れないので、影響はないと思いますが。 既存コードに引数でUpperStackを渡したら、入れたものを勝手に大文字に 変換するおかしなStackが紛れ込むことになります。ここではそういうことを 書いています。 >もう少し分かりやすい例をあげます。 Javaのコレクションクラスライブラリは、StackがVectorを継承していたりして いろいろトホホなので、「良い例」として出せるものではないと思います。 現実的に許容範囲内の例ではあるかもしれませんけど。 で、LinkedHashMapやTreeMapですが、これらがHashMapを継承してしまったために、 ・同じコレクションに対し、ある時は入力順に表示したいし、ある時は ソートして表示したい、という場合どうすればよいのか? (要件としてはすごくありそうだと思いますけれども) ・サブクラスにアクセスさせるために、HashMapのフィールドであるtableが  パッケージアクセスになってしまっているがこれはカプセル化の破壊では  ないのか。 (protectedにしなかったのはSunのエンジニアの良識だと思います) ・ていうかLikedHashMapではaddEntryとかcreateEntryとかパッケージアクセスの メソッドをばんばんオーバーライドしているけれど大丈夫か(スーパークラスの 実装に強く依存している)。 といった問題があるわけです。 それでもまあなんとか「現実的に許容範囲」なのは、オーバーライドした メソッドが、スーパークラス側のメソッドに対し「最低限同等の責務を果たす」と いうオーバーライドにおける大原則を守っているからでしょう。 その点においてもSEさんのUpperStackはだめです。同じget()でありながら、 勝手に大文字に変換してしまうためです。 で、 >Map<String, String> mp = new LinkedHashMap<String, String>(); ここでMapに代入しているのはなぜですか? 入力順に出てくることを期待するのなら、LinkedHashMapのまま持ち歩くほうが 安全です。あるMapがLinkedHashMapのつもりだったのに実はそうでなかった、 というケースは、プログラムが大きくなって、newする場所と使う場所が離れれば 離れるほどいくらでも発生することです。そうなってしまえば、入力順に 取り出せないのですから致命的な上、コンパイルエラーどころか実行時のエラーも出ず、 黙って間違った順番でデータを吐き続けることになります。 これを避けるには、ダウンキャストするか、instanceofでクラスを確認する 必要があるでしょう。危険ですけれども。774RRさんがおっしゃっているのは そういうことです。 Mapに代入するメリットと言えば、たとえばMapの中身をダンプする void dumpMap(Map m);というメソッドに対し、LinkedHashMapを渡せば 入力順に表示されるしTreeMapを渡せばソートして表示される、という動きを 期待したいときでしょう。でもこれは、dumpMap()という既存メソッドに 新たに開発したオブジェクトを混入させることに他ならず、それでうまく 動くかどうかは保証の限りではありません。『「異物」が実行時に紛れ込む』と 書いたのはそういうことです。 # これをうまく動かすためには、やはり先ほどの「オーバーライドにおける大原則」 # を守る必要があるわけです。 で、 >ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >でしょうか。 これについては答えていただけないのでしょうか。ぜひ書名を教えて欲しいのですけれども。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1272] Re:疑い深い・・・
投稿者:774RR
2009/05/20 11:17:08

# 題名にハンドル入れるのやめてほしい > SE 氏 変えちゃいました # [1269] に返信してもよかったんだけどこっちにつなぐことにする [1269] > これを次のように変更します。1行で済みます。 ものすごく近視眼的コメントがついていて思わず苦笑してしまったのだけど、 *** そういう範囲でしか変更がありえない **** のであれば [1260] [1269] で提示のような修正もまぁあり、の範疇に収まります。 が、実世界においてはそういう局所な話ですまないことのほうが多く、 俺も (ぱ) 氏ももっとマクロな=大規模プログラムでの応用の話をしているわけです。 そういうレベルでは、提示のコードのような派生はうまくいきません。 そもそも OO (というか継承-派生というシステム) のおいしいところは ・「基底クラスを使う人」と「派生クラスを作る人」が分離できる ・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい ・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、  自動的に正しく使ってもらえる、と判断してよい という点にあるのであって、 決して「ソースの再利用のためのテクニック」ではないのです。 http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&thread=270 このへんとか。 基底クラスを使っている側にとって 基底クラス側が本来期待している挙動と異なる動きをするような派生クラス というのはまずいのです。 しかも、基底クラスユーザと派生クラス作者はたいてい別人なのです。 基底クラスを使うソースファイルと派生クラスを作るソースファイルも別ファイルなのです。 [あたかも便利そうに見える] [が、正しく設計されているとは必ずしも言い切れない] 派生クラスを安直に作り、使ってしまうと 異なる開発者がいて、複数のファイルから構成されていて、各プログラマは自分の担当範囲しか理解しきれない という大規模開発では見えにくい/直しにくいバグの元となります。 LSP (Liskov Substitution Principle) という概念も、この辺から来ています。 んで、マルチプルインスタンスの件のほうはもういいのでしょうか? 俺としては既に書いたとおり「対象読者層が異なる」というだけの話だと思っております。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1273] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/20 13:42:06

大文字小文字の例が悪かったのか、話がそこから進まないようです。 修正方法には以下の4つがあります。 ----------------------------------------------------------- 1.別名でメソッド追加  別々の処理として追加したい場合に使用 2.継承  関連処理をまとめて変更したい場合に使用 3.分割して親クラスを継承  関連処理をグループ化して、片方のグループを変更したい場合に使用 4.staticメソッドを作成  関連のない任意の場所で使用したい場合に使用 ----------------------------------------------------------- それぞれ用途が違いますが、オブジェクト指向特有で強力なのが2,3です。 別に全て2でやれと言っているわけではなく、2の使い方が出来るのが 利点だと言っている訳です。 間違いやすいとか分かりにくいと言うのは、実装者のスキルの話で、 よく見て追えば分かるし、変な設計をすれば分かりにくくなります。 遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 オブジェクト指向の場合は処理は関連するデータと共にクラスに まとめられるため、その引数を必要とするメソッドを、引数のクラス内 に実装できるか検討すべきです。 つまり、分かりやすいとか間違えやすいとか言う話は別として、 4種類の変更方法を選択できるため、再利用性が高いと言っている訳です。 >ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >でしょうか。 本は色々読みましたが、全てが同意できる物はありません。 殆どが、オブジェクト指向と言いつつ、デザインパターンの説明本や、UMLの説明本、 プログラミング言語の小技本、翻訳がおかしい本、中にはWEBアプリケーションの 作り方本もありました。 WEBサイトも同意できる物もあれば、出来ない物もあり、半々ぐらいです。 オブジェクト指向関係の書籍のひどさは、(ぱ)さんもご存じだと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1274] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/20 14:40:28

スタックの例とかあんまり細かく見ずにコメントしますが…。 >それぞれ用途が違いますが、オブジェクト指向特有で強力なのが2,3です。 >別に全て2でやれと言っているわけではなく、2の使い方が出来るのが >利点だと言っている訳です。 >... >つまり、分かりやすいとか間違えやすいとか言う話は別として、 >4種類の変更方法を選択できるため、再利用性が高いと言っている訳です。 そもそも継承というメカニズムを使うのが間違いのもとになっちゃうような。 デザインパターンを学習されているなら継承を使う機会は減ると思うんですけど。 #減るというか注意深くなるというか >本は色々読みましたが、全てが同意できる物はありません。 となると、ここで力説されていらっしゃる実装継承を使ったOOP をどこから学ばれたのか興味深いですね。 ちなみにこのページはオブジェクト指向を学ぶうえにおいてとても参考になります。 一読してみてください。 http://d.hatena.ne.jp/sumim/20040525/p1
[この投稿を含むスレッドを表示] [この投稿を削除]
[1275] Re:疑い深い・・・
投稿者:SE
2009/05/20 15:31:59

>俺も (ぱ) 氏ももっとマクロな=大規模プログラムでの応用の話をしているわけです。 >そういうレベルでは、提示のコードのような派生はうまくいきません。 なぜ大規模プログラムでうまくいかないのかが分かりません。 実際、大規模プログラムで使用していますが、効果が出ています。 例えば総合試験で性能目標に達しなかった場合、従来の方法では普通は大変更に なりますが、オブジェクト指向の場合、一部のクラスの取得処理を変更しただけで 修正できた例もあります。 オブジェクト指向ではオブジェクト単位であるため、大きいレベルから小さいレベル まで対応できるのが特徴です。 >そもそも OO (というか継承-派生というシステム) のおいしいところは >・「基底クラスを使う人」と「派生クラスを作る人」が分離できる >・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい >・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 > 自動的に正しく使ってもらえる、と判断してよい これが利点ですか?ちょっと他人に説明するのが難しいです。 私の例では、処理に大修正が入った場合(例えばDB変更や、ローカルファイルから 通信を使ったリモートファイルへの変更)、これだけの修正で済みますなどと 言えますが、上記の場合はどう説明しますか? >んで、マルチプルインスタンスの件のほうはもういいのでしょうか? >俺としては既に書いたとおり「対象読者層が異なる」というだけの話だと思っております。 了解しました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1276] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/20 15:47:40

>デザインパターンを学習されているなら継承を使う機会は減ると思うんですけど。 >#減るというか注意深くなるというか デザインパターンは知っています。 ちなみにデザインパターンは学習する物ではなく、解析する物です。 >ちなみにこのページはオブジェクト指向を学ぶうえにおいてとても参考になります。 >一読してみてください。 >http://d.hatena.ne.jp/sumim/20040525/p1 これもひどい内容ですね。 この当たりの話は知っていますが、参考にするのはまずいでしょう。 これならまだ「ウィキペディア」の「オブジェクト指向プログラミング」の 方がマシです。 一度読んでみてはいかがですか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1277] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/20 18:32:43

>ちなみにデザインパターンは学習する物ではなく、解析する物です。 ?? すみません、仰っておられる意味がわかりません…。 >これもひどい内容ですね。 詳しく教えていただきたいのですが、 どこがひどいと思われるのでしょうか? 「この当たりの話は知っています」と書かれていることから類似のWebページなどをご存知なのでしょうか。 できればその情報のソースを教えていただきたいです。 (自分的にこの手の情報はsumimさんの日記くらいしか知らないので) >これならまだ「ウィキペディア」の「オブジェクト指向プログラミング」の >方がマシです。 >一度読んでみてはいかがですか? ありがとうございます。 読んでみます。 #できれば他にもSEさんが比較的マシだと思ってる本やWebページを #いろいろ教えていただきたいところですが
[この投稿を含むスレッドを表示] [この投稿を削除]
[1278] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/21 00:40:14

>大文字小文字の例が悪かったのか、話がそこから進まないようです。 では、よい例を出してもらえませんか。具体的な例なしでこの手の話をしても 意味がありません。 774RRさんへの返信に >例えば総合試験で性能目標に達しなかった場合、従来の方法では普通は大変更に >なりますが、オブジェクト指向の場合、一部のクラスの取得処理を変更しただけで >修正できた例もあります。 とありますが、これも具体的にどういうケースだったのかわかりません。 普通に考えて、どこかの処理がボトルネックになっていたのなら、そこだけ 書き直せば速くなるでしょう。もちろん、その処理がプログラムのあっちこっちに コピペされていれば大変更になるでしょうが、関数等に切り出されて一箇所に まとめられていれば修正するのは一箇所です。ここまではオブジェクト指向は 関係ありません。 オブジェクト指向であったがゆえにうまくいった、とのことなので、 関数化ではうまくいかないケースだったのでしょう。どういう理由で、関数化では うまくいかず、オブジェクト指向(実装継承?)でうまくいったのでしょうか。 仕事のソースをここに貼ることができないのはわかっていますが、概要だけでも 教えてもらえませんか。興味深いので。 >遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 >構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 オブジェクト指向の最大の特徴のひとつであるポリモルフィズムは、遠いところで newしたオブジェクトのメソッドを呼ぶと、呼ぶ側が意識しなくても、 そのオブジェクトに応じたメソッドが呼び出される、というものですよね? デザインパターンなどでは生成に関するパターンだけでいくつもあって、 うちいくつかは、具体的なクラスが何であるかを意識させないようにするための ものですし、DI(Dependency Injection)なんかも考え方はそっち方面です。 まあ、この手のことは、当面用途もないのに調子に乗って柔軟性を求めると ソースが追えなくなってしまうので、私はあまり好きではないのですけれど。 ありがちな例では、たとえばログを出力するLoggerクラスをabstractクラスもしくは interfaceとして作って、それを継承またはimplementsしてファイルに吐くLoggerや syslogに吐くLoggerを作ったりしますが、これは、遠く離れたところでnewした Loggerを引数等で持って回ることになると思うんですが。 >オブジェクト指向の場合は処理は関連するデータと共にクラスに >まとめられるため、その引数を必要とするメソッドを、引数のクラス内 >に実装できるか検討すべきです。 意味がわかりません。 さっきのLoggerの例で言えば、Loggerクラスを引数として受け取るメソッドは Loggerを使うアプリケーションですが、アプリケーションのメソッドを Loggerクラスの中に作れ、という主張……ではないですよね。 >>ひとつ伺いたいのですが、SEさんはどんな本でオブジェクト指向の勉強をされたの >>でしょうか。 こくぼさんからも質問が出ていますが、私もSEさんが「比較的マシ」だと思ってる 本やWebページを教えていただきたいです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1280] Re:>(ぱ)こと管理人さん
投稿者:kit
2009/05/21 10:32:18

>>ちなみにデザインパターンは学習する物ではなく、解析する物です。 > >?? >すみません、仰っておられる意味がわかりません…。 素直に解釈すると、SEさんは GoF本や PofEAA あたりも読んだことがないって ことになります (こういった本を読むこと == デザインパターンを学習すること ですから)。 そう解釈していいんですかね?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1282] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/22 01:53:22

kitさん、おひさしぶりです。 >>>ちなみにデザインパターンは学習する物ではなく、解析する物です。 >> >>?? >>すみません、仰っておられる意味がわかりません…。 > >素直に解釈すると、SEさんは GoF本や PofEAA あたりも読んだことがないって >ことになります (こういった本を読むこと == デザインパターンを学習すること >ですから)。 私にもSEさんのおっしゃる意味はよくわからないのですが、ちょっと穿って解釈すると、  ちなみにデザインパターンは学習(に値)する(ような)物ではなく、  (こんなものを調子こいて使ってしまうとソースが読みにくくなって  必死に)解析する(ハメになるような)物です。 という意味なんでしょうか。 そういう趣旨ならわからなくはないし、部分的には賛同しないでもないのですが、 もしそういう意図なら、もっとわかりやすく書いていただきたいです……
[この投稿を含むスレッドを表示] [この投稿を削除]
[1283] Re:疑い深い・・・
投稿者:(ぱ)こと管理人
2009/05/22 02:16:37

横から口を出しますけど、 >>そもそも OO (というか継承-派生というシステム) のおいしいところは >>・「基底クラスを使う人」と「派生クラスを作る人」が分離できる >>・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい >>・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 >> 自動的に正しく使ってもらえる、と判断してよい >これが利点ですか?ちょっと他人に説明するのが難しいです。 前回私が例に出したLoggerクラスで考えると、 >>・「基底クラスを使う人」と「派生クラスを作る人」が分離できる 「Loggerクラスを使う人」は、logger.write()のようなメソッドを単に呼べばよく、 「ログをファイルに出力するFileLoggerクラスを作る人」と分離できる。 >>・基底クラス(のメンバー)を使う人は、派生クラスについて知らなくていい 「Loggerクラスを使う人」は、logger.write()のようなメソッドを単に呼べばよく、 FileLoggerクラスについては知らなくていい。 >>・派生クラスを作る人は、基底クラス側で期待している動作(=契約)に反しない限り、 >> 自動的に正しく使ってもらえる、と判断してよい 「FileLoggerクラスを作る人」は、基底クラス側で期待している動作(=契約)に 反しない限り、自動的に正しく使ってもらえる、と判断してよい わけで、私から見れば、774RRさんはごく普通にオブジェクト指向の利点を 挙げていると思うんですけど。 もちろん、何にでも利点と欠点はあるものですし、その重み付けは用途によって 変わります。SEさんの過去の業務で実装継承がすごく役に立ったのなら、 それはそれで興味深いことです。 だからこそ、実際に役に立ちそうな現実的な例を挙げていただきたいと思いますし、 上記774RRさんが挙げられたような利点をあまり重視しておられないように見える割に、 [1260]のUpperStackにおいて、getUpper()のようなメソッドを作らずにget()を オーバーライドしていたり、 [1270]で >>「要素をgetする側は、大文字が欲しいとき、そのことを意識しないで済む」 >>ということにしたいのでしょうか? という問いに対して >そうです。 と答えていたり、 同じく[1270]で new LinkedHashMap<String, String>()の戻り値を Map<String, String>型の変数に代入したりしている 意図がさっぱりわからないわけです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1284] Re:>(ぱ)こと管理人さん
投稿者:kit
2009/05/22 10:49:48

>ちょっと穿って解釈すると、 > > ちなみにデザインパターンは学習(に値)する(ような)物ではなく、 > (こんなものを調子こいて使ってしまうとソースが読みにくくなって > 必死に)解析する(ハメになるような)物です。 > >という意味なんでしょうか。 > >そういう趣旨ならわからなくはないし、部分的には賛同しないでもないのですが、 なるほど。 勉強したばかりで調子にのって *必要ないのに* 使いすぎると、問題は問題ですね。 でも、そもそもデザインパターンの多くは、それなりのプログラマーだったら、 自分で似たようなものを必要に応じて考えて既に使っているものですよね。 各種パターン本の意義は、そういうものにきちんと名前をつけて、いちいち説明 しなくても意思の疎通を可能にするという側面が大きいわけです。これにはソース 中の名前づけを標準化して、可読性を高めることを含みます。 したがって、経験のあるプログラマーにとって、デザインパターンの学習という のは、既知の設計手法について、規範となる名前を学習するという意味になります。 また、デザインパターンとして標準化された名前を使うことによって、ソース等を 解析することなく (すなわち、名前を見ただけで) モジュールの役割を理解する ことが可能になります。 また、もちろん初学者にとっては、設計パターンを自分で一から考える手間を省く という学習の意義があります。 というわけで、もしそういう意味だったとしても、やっぱり賛成できませんねえ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1285] Re:>(ぱ)こと管理人さん
投稿者:yuya
2009/05/22 11:47:06

懐かしいお名前がいっぱいでうれしくなりました。 kitさんも >でも、そもそもデザインパターンの多くは、それなりのプログラマーだったら、 >自分で似たようなものを必要に応じて考えて既に使っているものですよね。 と書かれていますが、SEさんのご意見が、 「天下りに与えられたパターンを憶える(=学習する?)んじゃなくて、 自分で同じものを作ってみるなりしてきちんと理解する(=解析する?)べきだ」、 ということならば、賛成ですけどね。 議論の行く末が気になるので、SEさんにはまた登場していただきたいです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1286] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/22 15:27:15

>どこがひどいと思われるのでしょうか? >「この当たりの話は知っています」と書かれていることから類似のWebページなどをご存知なのでしょうか。 >できればその情報のソースを教えていただきたいです。 >(自分的にこの手の情報はsumimさんの日記くらいしか知らないので) アランケイの「メッセージ指向」は、C++の登場した当たりから軽視されるようになっていて、 現在のオブジェクト指向の実装や環境から考えると、誤解しやすい物になっているからです。 (ぱ)さんも「ただの関数呼び出し」と言っていますが、私もそう思います。 歴史に関してはウィキペディアに詳しく記載されています。 >#できれば他にもSEさんが比較的マシだと思ってる本やWebページを >#いろいろ教えていただきたいところですが オブジェクト指向自体の話ではありませんが、オブジェクト指向の間違いやすい所に関しては、 以下の記載がかなりいい所をついていると思います。(全て賛成できる訳ではありませんが) http://itpro.nikkeibp.co.jp/article/COLUMN/20060921/248617/?ST=develop&P=1
[この投稿を含むスレッドを表示] [この投稿を削除]
[1287] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/22 16:25:01

>関数等に切り出されて一箇所にまとめられていれば修正するのは一箇所です。 >ここまではオブジェクト指向は関係ありません。 ここがミソです。1つの関数を考えた場合はそうですが、関数群で考えると違います。 例えばファイル操作を考えてみましょう。 クラスなら以下のようになるとします。 class File{   public void open(){}   public void read(){}   public void write(){}   public void close(){} } これなら明確です。ファイルからメモりに変わっても簡単に変更できるでしょう。 しかしCの構造化なら関数同士の関連はありません。 そのため、もしかしたらread()は業務ロジックに組み込まれ関数化されていないかもしれませんし、 write()は3つに分割されているかもしれません。例がファイルなのでそんな簡単な間違いは しないと言うかもしれませんが、もしこれが業務ロジックなら簡単に判断出来ないかもしれません。 これが関数化(プロセス中心アプローチ(POA)または、データ中心アプローチ(DOA))と、 クラス化(オブジェクト中心アプローチ(OOA))の違いです。 POA、DOA、OOAの特徴と違いについては、以下のサイトがよく分かります。 (分かりにくい表現もありますが) http://itpro.nikkeibp.co.jp/article/COLUMN/20061019/251255/ ちなみに簡単に変更できた例は、 メモリ上で頻繁に検索するデータが100件から6万件に変わった時の事でした。 検索にキャッシュやヒストリー機能などあらゆる機能を組み込み高速化しましたが、 修正したクラスは1つです。もしCの構造化で組んでいたら、修正箇所と影響範囲を 調べるだけで嫌になっていたと思います。 Loggerのようないわゆる「横断的関心事」はOOに適さないので例としては良くないと思いますが、 普通のLoggerは、staticのフィールド変数として作成して直接使用するため、Logger自体を メソッドの引数にして使用する事は少ないと思います。 敢えてLoggerを例にするとすると、 void write(Logger l){} なら、 class Logger{   void write(){} } にすべきと言う事です。 >
[この投稿を含むスレッドを表示] [この投稿を削除]
[1288] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/22 16:36:27

>アランケイの「メッセージ指向」は、C++の登場した当たりから軽視されるようになっていて、 >現在のオブジェクト指向の実装や環境から考えると、誤解しやすい物になっているからです。 >(ぱ)さんも「ただの関数呼び出し」と言っていますが、私もそう思います。 >歴史に関してはウィキペディアに詳しく記載されています。 あぁ…。抽象データ型のオブジェクト指向が現代のオブジェクト指向だと解釈されているのですね。 そこらへんの各人のオブジェクト指向への認識の違いを理解していただくことも含めて sumimさんの説明ページへとリンクしたつもりでしたが伝わってないみたいで…。 #Wikipediaの説明も見ましたがあれではSmalltalkが不憫で仕方ありません >オブジェクト指向自体の話ではありませんが、オブジェクト指向の間違いやすい所に関しては、 >以下の記載がかなりいい所をついていると思います。(全て賛成できる訳ではありませんが) >http://itpro.nikkeibp.co.jp/article/COLUMN/20060921/248617/?ST=develop&P=1 ザッと見ました。 このページを見る限りではSEさんが例示しておられる 実装継承を使ったオブジェクト指向プログラミングを推奨しているわけではなさそうですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1289] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/22 16:57:12

デザインパターンと言うのは、世の中にある数多くのOOで組まれたプログラムの中から、 共通性のある物を抜き出して分類し、その特徴や利点/欠点を解析する学問的な物です。 重要なのは解析する能力を付ける事です。 誰かの分類したパターンと特徴を暗記しても意味はありません。 ただ私もGoFのパターンは見ました。学者的で実務に使えるのは2割程度だと思いましたが。 ITproのHPの人も言っていますが、「言語」→「実践」→「デザパタ」と進むのが いいと思います。実践無しでデザパタを見たら、大抵の人は勘違いすると思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1291] Re:オブジェクト指向の概念の発明者は誰ですか?
投稿者:(ぱ)こと管理人
2009/05/23 12:26:48

件名変えました。 >アランケイの「メッセージ指向」は、C++の登場した当たりから軽視されるようになっていて、 >現在のオブジェクト指向の実装や環境から考えると、誤解しやすい物になっているからです。 >(ぱ)さんも「ただの関数呼び出し」と言っていますが、私もそう思います。 こくぼさんには「Smalltalkが不憫で仕方ありません」と言われそうですが、 職業プログラマである我々が、現状、仕事でSmalltalkを使うことはまあまずないわけで、 JavaやC++やC#を使うのに「メッセージ」がどうこう言われたら誤解を招く、というのは わかります。 で、当のsumimさんのページにはまさにそういうことが書いてあるわけで、 >なお、この文脈の「オブジェクト指向」において、メッセージングはぜんぜん関係ない >無用のもの and/or 動的性実現のための(仮想関数より効率の悪い)実装のひとつに >過ぎない…ということを強く意識する必要があります。ケイの影響で「オブジェクト >指向=メッセージ」と脳に染みついている人には酷かもしれませんが、いっそ排除して >考えたほうがすっきりしますし、可能な限りそうすべきです。 >しがらみのない初学者へのレクチャーに際しては、ぜひとも「オブジェクトにメッセー >ジを送って…」とか「世の中のあらゆるものを(ry」なんて説明は後々無用な混乱を >招くだけなので、やめて欲しいと思います。 なぜこのページについて >これもひどい内容ですね。 とSEさんがおしゃるのか、さっぱりわからないんですけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1292] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/23 13:47:59

SEさんが何をおっしゃりたいのかますますわからなくなっていくのですが、 >ちなみに簡単に変更できた例は、 >メモリ上で頻繁に検索するデータが100件から6万件に変わった時の事でした。 >検索にキャッシュやヒストリー機能などあらゆる機能を組み込み高速化しましたが、 >修正したクラスは1つです。もしCの構造化で組んでいたら、修正箇所と影響範囲を >調べるだけで嫌になっていたと思います。 関連する操作やデータをまとめる、というのは普通にモジュール化であって、 私が「疑りぶかい~」で書いたオセロの例の、Cでstaticで隠蔽を行った board.cで達成していることでは? http://kmaebashi.com/programmer/object/othello.html 「疑りぶかい~」を書いたときの私の認識は、 「Cなどでプログラムを書いている普通のプログラマは、staticで情報隠蔽するような  モジュール化は普通に行っているだろう。でもそれは、オブジェクト指向ではない。  オブジェクト指向(C++流の)といえばカプセル化、継承、ポリモルフィズムと言われるけれど、  カプセル化は普通のCプログラマも理解していそうだし、継承やポリモルフィズムに  至る前にマルチプルインスタンスを理解しなければいけないのに、世間にあふれる  オブジェクト指向の説明からはそこがすっぽり抜けている。  多くの人がここで引っかかるように思うので、このミッシングリンクは埋めておく  べきではないか」 というものです。 この認識がズレている、という批判ならお受けしますけれども。 マルチプルインスタンスのさらに手前の事例を持ってきて、オブジェクト指向の 成果だと言われても…… 継承の話はどこにいったんでしょうか。 いや、「世間のCプログラマはstaticで実装を隠蔽するような気の効いたことは していない。だからお前の認識はズレているのだ」ということならそうなのかも しれませんけど(1ソースファイル1関数、という規約のプロジェクトとかって、 今でもあるんでしょうか)。 >普通のLoggerは、staticのフィールド変数として作成して直接使用するため、Logger自体を >メソッドの引数にして使用する事は少ないと思います。 うーん、Loggerくらいならstaticでもかまわないとは確かに思いますけれど、 私ならアプリケーションのインスタンスのフィールドに持ちますね。 オセロの例なら、Boardクラスで障害発生時とかのログを残すとして、Loggerは Boardに持たせます。名人戦のBoardだけ障害発生時の対応が違ったりするかも 知れませんし。よって、BoardのコンストラクタかsetLogger()メソッドの 引数でLoggerを渡すことになります。 >敢えてLoggerを例にするとすると、 >void write(Logger l){} >なら、 >class Logger{ >  void write(){} >} >にすべきと言う事です。 ええと、write()メソッドがログを吐くメソッドなら、 >class Logger{ >  void write(){} >} となるのは当たり前だと思うんですが……
[この投稿を含むスレッドを表示] [この投稿を削除]
[1293] Re:>(ぱ)こと管理人さん
投稿者:(ぱ)こと管理人
2009/05/23 13:51:39

>デザインパターンと言うのは、世の中にある数多くのOOで組まれたプログラムの中から、 >共通性のある物を抜き出して分類し、その特徴や利点/欠点を解析する学問的な物です。 >重要なのは解析する能力を付ける事です。 なるほど、「学問的な物です」というのはよくわかりませんが、 おっしゃりたいことはだいたいわかったように思います。 >誰かの分類したパターンと特徴を暗記しても意味はありません。 しかしこれを「意味はありません」と言い切っちゃうのはどうかと。 kitさんが既に書いておられますが、デザインパターンはパターンに名前をつけて プログラマ間のコミュニケーションに使うことに意味があるわけですから。 >ITproのHPの人も言っていますが、「言語」→「実践」→「デザパタ」と進むのが >いいと思います。実践無しでデザパタを見たら、大抵の人は勘違いすると思います。 ここに異論はありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1297] Re:オブジェクト指向の概念の発明者は誰ですか?
投稿者:こくぼ
2009/05/26 08:58:11

>こくぼさんには「Smalltalkが不憫で仕方ありません」と言われそうですが、 >職業プログラマである我々が、現状、仕事でSmalltalkを使うことはまあまずないわけで、 >JavaやC++やC#を使うのに「メッセージ」がどうこう言われたら誤解を招く、というのは >わかります。 Smalltalkが不憫っていうのは、SEさんが紹介している説明を見ると まるでSmalltalkが悪いせいでオブジェクト指向が理解されてない みたいな書き方をされてるせいです。 #自分も特にSmalltalkに思い入れがあるわけではありません^^; >とSEさんがおしゃるのか、さっぱりわからないんですけど。 ですよね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1298] Re:オブジェクト指向の概念の発明者は誰ですか?
投稿者:(ぱ)こと管理人
2009/05/27 02:24:13

>#自分も特にSmalltalkに思い入れがあるわけではありません^^; ありゃ、そうですか。了解です。 全然完璧に関係ないですが、大昔、fjに高木浩光さんが 「Smalltalk原理主義者を殲滅せよ」なんてことを書いていて(もちろんネタですが)、 今これを探そうとしてGoogleグループを見てみたのですが…Googleグループって、 NewsGroupの検索ができるのだと思っていましたが、いつのまに2ch検索エンジンに?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1301] 管理者により削除されました
2009/05/29 00:42:36

テスト投稿らしいものだったので、削除しました。 テスト投稿はテスト用掲示板にお願いします。
[この投稿を含むスレッドを表示]
[1302] Re:オブジェクト指向の概念の発明者は誰ですか?
投稿者:SE
2009/05/28 14:39:32

>>>これもひどい内容ですね。 > >とSEさんがおしゃるのか、さっぱりわからないんですけど。 1.メッセージ指向 2.クラス指向 3.手続き抽象化 のまるで3つのオブジェクト指向があるように思えますが、実質的にはオブジェクト指向は2です。 1はメッセージが焦点になっていますが、本質はオブジェクトで2と同様です。 3は少なくとも私は知りませんし、一般的ではないと思います。HP筆者の独自解釈では? もし初心者が見たら混乱するだけだと思います。2の説明だけあればいいと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1303] Re:>(ぱ)こと管理人さん
投稿者:SE
2009/05/28 15:24:23

>関連する操作やデータをまとめる、というのは普通にモジュール化であって、 >私が「疑りぶかい~」で書いたオセロの例の、Cでstaticで隠蔽を行った >board.cで達成していることでは? ここが重要です。 構造化プログラミングの「モジュール化」は基本的にモジュール化した所でしか有効ではありません。 1つの関数で考えた場合は分かりにくいかと思いますが、関連する複数の関数での場合を考えてください。 つまり拡張を見越して単位を合わせてモジュール化しておく必要があると言う事です。 オブジェクト指向の場合はクラス単位でモジュール化されているような物であると言う事です。 つまり末端のクラスから上位のクラスまで、全ての単位でモジュール化されているため、 あらゆる単位で変更が可能だと言う事です。 つまり私の言いたいのは、 オブジェクト指向の 利点は「再利用性が高まる事」=「変更がしやすい、変更しても壊れにくい」。 本質は「抽象化」 だと言う事です。 利点は「見通しの良さ」 本質は「マルチプルインスタンス」 ではないと思います。 >いや、「世間のCプログラマはstaticで実装を隠蔽するような気の効いたことは >していない。だからお前の認識はズレているのだ」ということならそうなのかも >しれませんけど(1ソースファイル1関数、という規約のプロジェクトとかって、 >今でもあるんでしょうか)。 774RRさんの言う通り、「対象読者層が異なる」というだけの話のようです。 つまり「インスタンスが複数あっていい」というあたりを理解していないプログラマ向けの文書で、 私の指摘は「インスタンスが複数あるのは当たり前」と理解しているプログラマの視点という事です。 >うーん、Loggerくらいならstaticでもかまわないとは確かに思いますけれど、 >私ならアプリケーションのインスタンスのフィールドに持ちますね。 >オセロの例なら、Boardクラスで障害発生時とかのログを残すとして、Loggerは >Boardに持たせます。名人戦のBoardだけ障害発生時の対応が違ったりするかも >知れませんし。よって、BoardのコンストラクタかsetLogger()メソッドの >引数でLoggerを渡すことになります。 棋譜をセーブデータとして残すために、コンストラクタかセッターにファイル名を渡すと 言うならボードクラスに入れるのはいいと思いますが、 名人戦の障害発生対応が違うかもしれないので、エラーログクラスを受け渡すと言うのは おかしいと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1304] Re:>(ぱ)こと管理人さん
投稿者:yuya
2009/05/28 16:49:04

クラスの階層構造のおかげで、モジュール化も適切な階層構造で行いやすくなる、ってことでしょうか。 少なくとも私自身は、そんなメリットを実感したこと、一度もないなぁ。 Cで「単位を合わせて」モジュール化する困難さと、クラスの階層構造を適切に設計する困難さは、 あまり違いがないように思うんですが、人によるのかな。 無地のノートより罫線の引いてあるノートのほうが書きやすい、ぐらいの違いはあるかもしれないけど。 Cで適切な階層構造のモジュール化が行えない人が、オブジェクト指向言語でクラス設計したところで、 (しかも実装継承で組んだりしたら)余計ぐちゃぐちゃになっちゃうような気がするんですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1305] Re:オブジェクト指向の概念の発明者は誰ですか?
投稿者:こくぼ
2009/05/28 18:42:42

>まるで3つのオブジェクト指向があるように思えますが、実質的にはオブジェクト指向は2です。 >1はメッセージが焦点になっていますが、本質はオブジェクトで2と同様です。 1の本質はオブジェクトではなくてメッセージだと書いてあるはずですが…。 #Smalltalkの文法やクラスやオブジェクトといった概念もおまけでしかない、とアランケイはのたまっています >もし初心者が見たら混乱するだけだと思います。2の説明だけあればいいと思います。 きちんと分類して書いてあるから少なくとも混乱することはないと思いますけどね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1306] Re:>(ぱ)こと管理人さん
投稿者:こくぼ
2009/05/28 18:55:50

>つまり私の言いたいのは、 >オブジェクト指向の >利点は「再利用性が高まる事」=「変更がしやすい、変更しても壊れにくい」。 >本質は「抽象化」 >だと言う事です。 >利点は「見通しの良さ」 >本質は「マルチプルインスタンス」 >ではないと思います。 本質は抽象化だと仰っているのにSEさんが出してるスタックの例はまったく 抽象化されていないような気がするのですが…。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1307] オブジェクト指向の利点の話
投稿者:(ぱ)こと管理人
2009/05/29 00:39:49

件名変えました。 >>関連する操作やデータをまとめる、というのは普通にモジュール化であって、 >>私が「疑りぶかい~」で書いたオセロの例の、Cでstaticで隠蔽を行った >>board.cで達成していることでは? >ここが重要です。 >構造化プログラミングの「モジュール化」は基本的にモジュール化した所でしか有効ではありません。 >1つの関数で考えた場合は分かりにくいかと思いますが、関連する複数の関数での場合を考えてください。 いや、だから私が例に出したboard.cにはちゃんと複数の関数があるんですけど。 http://kmaebashi.com/programmer/object/othello.html もうSEさんが何を言いたいのかさっぱりです。 >オブジェクト指向の >利点は「再利用性が高まる事」=「変更がしやすい、変更しても壊れにくい」。 >本質は「抽象化」 >だと言う事です。 「抽象化」なんてのはおよそあらゆるプログラミングパラダイムの目的みたいなもので、 それだけでは何がなんだかさっぱりです。 >774RRさんの言う通り、「対象読者層が異なる」というだけの話のようです。 >つまり「インスタンスが複数あっていい」というあたりを理解していないプログラマ向けの文書で、 >私の指摘は「インスタンスが複数あるのは当たり前」と理解しているプログラマの視点という事です。 私もそう思っていたのですが、ちょっと疑い始めているところです。 >棋譜をセーブデータとして残すために、コンストラクタかセッターにファイル名を渡すと >言うならボードクラスに入れるのはいいと思いますが、 >名人戦の障害発生対応が違うかもしれないので、エラーログクラスを受け渡すと言うのは >おかしいと思います。 まあそのへんは要件次第で、エラーログならstaticでよいという考え方もあるでしょう (Boardが持つのは「おかしい」と言われると、それは何故かと聞きたくなりますが)。 ええと、しかも、「コンストラクタかセッターに『ファイル名を』渡す」んですか? 棋譜をファイルに吐かず、こっちの画面に出したい、とかの場合はどうするんですか? もともとLoggerの話は、SEさんの[1269]における http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1269&range=1 >これを次のように変更します。1行で済みます。 とか、 [1273]における http://kmaebashi.com/bbs/list.php?boardid=kmaebashibbs&from=1273&range=1 >遠くの所でnewした特有の処理の入ったクラスを、引数で使い回すのは、 >構造化のスタンプ結合的で、オブジェクト指向的には良くない設計です。 とかの話から出てきたものです。Loggerを引数で引き回そうが、staticで保持しようが、 遠いところでnewされたオブジェクトを、その実際のクラスがわからない状態で 使用するということに変わりはありません。そのとき、うまく使えばポリモルフィズムで 動きが変えられるというのがよく言われるオブジェクト指向の利点です。 その点、SEさんのUpperStackは、使う側がUpperStackであることを意識して使わなければ ならない(リスコフの置換原則を破っている)のでダメだ、と言っているわけです。 CばっかりずっとやってきたプログラマにJavaで設計させると、機能単位でクラス分割は するものの、 (1)何もかもstaticフィールドとメソッドで作ってしまう。 (2)staticメソッドにしない代わりに、毎回オブジェクトをnewして、いくつか  メソッドを呼んだら使い捨てにしてしまう。 このどちらかの設計にしてしまうことがあります。 正直なところ、SEさんはこの(2)のタイプの人に見えてしょうがないんですが。
[この投稿を含むスレッドを表示] [この投稿を削除]