-OOP限定-プログラム設計相談室
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2005/09/24(土) 16:35:590478471
2011/03/09(水) 01:13:47.95462は別人。471のPDFを読めば馬鹿でも分かるように書かれている。読むべき箇所も示した。
それでももっと噛み砕いて説明しないと分からないのか…。
いちおう試みてみるけど、まぁ俺には無理だなw
> はっきりしておかなければならないこととして、100%閉じたプログラムというものは
> あり得ないということがあります。
(中略)
> 一般的には、モジュールがどんなに頑張って閉鎖したつもりでも閉じていない部分が
> 必ずあって、それに対して何らかの変更が起きてしまうものなのです。
と書いてあるだろ?
お前が>>431から話しているのは、閉じていないものをどうやったら外見上閉じているもの
として扱えるか?という本末転倒な話なの。メタクラスで追加なんてその典型。
既存のソースコードを変更しないから閉じているのではなく、OCPを満たした閉じている
プログラムは必然的に既存のコードの変更が必要なくなるということ。
意図せず開いてしまったものは、当然だけど変更せざるを得ない。
PDFのShapeの例だと「Listing 2」はその時点ではOCPを満たしていると考えられるが、
描画順序というルールの導入に対しては開いていて、「Listing 3」への変更はコードを
変更することでしか対処できない(そしてPDFでもメソッドの追加という変更をしている)。
この「Listing 2」から「Listing 3」の変更は>>431の状況の具体例と考えられる。
頑張ってみたけど駄目かねぇ…
しかし間違いに気づいたら素直に認めてくれよ。俺も認めるからさ。
0479デフォルトの名無しさん
2011/03/09(水) 19:36:42.51ようやく自分の意見を書いたのか。
最初に書いて置くが、同じ文章をよんでも知識や経験で理解する内容は違う。
同じ人間でも今日読んで理解した内容と、数年後に読んで理解した内容は違うだろう。
それに、なぜその文章で議論しないといけない?
>相当やさしく書かれているから、これで理解できなければ救いようがないわ
明らかに主観で薦めているものを前提にしている、客観性がゼロだ。
まっ、しかしマーチンを選択したのは良いと思うが。(ただしC++を対象にしているから抽象化が弱いが)
>お前が>>431から話しているのは、閉じていないものをどうやったら外見上閉じているもの
>として扱えるか?という本末転倒な話なの。メタクラスで追加なんてその典型。
ほら最初から理解が違う、マーチンの言っているのは将来にわたって全て閉鎖するのは不可能だと言っていだけ。
だから、その時点で閉鎖されているモジュールはいくらでも存在する。
それとメタクラスを理解出来ているのか?「メタクラスで追加なんてその典型」なぜ”追加”と言う言葉を使う?
メタクラスはクラスの抽象化だ、クラス自体を入れ替えると言うことで、実装の入れ替ということだ、追加じゃない。
wikipediaをあまり信用していないから引用するのも嫌なんだが、そっちが出したから出してみる。
>ポリモーフィックな開放/閉鎖原則
> 1990年代、開放/閉鎖原則とは一般的に抽象インタフェースの利用を指すように意味が変わっていった。
> その定義では実装はもはや固定ではなく、複数の実装が存在可能となり、互いにポリモーフィックに入れ替えることができる。
「実装はもはや固定ではなく、複数の実装が存在可能となり、互いにポリモーフィックに入れ替える」
この入れ替えを、メタクラスで行おうとする話だが、なにが「本末転倒な話」なのか詳細に説明してくれるか?
0480デフォルトの名無しさん
2011/03/09(水) 19:37:23.76>既存のソースコードを変更しないから閉じているのではなく、OCPを満たした閉じている
>プログラムは必然的に既存のコードの変更が必要なくなるということ。
>意図せず開いてしまったものは、当然だけど変更せざるを得ない。
次にこれだ、「OCPを満たした閉じているプログラムは必然的に既存のコードの変更が必要なくなる」
自分が引用している部分と矛盾するとは思わないのか?「100%閉じたプログラムというものは あり得ない」
OCPを満たしているから修正が必要ないんじゃなく、現時点で修正の必要がないからOCPを満たしているんだろう。
>PDFのShapeの例だと「Listing 2」はその時点ではOCPを満たしていると考えられるが、
>描画順序というルールの導入に対しては開いていて、「Listing 3」への変更はコードを
>変更することでしか対処できない(そしてPDFでもメソッドの追加という変更をしている)。
>この「Listing 2」から「Listing 3」の変更は>>431の状況の具体例と考えられる。
次はこれ、ほら〜また俺との認識が違う、この「Listing 2・Listing 3」の話は開発時の設計方法だと認識したが。
ここで書いてある「戦略的閉鎖」とは、
>完全な閉鎖というのがありえないとすると、これを戦略的に行わなければならないことになります。
>つまり、設計者は、どのような種類の変更に対応すれば、その設計を閉じられるかということを
>選択しなければならない
つまり、いかに閉鎖したクラス設計するかが書かれている。それに対してOCPとは(wikipedia)
>つまり、あるクラスが一度コードレビューやユニットテストなどの品質検査を通過し実際の運用に入ったならば、
>そのクラスを修正してはならず、拡張によって対処しなければならない。
運用が始まったものに対する原則だ。 俺の書いた>>431は運用が始まった後のことだ。
まったく、俺の聞いたことの入り口すら理解出来ないのか?
0481471
2011/03/09(水) 21:26:35.22> それとメタクラスを理解出来ているのか?「メタクラスで追加なんてその典型」なぜ”追加”と言う言葉を使う?
431は機能追加についての話だったからその意味で"追加"と書いたがおかしかったか?
この話でメタクラスが出てくること自体がおかしい(ついでにNullオブジェクトの方も
意味不明)が、お前が具体的にどういう方法を考えているのかなんて知らない。
もしかしたら俺がものすごく勘違いをしているのかもしれないな。
それなら本末転倒といったのは先走りすぎたかも知れない。
> 「実装はもはや固定ではなく、複数の実装が存在可能となり、互いにポリモーフィックに入れ替える」
> この入れ替えを、メタクラスで行おうとする話だが、なにが「本末転倒な話」なのか詳細に説明してくれるか?
しかし、これをよんでも相変わらず意味不明。
とにかく憶測で話をしても埒があかないから、メタクラスでの方法の正当性を主張したいなら
Shapeの例などで具体的に>>431を説明してくれ。
0482471
2011/03/09(水) 21:27:14.66> 次にこれだ、「OCPを満たした閉じているプログラムは必然的に既存のコードの変更が必要なくなる」
> 自分が引用している部分と矛盾するとは思わないのか?「100%閉じたプログラムというものは あり得ない」
> OCPを満たしているから修正が必要ないんじゃなく、現時点で修正の必要がないからOCPを満たしているんだろう。
違う。OCPを満たしていれば修正の必要は無いが、修正の必要がないからといってOCPを
満たしているとは限らない。OCPはOOPだけの概念ではなくグローバル変数などについても
いえることだが、グローバル変数を使用している(=OCPを満たしていない)としても修正の
必要があるとは限らない。何か矛盾することを書いたか?
> 次はこれ、ほら〜また俺との認識が違う、この「Listing 2・Listing 3」の話は開発時の設計方法だと認識したが。
中略
> 運用が始まったものに対する原則だ。 俺の書いた>>431は運用が始まった後のことだ。
じゃあ「Listing 2」の段階で運用が始まり、その後描画順序というルールを導入する必要が
でてきたとしたら?同じことだろう?
描画順序というルールを始めから想定するなんて不可能で、設計段階でどんなに頑張っても、
運用段階では閉じていない部分が必ずでてきてしまう。だから完全な閉鎖がありえないと
書かれている。
そこで、経験や勘でなるべく有り得そうな変更を予測して、戦略的にOCPを適用する必要が
あるということ。
お前は注意深く設計されたクラスは全てに対し完全にOCPが適用され、完全に閉鎖されている
という前提で話をしているからおかしいの
もちろんOCPが満たされている範囲では、wikipediaの引用部分に書かれていることは全て
当てはまる(そして逆に言えばOCPが満たされていない場合は、当てはまらない)。
0483デフォルトの名無しさん
2011/03/09(水) 23:18:50.99たとえば、図形処理モジュールが
「図形一般をあらわすインタフェース(or 抽象クラス)があって、
円や矩形などの具体的な図形はすべてそれを継承している」
ように設計されていたとする。
このモジュールは新しい図形の種類(三角形など)の追加に関して閉じているが、
新しい図形の操作の追加に関しては閉じていない。
431は後者のときに、既存クラスに手を入れずに対処する方法を質問したのではないかと思う。
0484デフォルトの名無しさん
2011/03/09(水) 23:31:12.43追加したい操作にもよるだろうが、究極的には最初からクラス間の依存関係を全てインターフェイスで扱うか
全てのフィールドはprotected、全てのメソッドをオーバーライド可能にしておいてカプセル化を壊すかしかない
0486デフォルトの名無しさん
2011/03/10(木) 00:47:36.69見事に話が噛み合っていない。全部に対応するのは疲れるから本筋のところだけ書く。
(メタクラスやNULLオブジェクトは自分で勉強してくれ)
>じゃあ「Listing 2」の段階で運用が始まり、その後描画順序というルールを導入する必要が
>でてきたとしたら?同じことだろう?
だから書いたんだ。同じ物を読んでも同じ認識にはならないと、それなのにお前はただ読めと、まったく...
本題にはいるが、マーチンが書きたかったのは運用に入る前の設計方法で
俺が聞いているのは運用後の設計方法、まったく違う。
運用前の設計では、マーチンが書いているようにOCPを適用しやすく設計方法で
運用後はOCPをいかに守るべきかの設計方法を聞いている。
>お前は注意深く設計されたクラスは全てに対し完全にOCPが適用され、完全に閉鎖されている
>という前提で話をしているからおかしいの
またそうやって決め付ける。自分の認識が間違っているとは思わないのか?
書いた本人の俺が違うと言っている認識についてどう思うんだ?
>>483
その通り、理解できる人がいると嬉しい。
そこが入り口で、その場合にどう設計すれば良いのかを聞きたかったんだが、その入り口にもなかなか立てない...
>>484
>そんなもん最初から想定してないと無理だろ
なぜ無理だと決め付ける?
>追加したい操作にもよるだろうが、究極的には最初からクラス間の依存関係を全てインターフェイスで扱うか
>全てのフィールドはprotected、全てのメソッドをオーバーライド可能にしておいてカプセル化を壊すかしかない
なるほど、それを気にして今までカプセル化が崩れると言っていたのか、納得した。
だが自分でも「インターフェイスで扱う」とか解決策を考えているじゃないか?「フィールドはprotected」もgetter/setterを書けば良い事だし。
まっ、それでも「最初からある程度は想定していないと」と考えるのは分かる、だから俺もメタクラスと書いた。
(メタクラスならクラスごと入れ替える訳だし、想定しなくてもなんとかなる場合が多い)
0487デフォルトの名無しさん
2011/03/10(木) 00:48:18.95>それと同じことを直前で書いたつもりなんだけどなw
>やっぱ俺の説明が下手くそなんだろうな
説明が下手じゃなく書いている内容が違うんだろう?
>お前は注意深く設計されたクラスは全てに対し完全にOCPが適用され、完全に閉鎖されている
>という前提で話をしているからおかしいの
> 新しい図形の操作の追加に関しては閉じていない。
> 431は後者のときに、既存クラスに手を入れずに対処する方法を質問したのではないかと思う。
が同じ? 「完全に閉鎖されている」と「追加に関しては閉じていない」が同じだと? 駄目だ俺には正しく読み取れない。
0488デフォルトの名無しさん
2011/03/10(木) 01:34:29.39メタクラスによる機能追加というのは具体的にどうやるつもりなのか示してくれ
0489471
2011/03/10(木) 01:35:05.87> (メタクラスやNULLオブジェクトは自分で勉強してくれ)
俺はNullオブジェクトというと書籍の『リファクタリング』などに載っているものを想像
するんだけど、>>431はどうもそれとは違うようだから勉強しようにもできないんだ。
それからメタクラスによって>>431を解決する方法は431自身しか知らないよな?
だったら勉強しようがないだろ。
繰り返すが、自分の正当性を示したいのなら具体的に説明しろ。
できないならちゃんと認めろ馬鹿が。
> 本題にはいるが、マーチンが書きたかったのは運用に入る前の設計方法で
> 俺が聞いているのは運用後の設計方法、まったく違う。
ではそのマーチンなら運用後の設計方法はどうすると思う?そんなの本人しか分からない?
確かにそうだけどおかしいとは思わないか?
OCPは20年以上前からあり、>>431のような疑問も当然現れてくるはず。なのに運用後
のことは何も言及されていないということになる。
マーチンだけじゃない。OCPに関してはたびたび目にするが>>431のような質問は俺は見た
ことも聞いたこともない。ここで初めて目にした。
もし既にあるというのなら教えて欲しい(そして何故そこでの解決法で満足せずここで
質問したのかということも)。
最後に一つ答えて欲しい。お前は>>480の最後で
> まったく、俺の聞いたことの入り口すら理解出来ないのか?
と書いているが、お前は天才で、20年以上にわたり誰も考えつかなかった>>431の解決策を
世界で初めて考え出し、それを理解できない多くの凡人の方がおかしいということか?
ここで「はいそうです」と答えてくれると嬉しいね。話が噛み合わない原因がはっきり
するから。
0490デフォルトの名無しさん
2011/03/10(木) 08:21:07.60それってまんまSmalltalkとかRubyの事だな
ところで、メタクラスという言葉はクラスのクラスの事を指してるんだよな
なんでクラスを入れ替えるとか機能追加とかそういう話になるんだ?
もしかしてこの認識がなんか間違ってるのか
0491デフォルトの名無しさん
2011/03/10(木) 09:56:55.73具象クラスがそれを実装してるとする。draw()の他にrotate()を追加したいとする。
OCPに従うならRotatableShapeインターフェースを新規作成して
RotatableTriangle等の具象クラスを作成する。でも仕様変更ですべての具象クラスが
Rotatableになる必要があるならリファクタリングしてShapeに手を入れた方がいい。
OCPはOOPの基本的な原則であって、予測してなかった仕様変更に対してまで
頑なに守るようなルールじゃないし、あらかじめShapeにメソッドが追加されることを
前提にしたところでShapeの設計は変わらない。
>たまに継承を使うなと言う人がいるけど
継承を使うなは論外だと思うけど、継承より委譲が大原則。理由はより疎結合になるから。
サブルーチン的な発想で共通機能をベースクラスに押し込んで継承するのは間違いなんだけど
割とやりがち。Shapeの例だとそれぞれのインスタンスをファイルに保存することが出来たとして、
AbstractShapeクラスを作ってそこにsave()メソッドを実装して継承するのは駄目で、
ShapeSaverクラスを作ってそっちに委譲する、というイメージ。
0492デフォルトの名無しさん
2011/03/10(木) 10:02:07.87絶対に変更しないんだろ? だったらフィールドをそのまま公開してるのと同じだ
0493デフォルトの名無しさん
2011/03/10(木) 20:16:53.89インタフェースを用いるというのはその実現手段のひとつでしかない。
もし操作が追加されると予測されるなら、switch〜case方式にする手もあるし、
操作の共通インタフェースを導入するという手もある。
メタクラスを使ってクラスごと入れ替えるというのも、
乱暴だが、選択肢のひとつではあるだろう。
0494デフォルトの名無しさん
2011/03/10(木) 20:29:07.49既存クラスのソースファイルをビルドから除外して
かわりに別のファイルに差し替えるのとどう違うの?
0495デフォルトの名無しさん
2011/03/10(木) 21:41:21.34switch〜case方式に戻してどうすんだよ
OOPにおけるOCPは「いかにswitch文を除去するか?」が最重要テーマと言っても良いくらいなのに
OCPが分からないなら黙っておいた方がいいよ
0496431
2011/03/11(金) 02:04:56.19共通モジュールServiceAクラスがあり
それがClientBクラスなどいろいろな箇所で使われている。
ClientBクラスはServiceAクラスをコンポジション(委譲)して使っている。
なので、ClientBクラスはServiceAクラスのインスタンス生成・破棄を管理している。
ある日仕様変更があり、ServiceAクラスに新機能を追加することになった。
現在使用しているクライアントにも、新仕様を適用したクラスを使用させたい。
この場合、修正のやり方として一番簡単なのはServiceAクラスを直接修正。
新しいメソッドを追加する、しかしこれではServiceAクラスがOCP違反になる。
次にServiceAクラスを継承して修正した場合、ServiceAクラスはOCPを満たすが
ClientBクラスなど修正が必要になりOCP違反になる。
では、ServiceAクラス・ClientBクラスともに継承して修正すれば良いのではと考えるが
しかしこれも「依存するモジュールに変更が連鎖して広がっている」のでOCP違反。
0497431
2011/03/11(金) 02:05:38.53では、なぜ変更の連鎖が起きるのか?
ClientBクラスとServiceAクラスとの関係がDIP違反だから起きている。
ClientBクラスがServiceAクラスをコンポジションしているから
ClientBクラスが上位(高次)モジュールなのに
ServiceAクラスと言う下位モジュールの具象クラスに依存している。
DIPを守るには、上位と下位の繋がりを抽象化すればいい。
これを解決するには一つの方法は、クラスを抽象化(メタクラス)すればいい。
ここでメタクラスを簡単に説明すると、普通クラスからインスタンスを作成する。
これがメタクラスだと、クラス(オブジェクトじゃなく型自体)を入れる変数を想像してくれ
その変数を使ってインスタンスが作れる、変数だからいろいろなクラスが設定出来る
インスタンスを作る方では、実際にどのクラスからインスタンスが作られたのか分からない。
つまり、クラスが抽象化される。
0498デフォルトの名無しさん
2011/03/11(金) 08:47:31.920499デフォルトの名無しさん
2011/03/11(金) 10:35:38.79で、DIによって実装クラスを入れ替えるのが
既存クラスにメソッド一個追加するよりも既存コードの動作への影響が少ないというの?
何を根拠に?
0500デフォルトの名無しさん
2011/03/11(金) 17:43:28.67> 431(と分かってなさそうなその他数名)は読んどけよ
の471が一番理解出来ていないのはわかった
最近多いよね、民主党みたいに墓穴掘るやつw
0501デフォルトの名無しさん
2011/03/11(金) 20:55:26.54なぜ関係がないと思うんだ? まっ一つの方法でしかないが。
>>499
>だったら最初からそう言えよ
>で、DIによって実装クラスを入れ替えるのが
最初から言っている、具体例にしただけだ。
ところで、DIって何だ? わからないんだが。
>>500
>いまいち理解出来んが
簡単に書いたつもりだが...
しかし、東北から関東まで大変そうだな。
0502デフォルトの名無しさん
2011/03/11(金) 22:18:31.68>496のような問題が起きないように設計するための手法で、
その例だとClientが使うServerオブジェクトを外から与えてやるようにする。
0503デフォルトの名無しさん
2011/03/12(土) 09:39:42.41そもそも>>431と>>496,497では同じことを書いているようには読めない。
OCPを誤解しているのは相変わらずだし、抽象化やメタクラスの説明もめちゃくちゃ。
DIをわからないというのも意味が分からない。
さすがにもういいや。
>>500は…
>>461→>>464を読んだときも感じたんだけど、なんだろうな?この違和感…w
0504デフォルトの名無しさん
2011/03/12(土) 11:24:51.23既存クラスには絶対手を入れない、という方針の是非はともかく。
>496の例ならDIですむが、設計時に予測していないような修正だったら
メタレベルでクラス間のつながりを変更するしかないかもしれん。
なんかもっと難しそうな例はないのか? >496
0505デフォルトの名無しさん
2011/03/12(土) 12:51:07.48じゃあ通訳して
特に431の方
0506デフォルトの名無しさん
2011/03/12(土) 13:13:33.62どういう勉強したらそんなことになるのか
0507デフォルトの名無しさん
2011/03/12(土) 21:50:59.26>メタレベルでクラス間のつながりを変更するしかないかもしれん。
なるほど、だからDIと書いたのか。
Dependency Injectionは知っているが文脈的に別の意味だと思った。
DIはメタクラスじゃない、メタクラスは言語の仕様だから。
DIで実装してもいいが、それは変更があると分かっているで
メタクラスなら無条件にインスタンス生成は
クラスからじゃなくメタクラスで行うと決めていればいい。
メタクラスは設計と言うレベルじゃなく実装できるが、DIは設計しないと。
>>503
>さすがにもういいや。
助かる。
>>505
”通訳”しないと分からない時点で...
まぁ俺には関係ないが。
>>506
>OCPやLSPやDIPは知ってるのにDI知らんて
OCPやLSPやDIP知ってると認めてくれるのか、有難い。
ただメタクラスをDIと言われてもピントこないしな。
(DIをメタレベルとか普通に使っているのか?)
0508デフォルトの名無しさん
2011/03/12(土) 21:55:33.85DIで実装してもいいが、それは変更があると分かっているときで
メタクラス実装なら無条件に、インスタンス生成はクラスではなく
メタクラスで行うと決めていればいい。
メタクラスは設計と言うレベルじゃなく規則レベルで実装できるが
DIは設計がともなう。
0509デフォルトの名無しさん
2011/03/13(日) 00:06:31.14> メタクラスは設計と言うレベルじゃなく規則レベルで実装できるが
これって一つ間違えるとクラスシステム全体が………
に, なっちゃわね?
clos/mopとかつついてる, と時々,
何やってるんだ? >俺
に, なるんだが………
0510デフォルトの名無しさん
2011/03/13(日) 21:07:46.77まともに話して通じるとは思えない。DIコンテナなんか何一つ使ったことないんだろう。
OCPに固執するのは会社のルールで明文化されてるのかな
0511デフォルトの名無しさん
2011/03/13(日) 21:10:26.40文脈的に別の意味と思うのは難しいな
0512デフォルトの名無しさん
2011/03/13(日) 22:44:51.97低いレベルだな、がっかりだよ。
>さすがにもういいや。
なんだろう、もう相手しなくていいから。
0513デフォルトの名無しさん
2011/03/15(火) 04:18:57.560514デフォルトの名無しさん
2011/03/15(火) 13:14:25.190515デフォルトの名無しさん
2011/03/15(火) 15:49:10.75http://ja.wikipedia.org/wiki/DI
無い。
>>514
>>497の例で言えばServiceAを継承して1メソッドの動作を変えたServiceA'を
作成してClientBは無修正に適用できる。こんなことは自動ユニットテストで
当たり前のように行われてること。でも>>491の例にあるShape#rotate()を
追加するようなときはClientB側も変更範囲なのは当たり前の話で
こういうのは変更の連鎖といわない。連鎖はたとえばServiceAのメソッド引数に
パラメータを追加して、挙動に変更のないクラスまで修正を強要すること。
0516デフォルトの名無しさん
2011/03/15(火) 18:58:16.02それはもっともだが、>>431の言う既存クラスにメソッドを追加してはいけない理由はそもそも
「既存クラスにメソッドを追加する際に既存クラスの他のメンバの動作を変えてしまうかもしれないから」
だ。テストすればいいというなら既存クラスにメソッドを追加すること自体は何の問題も無いよね。
メソッド一個追加するのを避けてクラスごと差し替えるなんて本末転倒じゃん。
0517デフォルトの名無しさん
2011/03/15(火) 20:41:13.92既存のソース部分はそのまま使うので全然本末転倒ではない。
テストすればいいっていう話はOCP守ってそんな見通しの悪い
クラス構成でメンテしていくより綺麗にリファクタリング、つまり元のクラスに手を入れちゃって
それが仕様通りであることをテストで保証すればいいってことじゃないかな。
実際にはUnitTestですべてまかなえる訳じゃないし理想論に過ぎないかもだけど、
見通しのいいソースを維持できる。OCPを守ることが義務づけられでもしていない限り
OCPにこだわってわかりにくいソースをメンテし続ける方が高コスト。
今後のメンテ回数がすくなければOCPの方がいいケースもあるかもしれない。
0518デフォルトの名無しさん
2011/03/15(火) 21:18:21.02アクセスしないのであれば、クラスの外に静的メソッドとして作ればいいわけだから
当然プライベートメンバへのアクセスが必要なケースということだよな?
そこはどうするの? 最初から全部公開しておく?
0519デフォルトの名無しさん
2011/03/15(火) 22:08:02.07既存ソースを変更しないルールに沿うならprivateメンバーに依存するようなメソッドは全部オーバーライドしないといけない。
そもそもOCPにこだわるのが時代遅れ。
0520デフォルトの名無しさん
2011/03/15(火) 22:57:38.04ポリモするのもそりゃいいさ。case書きまくるのにくらべ段違いにいいさ。
でも、クラス階層が不用意に、アンバランスに育っていく気持ち悪さってないぞ。
そうなるくらいなら、クリクリッとした、よく設計された使いやすいクラスが、
フラットな場所にコロコロ転がってるほうが使いやすい。
不用意な継承も、protectedもいらない。
使わない!として無理したほうがキレイな糞がひねりだせそう。
継承してOCP♪、protected使って継承迎合♪ 糞が軟便になってしまう。
0521デフォルトの名無しさん
2011/03/16(水) 19:14:12.65使う積極的な理由がないなら、極力使わないほうがいい。
0522デフォルトの名無しさん
2011/03/16(水) 23:37:30.39共通処理をスーパークラスにおくのは愚の骨頂
0523デフォルトの名無しさん
2011/03/16(水) 23:39:53.15既存クラスを使用するクライアントに影響を与えないようにするためのもの
既存クラスを使用するクライアントが無いのなら
OCPにこだわるメリットはあまりなさそう。というか思いつかない
0524デフォルトの名無しさん
2011/03/19(土) 10:34:02.84「相談」がしにくい雰囲気だよね。
0525デフォルトの名無しさん
2011/03/19(土) 19:31:00.100526デフォルトの名無しさん
2011/03/19(土) 22:53:03.800527デフォルトの名無しさん
2011/03/20(日) 07:48:22.66内容がどうであれあんな態度を取られたら空気も悪くなるさ
0528デフォルトの名無しさん
2011/04/23(土) 16:58:06.01そもそも設計間違ってます?
0529デフォルトの名無しさん
2011/04/23(土) 20:51:03.98委譲元の一部の情報がほしいだけなら引数オブジェクト使うとかでもいいけど
委譲元そのものを知りたいなら相互参照するしかないしね
0530デフォルトの名無しさん
2011/04/23(土) 21:13:17.59フォームがボタンのクラスに依存するしボタンのインスタンスを参照する
ボタンはフォームのクラスには依存しないけどフォームのインスタンスを参照する
0531デフォルトの名無しさん
2011/04/23(土) 23:22:11.83一対一でやれてるかぎりはまだ平気。
0532デフォルトの名無しさん
2011/04/25(月) 08:08:55.65ありがとうございます。
0533デフォルトの名無しさん
2011/04/25(月) 08:59:12.400534デフォルトの名無しさん
2011/04/25(月) 11:26:30.58利用側(委譲先)がコンポーネント(委譲元)を参照するのは自然なこと
0535デフォルトの名無しさん
2011/04/25(月) 12:24:18.160536デフォルトの名無しさん
2011/04/25(月) 13:56:58.83deleteがめんどくさいんだ
0537デフォルトの名無しさん
2011/04/25(月) 14:09:01.29委譲メソッド追加するのもメンドクサイし継承がいいかもしれない・・・
0538デフォルトの名無しさん
2011/04/27(水) 01:31:44.86東の民族→東夷
西の民族→西戎
南の民族→南蛮
北の民族→北狄
東夷族なんて”族”は無い、あるのは大和民族や朝鮮民族などの民族。
これだと漢民族と4つの民族しかいないことになる。
それに、たしか韓国の主張だと朝鮮民族は文化の遅れているえびす(夷)には入らないと言っていたが
自分達をえびす(夷)だと認めるのか?
0539デフォルトの名無しさん
2011/04/27(水) 01:33:37.82誤爆です。orz
0540デフォルトの名無しさん
2011/05/23(月) 01:36:03.20と考えてそれを半分くらい作ったところで、
他の箇所からちょっと飛行機臨時便飛ばすことにしたから、
なんかあったら乗っけていいよ、みたいな手はずになってしまい、
そっちを通すようにしてたら、飛行機の着陸する空港が臭くなってしまい、
ちょっとまてよ、ちょっと飛行機やめよう、ターミナルバスも、滑走路も、
全部ひっこめよう、となって、そういえば、と元のど真ん中の道を思い出し、
そっちを開通させてみると、なんと見通しのいい頼れる一本道であったことか。
ということってよくある。
0541デフォルトの名無しさん
2011/05/28(土) 14:10:36.35多くの場合、ってほど多いとも思わないが…
普通は相互参照しないなあ。
0542デフォルトの名無しさん
2011/05/29(日) 19:05:36.700543デフォルトの名無しさん
2011/06/09(木) 22:22:30.07クラスの相互依存と混同してないか?
普通にobserverやるとたいがい結果的に相互参照になるぞ
Javaや.NETなどのようにGUIのイベントにobserverが使われる場合
コンポーネントからのイベントを受け取ろうとするたびに確実に相互参照が増える
0544デフォルトの名無しさん
2011/06/10(金) 07:22:57.770545デフォルトの名無しさん
2011/06/10(金) 12:18:09.19Observerを相互参照というのもピントがズレている。
0546デフォルトの名無しさん
2011/06/11(土) 01:47:05.52シンプルで少数精鋭の時はそれでいいけど人数多くて開発者のレベルもマチマチだと駄目だ。
トランザクションスクリプト派に乗り換えよう。趣味のプログラムだけ頑張ろう。
0547デフォルトの名無しさん
2011/06/23(木) 23:06:14.04どのレベルまで行うか?個人的な基準があれば聞きたい。
あと、レベルの低い回答は無視するから。
0548デフォルトの名無しさん
2011/06/28(火) 13:57:31.170549デフォルトの名無しさん
2011/06/28(火) 15:23:15.89自分の作ったクラスの何パーセントくらい再利用してる?
俺は10%位のような気がする。
0551デフォルトの名無しさん
2011/06/28(火) 23:24:05.130552デフォルトの名無しさん
2011/06/29(水) 02:16:16.48http://ja.wikipedia.org/wiki/%E9%96%8B%E6%94%BE/%E9%96%89%E9%8E%96%E5%8E%9F%E5%89%87
見てみたら、メイヤーの定義とそれ以降の定義と大きく2つあるんですね。
メイヤーの定義って、昔々再利用が叫ばれてた頃のモジュール化思想と何が違うんでしょう…?
べつに継承、とかオブジェクト指向、とかが文脈に登場する必要が無いような。
0553547
2011/06/29(水) 13:28:33.55それは構造化的な汎用化を言ってないか?
構造化の汎用化は、共通処理のモジュールを作り再利用するが
OOの汎用化は操作を”汎用”化する。
例えば(オブジェクトが相手のオブジェクトにメッセージを送る)
運転手(オブジェクト) → ハンドルを右(メッセージ) → 乗り物(オブジェクト)
乗り物が車オブジェクトなら、タイヤを右にする。
乗り物が船オブジェクトなら、舵を右にする。
乗り物が飛行機オブジェクトなら、尾翼を右にする。
こんな風に、メッセージを統一するのがOOの汎用化。
使われるモジュールを統一するのが構造化的汎用化で
使うほうが統一したメッセージを送るのがOO的汎用化。
0554551
2011/06/29(水) 13:35:27.53実装レイヤーよりもうちょっと上の話か。難しいな。
リアルで会話してると抽象的な会話は誤動作や副作用を生みやすいが、まー、いったん実装すればそれでいいからなー。
ふむ〜。
0555デフォルトの名無しさん
2011/06/29(水) 14:00:53.52関数呼び出し?
0556デフォルトの名無しさん
2011/06/29(水) 19:31:58.90OO以外だと元のソースに手を入れないで拡張するのが難しい
ソースをコピーするっつー方法もあるけど、後々地獄を見るのは確実
0557デフォルトの名無しさん
2011/06/29(水) 20:40:21.25概念を言うと、メッセージってのは、オブジェクトに与える指示の事。
オブジェクトはメッセージを受け取ると、対応するメソッドを実行する。
C++の系譜を汲む言語は、ほぼメッセージの概念が消失してて、
直接メソッドを呼んでる感じになってる。
今メッセージを意識できるのはダックタイプだな。
ダックタイプは明確なメッセージ実装のひとつだ。
あと、Windowsのウィンドウメッセージの仕組みもOOPの
メッセージに由来している。
0558デフォルトの名無しさん
2011/06/30(木) 01:00:44.68大抵完全抽象化クラスを使えば済むし、大体それが正しい場合が多い。
なんせ実装継承したら、親クラスの実装を交換する術がない。
protectedが使える、templateメタプログラミングができるってのは、
別にオブジェクトとして重要じゃないし。
実装継承がどうしても必要なケースってどんな状況かねぇ。
0559547
2011/06/30(木) 10:49:08.55>どのレベルまで行うか?個人的な基準があれば聞きたい。
もう少し具体的な例を書いてみる。
例えば、
>>558 >なんせ実装継承したら、親クラスの実装を交換する術がない。
OO技術者なら分かると思うがいくらでも親クラスの実装を変える方法はある。
例えばBrigteパターンで実装ロジックの分離できるし
メッセージも極端な例ではInterpreterパターンを使えば何でも送れる。
しかし、全てのクラスをこのように作るのは抽象化しすぎで、いわゆる「抽象化中毒」だ。
OOである以上抽象化は必須だと思うが、「抽象化中毒」もよくない。
個人的なバランスの取り方を聞きたい。
(これが完全な正解と言う答えはないと思っているから、個人の意見を聞きたい)
0560デフォルトの名無しさん
2011/07/01(金) 01:02:05.84BrigteってBridgeパターンの事?
まぁ、それはいいとして、わざわざBridgeの為に親を実装継承して何に使うの?
必然性がなくてあんまり効果無くねって思う。
例えば、こういう感じのコード。
BinalyArray pixelArray = new ColorArray();
Screen screen = new DrawingScreen();
BinalyWritable adapter = new ScreenAdapter(screen);
pixelArray.WriteTo(adapter);
DrawableAdapterはBinalyWritableの完全抽象化クラスを実装しているだけで、
ColorArrayとは直接接点がない。DrawaingScreenは、Screenを実装してるだけで、
Adapterとは直接接点がない。ましてや、ColorArrayは一切関係がない。
こういう作りにしておくとColorArrayとDrawingScreenのような全く関係ない
クラス同士を結び付けられるようになるじゃん。
で仮に、Bridgeなんかを使うと、少なくともBinalyWritableとその直系はScreenに依存するようになる。
例のコードだと依存してるのはScreenAdapterっていういかにも使い捨てなクラスだけなんだけどね。
そう思うとやっぱりわざわざBridgeまでして親用意しても邪魔なだけじゃねって思う。
まぁ、あなたのおっしゃる「抽象化中毒」なんでしょうけどね。
0561デフォルトの名無しさん
2011/07/01(金) 13:03:27.00間違えたすまない。
0562デフォルトの名無しさん
2011/07/02(土) 23:37:05.08まぁ、たしかにそりゃそうなんだけど、元を辿るとオーバーライドできないからって事なんだよな。
そこに言及した話がない。
int getUnitCost()
{
return Math.parseInt(arguments["unit.count"]);
}
public int unitCount;みたいに親クラスで公開されてると↑みたいなコードに
オーバーライドできん。なぜプロパティが許されるかってのもそこなんだよな。
※ただ個人的にgetter/setterは糞だと思ってる。
0563天使 ◆uL5esZLBSE
2011/07/03(日) 00:39:52.37∨∨∨∨∨∨
>>>>>>>>>>>>> 実装レイヤーよりもうちょっと上の話か。難しいな。 <<<<<<<<<<<<<(キリッッッッ!!!!きリッ!!
∧∧∧∧∧∧∧(キリッ!キリ
∨∨∨∨∨∨∨∨∨
>>>>>>>>>>>>>> リアルで会話してると抽象的な会話は誤動作や副作用を生みやすいが、まー、いったん実装すればそれでいいからなー。 <<<<<<<<<<<<<<(キリッッッきリッッッッッ!!!!
∧∧∧∧(キリ!
ゴミ量産機
0564天使 ◆uL5esZLBSE
2011/07/03(日) 10:58:16.550565デフォルトの名無しさん
2011/07/03(日) 19:54:31.14>オーバーライドできないから
違うよ
抽象メンバやインターフェイスメンバとして宣言されたオーバーライド前提のものならともかく、
オーバーライドされることが想定されてないアクセサを正しくオーバーライドするなんてまず無理
できたとしてもスーパークラスの実装にべったり依存した形になるからカプセル化を破ることになる
0566デフォルトの名無しさん
2011/07/03(日) 20:09:34.66スーパークラスはどうしても拡張が必要だとか余程のことがない限り使わないようにする。
別にスーパークラスが存在しても構わないけど、基本的にインターフェースに束縛して使用する。
0567デフォルトの名無しさん
2011/07/03(日) 20:19:05.01直接オーバーライドせず>>560みたいにすればいい。
0568デフォルトの名無しさん
2011/07/03(日) 20:51:48.30それが徹底できるなら理想かもしれないが、問題はインターフェイスで宣言するかどうかじゃなくて、
クラスを実装するときにプロパティがオーバーライドされる可能性を想定しているかどうかだよ。
>>562のようにスーパークラスのgetUnitCostを呼び出さないオーバーライドを許すなら、
当然スーパークラス内でgetUnitCostの後ろのフィールドには直接アクセスしてはいけないし
スーパークラスで前提としてるgetUnitCostの細かい振る舞いについて仕様を決めなきゃいけない場合もある。
ですべてのプロパティについてそこまで考えてるのかって話
0569デフォルトの名無しさん
2011/07/03(日) 21:13:59.03>>562書いたの俺だけど、あれはインターフェースのオーバーライド前提に書いたよ。
スーパークラスはオーバーライドしづらいから、初めから継承する事を前提にしてないよ。
0570デフォルトの名無しさん
2011/07/04(月) 00:26:30.38オーバーライドされることを想定していなくて非抽象なプロパティも一般的には多く使われてるのは事実なんだから
アクセサ使う目的を一般的に説明するなら、やっぱりあとで実装を変えられるようにするためでしょ。
多態使うのは元を辿ると実装を変えたいからだと言うならわかるが、逆は不自然じゃないか?
0571デフォルトの名無しさん
2011/07/04(月) 00:55:39.43あと、すごく個人的な意見だけど getter/setter とプロパティは嫌い。正直意味ないと思う。
もともとIDEでGUIの値を簡単に変えられるようにした枠組みだもん。
Delphi、VB、Java beanとね。JavaやC++に長らくプロパティが存在しなかった原因は、
ホンというとSmalltalkで確立したオブジェクト指向に反してるからだと思う。
例えば、
interface RGB
{
void change(double red,double green,double blue);
void change(int rgb);
void to(RGB rgb);
}
っていうインターフェース用意しておけば、相互でchange呼び出せば済む話だし。
0572デフォルトの名無しさん
2011/07/04(月) 09:34:16.87Javaなんかはまだ可愛げがあるが、
C#でプロパティ用意しちゃってるあたりで、
もうたまらない。インタフェースというより、
構造体的に扱う事を強いてる。
設計段階で悪いほうに導いてるように見える。
0573デフォルトの名無しさん
2011/07/04(月) 09:49:51.410574デフォルトの名無しさん
2011/07/04(月) 20:47:47.11プロパティは.NET Frameworkに不可欠な概念なんだからそこに文句を付けるのはナンセンス
0575デフォルトの名無しさん
2011/07/04(月) 20:59:41.22非常に頻繁に利用され、決まりきってて、有効性もわかってるパターンは
言語に組み込んで統一するっていうのは当然の進化だろう
何を言おうが「現実に使われてる」わけで、バラバラに各自のルールでやってるよりはずっとマシ
0576デフォルトの名無しさん
2011/07/04(月) 21:36:14.05プロパティはイヤ、プロパティ嫌い、と繰り返しててワロタw
0577デフォルトの名無しさん
2011/07/04(月) 22:04:56.46interface RGB
{
void change(double red,double green,double blue);
void change(int rgb);
RGB to(RGB rgb);//引数で取ったオブジェクトが帰る。
}
こういうインターフェース面白いよね。
void change(RGB source)
{
RGB fillter = source;
fillter = fillter.To( new NegativePositive() );//ネガポジ
fillter = fillter.To( new Edge(0.9) );//強調
fillter = fillter.To( new Sepia() );//セピア
fillter.To( this.color ); //最終結果をメンバーへ
}
フィルター化して幾らでも機能を拡張できる。
アクセサ中心でこういうの書こうとするとホント汚くなる。
■ このスレッドは過去ログ倉庫に格納されています