トップページ⇒tech
1001コメント438KB

-OOP限定-プログラム設計相談室

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2005/09/24(土) 16:35:59
全部publicでいいじゃん!ってならないようにするスレです。
0438デフォルトの名無しさん2011/03/02(水) 18:50:00.49
>親・子クラス関係なく多態で扱いたい。
>既存動作に影響しないけど、それを証明するのは?
>既存処理に影響が出ないかたちでスーパークラスのメソッド(多態)として使いたい。

単体テストをしっかり書いてからリファクタリング
クラス設計だけじゃ無理だと思うよ
0439デフォルトの名無しさん2011/03/02(水) 19:25:03.69
>たしかに既存動作に影響しないけど、それを証明するのは?
そんなことを言い出したらOCPの教義である多態を使って拡張したとしても同じことだろ
どっちみちテストは必要
0440デフォルトの名無しさん2011/03/02(水) 19:51:23.39
>その理由は? たまに継承を使うなと言う人がいるけど納得出来る理由を聞いたことがない。
最初からクラスを継承禁止にしておけば君の心配は全て解決するじゃん。これ以上わかりやすい理由はない。
継承を許している以上、新たにサブクラスが追加されることによって既存のコードが動かなくなる可能性は
常に存在する。
0441デフォルトの名無しさん2011/03/02(水) 21:56:09.01
>>438
>単体テストをしっかり書いてからリファクタリング
>クラス設計だけじゃ無理だと思うよ
余計なテストをしなくて済む為のOCPだと思うけど。

>>439
>どっちみちテストは必要
余計なテストをしなくて済む為のOCPだと思うけど。

>>440
>継承を許している以上、新たにサブクラスが追加されることによって既存のコードが動かなくなる可能性は常に存在する。
既存コードに影響が無い作りをする為のOCPでしょう。
それに、サブクラスが追加しても親クラスには何ら影響はないでしょう。(あるなら教えて欲しい)


俺が聞きたいのは、OCPを適用したら既存部分はまったく影響ないけど
既存コードを修正したい場合があるから、OCPが崩れる。
その影響を最小限にするクラス設計をみんなどうしているのか?を聞きたい。
0442デフォルトの名無しさん2011/03/02(水) 22:03:48.05
ここまでOCP,OCP言う人初めて見たわ。俺、そこまで深く考えてないわ。
0443デフォルトの名無しさん2011/03/02(水) 22:29:11.28
>余計なテストをしなくて済む為のOCPだと思うけど。
変更時に既存動作に影響がないか確認するためのテストファーストです。
リファクタリングしようがしまいがテストは書かなきゃ駄目。
余計なテストなんてものはない

>影響を最小限にするクラス設計をどうしているのか?
だから>>438
0444デフォルトの名無しさん2011/03/02(水) 22:51:01.38
メソッドを追加するだけなら、影響が及ぶのはそのクラスだけ。
でも、サブクラスが増えると、それが混ざる可能性のある場所全てが誤動作する可能性がある。
程度問題だが、そういう見方も可能。
0445デフォルトの名無しさん2011/03/02(水) 23:14:23.18
正しくOCPを守れていれば>>444のような問題は起こらないよ。
それが「修正に対して閉じている」ということだから。
でも、それをどうやって証明する? 結局テストするしかないじゃないかw
0446デフォルトの名無しさん2011/03/03(木) 02:03:12.57
>>442
>ここまでOCP,OCP言う人初めて見たわ。俺、そこまで深く考えてないわ。
んっ? 質問だけど、クラス設計の時は何を目指してやっているの?
例えばデザインパターンを使って設計していても根底にはOCPがあると思うけど。

>>443
>変更時に既存動作に影響がないか確認する
OCPは変更(修正)しては駄目と言う原則だけど。
機能追加する部分はテストファーストやTDDでやってもいいけど、質問している事と違うだが...

>>444
>でも、サブクラスが増えると、それが混ざる可能性のある場所全てが誤動作する可能性がある。
「サブクラスが増える」と「それが混ざる」 何が混ざると?影響が混ざると言うこと?

>>445
>でも、それをどうやって証明する? 結局テストするしかないじゃないかw
機能追加だけ行えば既存機能は影響がないと思うけど。

言語にもよるけど、継承元クラスのコードが無くても(バイナリで提供)
継承したクラスを作ることが出来る言語もある。
親クラスをバイナリ・レベルで提供だから、動作には変更が無いことを証明していると思うけど。
04474422011/03/03(木) 08:06:53.95
>>446
>んっ? 質問だけど、クラス設計の時は何を目指してやっているの?
普通に>>432とか>>433とか。OCPは単なる原則であって規制だという認識じゃないんで、
OCPを守る為に設計、OCPはテストをしなくて済む為のもの、とかまで拡大解釈してない。
0448デフォルトの名無しさん2011/03/03(木) 09:30:51.37
サブクラスが混ざるというのは、例えばスーパークラスのインスタンス
を受ける既存メソッドの引数に、新しいサブクラスのインスタンスを渡すこと。
それによってそのメソッドが正しく動作しないケースは実際にある。
LSPって知ってる?
0449デフォルトの名無しさん2011/03/03(木) 13:38:08.79
>>447
それは手法であって、目的や目標がじゃない気がする。
設計に目的や目標は、いらないと考えている?

>>448
Liskovは知っているけど、それを守る為のOCPでしょう。
機能追加はもちろんテストしないといけないけど
それ以外に影響を出さない為のOCPで
LSPはモジュールを置き換えたときに適切な動作しないといけないと言うだけで
当たり前の事を言っているだけ(だから原則なのかもしれないけど)
そのことは、今回来ていない。

何か話しが噛み合わないな...
0450デフォルトの名無しさん2011/03/03(木) 13:41:26.47
設計の目的…だと…?
0451デフォルトの名無しさん2011/03/03(木) 15:10:04.82
だからLSPが守れていることはどうやって証明するの?
なんでその証明は不要なのに、既存クラスにメソッドを追加したときに
その既存クラスの動作に影響を与えないことの証明は必要なの?
04524512011/03/03(木) 15:38:42.43
伝わらなそうなので整理
431が主張する「サブクラスが追加されても既存のコードは正しく動作する」はLSPが大前提なわけ。
でもそれって自明なことじゃないでしょ? やってみないとわからない。
サブクラスの実装に問題が無くても、既存のコードが暗に既存サブクラスの細かい仕様外の動作を前提にしてしまっていて
それがサブクラスを追加することで明るみに出るかもしれない。
それって、既存クラスにメソッドを追加することのリスクと本質的に何が違うの?
0453デフォルトの名無しさん2011/03/03(木) 17:34:25.32
>>450
普通OODだと、変更に強い設計にするとか再利用しやすい設計とか。

>>451,452
>だからLSPが守れていることはどうやって証明するの?
機能追加にLSPは関係ないと思う。、
修正なら使っているクライアントにLSPを保障しないといけないけど
機能追加は、その時点で誰も使っていないから「置換」は発生しない。
431の例で誰に対するLSPを証明するの? LSPは関係ないと思うけど。

>サブクラスの実装に問題が無くても、既存のコードが暗に既存サブクラスの細かい仕様外の動作を前提にしてしまっていて
もし前提にしてたとしても、それはその時点で実装されているメソッドに対してでしょう?
新しく実装されるメソッドを前提にクラスが作られているとは思えない。
0454デフォルトの名無しさん2011/03/03(木) 18:58:27.53
>>437
>機能追加する部分はテストファーストやTDDでやってもいいけど、質問している事と違うだが...

じゃあ確認するけど
>既存クラスに機能追加した時に、OCPを守った上で一番良い方法は?
>みなさんはメソッド追加を見越して、どのようなクラス設計をしていますか?
>既存の動いているシステムに機能追加する場合を想定している。
>OCPではそれも含めて修正は禁止していると思っているんだが。
>既存処理に影響が出ないかたちでスーパークラスのメソッド(多態)として使いたい。
これでいいよね?

メソッドの追加はOCP違反なんでしょ?
だから、既存部分の動作が変わっていないか確認するためにテストを書いたら、と言ってるんだよ
OCPを守っていればテストが不要というわけじゃないけどね

>何か話しが噛み合わないな...
OCPはこうあるべきという原則であって、守っていれば既存の動作が変更されないということを
保証する技術じゃないよ。かみ合わない原因はこれ
0455デフォルトの名無しさん2011/03/03(木) 22:49:19.89
いや、設計方針を聞いているのにテストと言われても。
0456デフォルトの名無しさん2011/03/03(木) 23:12:07.54
>>455
失礼、アンカーが抜けてた
>>438
>クラス設計だけじゃ無理だと思うよ
0457デフォルトの名無しさん2011/03/04(金) 01:46:33.11
>>441
「余計」ちゅーのがそもそも間違い
0458デフォルトの名無しさん2011/03/04(金) 10:41:27.59
ふと「置換」とか曖昧な概念で議論せずにDbCの(事前|不変|事後)条件(*)を使ってよとか思って
>機能追加にLSPは関係ない
に対して考えてみたけど

機能追加を最小単位のメソッド追加まで分割したとき、
その機能追加で追加されるあるメソッドfの事後条件が他のメソッドgの事後条件でも言及されている識別子vを含むとき
(例:fの事後条件にv=aが、gの事後条件にv=bが含まれる)
vを利用している式eの(*)に影響しこの式eを含むメソッドhの(*)が変化する
hがクラスBを基底とする派生クラスCのメソッドでありBにそのインタフェースであるh'があるとき
この変化の前後でhの事後条件がh'のそれより弱められてしまった場合またはhの事前条件がh'のそれより強められてしまった場合
LSPは満たされなくなる

とかいう文章が浮かんできて
うん、やっぱ使わなくていいやという結果になった
0459デフォルトの名無しさん2011/03/04(金) 14:11:25.75
なぜ、こんなに話が噛み合わないかな...

まず第一点目として、OCPを守っていれば既存コードには影響ないと思っている。
>OCPはこうあるべきという原則であって、守っていれば既存の動作が変更されないということを
>保証する技術じゃないよ。かみ合わない原因はこれ
マルチスレッドとかで動いているとか無い限りOCPを守れば既存機能は保障される。

次に第二点目として、OCPを守っていれば単体テストの範囲は追加機能分だけ
余計な単体テストは不要になる、その為にもOCPを守って作った方がいい。

俺の質問を言い換えれば、テストなどをどうすれば簡略化出来るか?
と言う質問にもなるのに、それを「テストをしなさい」と言われても...

話が噛み合わないのでこの質問はこれで終了します、レス有難うございました。
0460デフォルトの名無しさん2011/03/04(金) 17:55:34.05
話が噛み合わないのは、>>459はOCPが守られていることを前提にしているから。
機能追加に伴って顕在化するようなバグや設計上の問題が
既存コードには全く存在しないことを仮定している。
それに対して、他の人はその前提がおかしいと言っている。
そういうことを前提にしていいのであれば、カプセル化の原則が厳密に守られていることを前提にすれば
メソッドを既存クラスに追加しようが全く問題ないことになるよね。
0461デフォルトの名無しさん2011/03/04(金) 18:20:06.72
>>459
>なぜ、こんなに話が噛み合わないかな...
なぜ噛み合わないのか?それは聞いた場所が悪いんじゃないのか。
OCPやカプセル化すら理解出来ていない奴に聞いてもしょうがないだろう。

ここじゃなく知恵袋で聞いて来い。
あっちは一瞬で京大の問題まで解いてくれるから、まともな答えが返ってくるぞw
0462デフォルトの名無しさん2011/03/04(金) 18:42:07.42
>>459
もう何度もいってるし460もいってるけど前提が間違ってる
OCPは動作が変更されないことを保証しない。

追加したメソッドがメンバ変数(あるいはグローバル変数)に干渉していて
既存メソッドが正常に動作する前提を崩している可能性がある。
これはスーパークラスに追加した場合でも継承してサブクラスに
追加(君の言うOCPを適用)した場合でもかわらないし、追加メソッドのテストだけでは確認できない。

別に反論してくれなくてもいいけど、反論するなら
>OCPを守っていれば既存コードには影響ないと思っている。
みたいな感想ではなく、根拠をしめしてね

ついでに、勘違いしてる人と定義論争したくないから今まで黙ってたけど
君のOCPの定義は間違ってるよ
>OCPは変更(修正)しては駄目と言う原則
とか
>OCPを守っていれば単体テストの範囲は追加機能分だけ
>余計な単体テストは不要になる
とかはメイヤーさんが聞いたら泡吹いて卒倒するレベルだからよそでは言わないほうがいいよ
こっちは反論を受け付けません。ちゃんとしりたかったらメイヤーのオブジェクト指向入門読んでね
0463デフォルトの名無しさん2011/03/04(金) 22:56:26.20
Strategyパターンなどで機能を追加したときに既存クラスの不適切な実装のせいでうまく動作しなかったら
それは結果としてOCPを破ってる(正しく開かれてない)と言うこともできるんじゃないの?
どっちにしろ彼は既存コードが拡張に対して絶対に正しく動作するという理想的な状況を仮定しているわけだから
そんなものを作れる完璧超人が既存クラスにたかがメソッド一個追加するときに
誤って既存メンバの動作を変えてしまうようなヘマをするとは思えないけども
0464デフォルトの名無しさん2011/03/05(土) 13:07:00.87
>>461
他の所で聞いてもいいけど、別に正解だけを聞きたいだけじゃないからな。
正解は複数あると思うし、その環境にベストな答えは自分で考えないといけないと思っている。

>>462
君は間違っている。
逆に聞くが、何の言語を使っているか知らないが、言語に標準や共通ライブラリーが実装されていると思うが
その標準ライブラリーのクラスから継承してクラスを作った場合に、君は標準ライブラリーのクラスまで単体テストしているのか?
もっと言えば、その標準ライブラリークラスのまた親など全ての親クラスに対して単体テストをしているのか?

>追加したメソッドがメンバ変数(あるいはグローバル変数)に干渉していて
>既存メソッドが正常に動作する前提を崩している可能性がある。
OCPの理解がまったく出来ていない、フィールドに既存メソッドが想定していない値が入るようになった場合
そのメソッドは継承して処理するのがOCPだから、既存メソッドの処理は変えないし単体テストをする必要もない。

>とかはメイヤーさんが聞いたら泡吹いて卒倒するレベルだからよそでは言わないほうがいいよ
メイヤーと言うなら、形式手法は知っているのか? メイヤーの考えを正しく理解したいなら
そのあたりから勉強しろ。

>>463
>どっちにしろ彼は既存コードが拡張に対して絶対に正しく動作するという理想的な状況を仮定しているわけだから
上でも書いたけど、正しく動作しないメソッドが有った場合は、そのメソッドを継承する。
それがOCPだと思うけど。それと知っていると思うがOCPはバグなら修正を認めている。

>Strategyパターンなどで機能を追加したときに既存クラスの不適切な実装のせいでうまく動作しなかったら
元の話に戻るけど「Strategyパターンなどで機能を追加」は考えてみたけど
その場合に、今度を機能追加や継承が多いと「デメテルの法則はどうなるのか?」と考えてしまう。
でも基本的には「Strategyパターン」で実装するのが一番最適な正解だとは思うど
そのあたりの、参照や依存関係が複雑化するのはどう考えるか聞きたい?
0465デフォルトの名無しさん2011/03/05(土) 13:52:01.89
>フィールドに既存メソッドが想定していない値が入るようになった場合そのメソッドは継承して処理する (*)

基底メソッドが想定していない値を派生先のメソッドで処理するということは
派生先メソッドの事前事後条件が派生元のそれより弱いということになる
これは派生クラスの事後条件が基底クラスより弱くなってはいけないという意味のLSPに反する

形式手法というかDbCに対してはOCPよかLSPの方が相性いいなと思った
OCPは拡張とか修正とかいう曖昧な概念をどうやって論理に翻訳すればいいかわからない
できることを増やすという意味の拡張ならとりあえず全体としてはより弱い事後条件になり
より安全にという意味の修正では事前条件が弱くつまり緩和されるわけか?

ただ計算機による支援なしでまともにDbCとか使えるわきゃねぇから
(*)のやり方そのものが問題になることは殆んどないだろうな
0466デフォルトの名無しさん2011/03/05(土) 16:00:56.66
>フィールドに既存メソッドが想定していない値が入るようになった
カプセル化も破ってるな
絶対に既存クラスが修正されないなら勝手だが、
標準ライブラリのような外部のパブリックなAPIを使うケースを引き合いに出すなら不適切だろ
0467デフォルトの名無しさん2011/03/05(土) 19:28:07.27
だんだんOCP関係なくなってきた感じがするなー
長くなったので二分割

>>464
>標準ライブラリーのクラスから継承してクラスを作った場合
自分が作ったクラスならテストしてるよ。
勘違いしてるみたいなんで訂正するけど、既存メソッドといってたのは
サブクラスを経由している既存メソッドという意味ね。親クラスまではテストしない。

>OCPの理解がまったく出来ていない、フィールドに既存メソッドが想定していない値が入るようになった場合
>そのメソッドは継承して処理するのがOCPだから、既存メソッドの処理は変えないし単体テストをする必要もない。
過去の発言をそのままお返します。

>なるほど、たしかに既存動作に影響しないけど、それを証明するのは?
0468デフォルトの名無しさん2011/03/05(土) 19:30:55.32
後半
>既存コードに影響が無い作りをする為のOCPでしょう。
>OCPを守れば既存機能は保障される
>メソッドは継承して処理するのがOCPだから
よくこんな感じの発言するけど、OCPはただの原則。

「モジュールは開いていると同時に閉じているべきである」 これだけ

サブクラスを作ってスーパークラスに手を加えないのも
Strategyパターンあたりを使って機能を追加するのも
OCPを実現する手法・技術ではあるけどOCPそのものじゃない。
その手法・技術も単独では既存動作を保証しない。テストが必要だというのはこういう理由。

なぞの技術OCPを使えば既存動作は保証されるというわけじゃないんだよ。

>メイヤーと言うなら
確かにメイヤーのくだりは要らなかったな。大人気ない煽りだった。申し訳ない。
主張は変えないけどね

>君は間違っている。
根拠を書いてね
0469デフォルトの名無しさん2011/03/08(火) 00:41:03.78
>>465
>派生先メソッドの事前事後条件が派生元のそれより弱いということになる
>これは派生クラスの事後条件が基底クラスより弱くなってはいけないという意味のLSPに反する
反論じゃないが事前条件が弱くなるのは許されている、事後条件が弱くなるのはOCPにも違反している。

>形式手法というかDbCに対してはOCPよかLSPの方が相性いいなと思った
LSPが具体的な原則で、OCPはもっと広い意味での原則でLSPも含んでいる。
クライアントが相手の型を意識させた場合、それはクローズしていない事になる。
まっ認識の差だけで、多分考えている方向性は同じだと思う。

>>466
論外の意見だな。

>>467
>サブクラスを経由している既存メソッドという意味ね。親クラスまではテストしない。
意味が分からん 462の
>追加(君の言うOCPを適用)した場合でもかわらないし、追加メソッドのテストだけでは確認できない。
「親クラスまではテストしない」「追加メソッドのテストだけでは確認できない」は何のテストを行うのか?
これが相手に伝わる文章だと思うっているのか?

>過去の発言をそのままお返します。
本当にOCPを理解しているのか? >既存クラスにメソッドを追加してはいけないというのがまずおかしいでしょ
既存クラスにメソッドを追加するのがOCPだとでも思っているのか? 
OCPは既存クラスを修正しては駄目だと言うことだ。

>「モジュールは開いていると同時に閉じているべきである」 これだけ
そんな認識だから駄目なんだろう、修正に対して閉鎖していて、機能追加に対して開放されていると言うことだ。

まったく、まともなレスをくれるのは>>465ぐらいしかいない。
0470デフォルトの名無しさん2011/03/08(火) 07:27:34.50
メソッドの追加自体は修正とちがうんでない?
追加したメソッドが既存のメソッドの動作を変更しうる場合が修正?
動作を変更しないことを証明するのは難しいから追加も修正とみなして禁止?
よくわからん
0471デフォルトの名無しさん2011/03/08(火) 08:08:21.46
wikipediaの開放/閉鎖原則の頁に参考資料として「和訳 The Open-Closed Principle
(開放-閉鎖原則)」というPDFがあるから、>>431(と分かってなさそうなその他数名)は
読んどけよ
相当やさしく書かれているから、これで理解できなければ救いようがないわ
0472デフォルトの名無しさん2011/03/08(火) 11:36:59.45
>>470
>動作を変更しないことを証明するのは難しい
そういうことでしょ
特に、修正は原則として既存クラスのメンバをオーバーライドして動作を変更する
(つまりカプセル化を破る)ことで行うというポリシーが前提なので
細かい動作の変更が大きな影響を及ぼす恐れがある
そのポリシーの是非は今は問題にしていない
0473デフォルトの名無しさん2011/03/08(火) 20:35:02.43
>>469
>何のテストを行うのか?
サブクラスがスーパークラスから継承しているメソッド(非オーバーライドも含め)

ほかにもいろいろあるけどもういいや
OCPを適用した場合に省くことできる「余計なテスト」の例とその根拠だけ解説してくれ
あればweb上で参照できるソースも
0474デフォルトの名無しさん2011/03/08(火) 20:37:00.95
>>470
>メソッドの追加自体は修正とちがうんでない?
クラス単位で見た場合に修正となる。

>動作を変更しないことを証明するのは難しいから追加も修正とみなして禁止?
追加を修正とみなして禁止ではない、実際メソッドの修正なら元のソースを修正するが
追加なら元のソースは無くても出来る。(言語にもよるが)
大雑把に言えば現在のソースに直接手を入れるのが修正。

>>471
なぜ自分の意見で書かない自信がないのか?
>open-closed principle を満たすプログラムでは新しいコードを追加するだけで機能を追加すること
>になるので、既存のコードを変更することはありません。ですから、この原則を満たさないプログラム
>で見受けられるような変更の連鎖を経験することもないのです。
「変更の連鎖を経験することもない」この意味が分かるか?
OCPを守っていれば、「変更の連鎖がない」つまり親クラスに影響を与えないと言うことだ。

>>472
>特に、修正は原則として既存クラスのメンバをオーバーライドして動作を変更する
>(つまりカプセル化を破る)ことで行うというポリシーが前提なので
「オーバーライドして動作を変更する」オーバーライドしたら、それは修正じゃないだろう。

0475デフォルトの名無しさん2011/03/08(火) 23:27:35.37
CLOSを使ってみたら、オブジェクトがメソッドを抱え込んでることが疑問に思えてきたんだけど、
あんたら的にはどう思う?
04764712011/03/08(火) 23:43:52.62
>>474
お前は誰と戦ってんだよ?
俺はOCPを誤って理解してる馬鹿がいたから分かりやすい文書を教えてやっただけのこと
くだらん煽りはいいから早く続きを読め
まだ途中までしか読んでないんだろ?

お前が引用した箇所のすぐ下、「戦略的閉鎖」まで読めば誤りに気がつくだろ
(普通はもっと早く気がつくだろうけど)
俺はこのPDFほど優しく教えられないからな、素直に読んでくれることを望むよ
0477デフォルトの名無しさん2011/03/09(水) 00:11:38.05
>>473
>open-closed principle を満たすプログラムでは新しいコードを追加するだけで機能を追加すること
>になるので、既存のコードを変更することはありません。ですから、この原則を満たさないプログラム
>で見受けられるような変更の連鎖を経験することもないのです。
下にも書いたこれでいいか、影響範囲が特定出来れば「余計なテスト」はいらない。

>>475
俺は知らない。

>>476
まったく、メイヤーを読めとかマーチンを読めとかお前が読めよ。
理解出来ていないのは、お前だから早く気づけ。
自分の言葉で説明出来ない黙っていろよ。


今日は、まともなに話が出来る人間はいなかったな。
04784712011/03/09(水) 01:13:47.95
>>477
462は別人。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
>>478
ようやく自分の意見を書いたのか。

最初に書いて置くが、同じ文章をよんでも知識や経験で理解する内容は違う。
同じ人間でも今日読んで理解した内容と、数年後に読んで理解した内容は違うだろう。
それに、なぜその文章で議論しないといけない? 
>相当やさしく書かれているから、これで理解できなければ救いようがないわ
明らかに主観で薦めているものを前提にしている、客観性がゼロだ。
まっ、しかしマーチンを選択したのは良いと思うが。(ただし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は運用が始まった後のことだ。

まったく、俺の聞いたことの入り口すら理解出来ないのか?
04814712011/03/09(水) 21:26:35.22
>>479

> それとメタクラスを理解出来ているのか?「メタクラスで追加なんてその典型」なぜ”追加”と言う言葉を使う?
431は機能追加についての話だったからその意味で"追加"と書いたがおかしかったか?
この話でメタクラスが出てくること自体がおかしい(ついでにNullオブジェクトの方も
意味不明)が、お前が具体的にどういう方法を考えているのかなんて知らない。
もしかしたら俺がものすごく勘違いをしているのかもしれないな。
それなら本末転倒といったのは先走りすぎたかも知れない。

> 「実装はもはや固定ではなく、複数の実装が存在可能となり、互いにポリモーフィックに入れ替える」
> この入れ替えを、メタクラスで行おうとする話だが、なにが「本末転倒な話」なのか詳細に説明してくれるか?
しかし、これをよんでも相変わらず意味不明。
とにかく憶測で話をしても埒があかないから、メタクラスでの方法の正当性を主張したいなら
Shapeの例などで具体的に>>431を説明してくれ。
04824712011/03/09(水) 21:27:14.66
>>480

> 次にこれだ、「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、全てのメソッドをオーバーライド可能にしておいてカプセル化を壊すかしかない
04854712011/03/09(水) 23:55:34.50
>>483,484
それと同じことを直前で書いたつもりなんだけどなw
やっぱ俺の説明が下手くそなんだろうな
0486デフォルトの名無しさん2011/03/10(木) 00:47:36.69
>>481,482
見事に話が噛み合っていない。全部に対応するのは疲れるから本筋のところだけ書く。
(メタクラスやNULLオブジェクトは自分で勉強してくれ)
>じゃあ「Listing 2」の段階で運用が始まり、その後描画順序というルールを導入する必要が
>でてきたとしたら?同じことだろう?
だから書いたんだ。同じ物を読んでも同じ認識にはならないと、それなのにお前はただ読めと、まったく...

本題にはいるが、マーチンが書きたかったのは運用に入る前の設計方法で
俺が聞いているのは運用後の設計方法、まったく違う。
運用前の設計では、マーチンが書いているようにOCPを適用しやすく設計方法で
運用後はOCPをいかに守るべきかの設計方法を聞いている。

>お前は注意深く設計されたクラスは全てに対し完全にOCPが適用され、完全に閉鎖されている
>という前提で話をしているからおかしいの
またそうやって決め付ける。自分の認識が間違っているとは思わないのか?
書いた本人の俺が違うと言っている認識についてどう思うんだ?

>>483
その通り、理解できる人がいると嬉しい。
そこが入り口で、その場合にどう設計すれば良いのかを聞きたかったんだが、その入り口にもなかなか立てない...

>>484
>そんなもん最初から想定してないと無理だろ
なぜ無理だと決め付ける?
>追加したい操作にもよるだろうが、究極的には最初からクラス間の依存関係を全てインターフェイスで扱うか
>全てのフィールドはprotected、全てのメソッドをオーバーライド可能にしておいてカプセル化を壊すかしかない
なるほど、それを気にして今までカプセル化が崩れると言っていたのか、納得した。
だが自分でも「インターフェイスで扱う」とか解決策を考えているじゃないか?「フィールドはprotected」もgetter/setterを書けば良い事だし。
まっ、それでも「最初からある程度は想定していないと」と考えるのは分かる、だから俺もメタクラスと書いた。
(メタクラスならクラスごと入れ替える訳だし、想定しなくてもなんとかなる場合が多い)
0487デフォルトの名無しさん2011/03/10(木) 00:48:18.95
>>485
>それと同じことを直前で書いたつもりなんだけどなw
>やっぱ俺の説明が下手くそなんだろうな
説明が下手じゃなく書いている内容が違うんだろう? 

>お前は注意深く設計されたクラスは全てに対し完全にOCPが適用され、完全に閉鎖されている
>という前提で話をしているからおかしいの
> 新しい図形の操作の追加に関しては閉じていない。
> 431は後者のときに、既存クラスに手を入れずに対処する方法を質問したのではないかと思う。
が同じ? 「完全に閉鎖されている」と「追加に関しては閉じていない」が同じだと? 駄目だ俺には正しく読み取れない。
0488デフォルトの名無しさん2011/03/10(木) 01:34:29.39
堂々めぐりだからもういいよ
メタクラスによる機能追加というのは具体的にどうやるつもりなのか示してくれ
04894712011/03/10(木) 01:35:05.87
>>486
> (メタクラスやNULLオブジェクトは自分で勉強してくれ)
俺はNullオブジェクトというと書籍の『リファクタリング』などに載っているものを想像
するんだけど、>>431はどうもそれとは違うようだから勉強しようにもできないんだ。
それからメタクラスによって>>431を解決する方法は431自身しか知らないよな?
だったら勉強しようがないだろ。
繰り返すが、自分の正当性を示したいのなら具体的に説明しろ。
できないならちゃんと認めろ馬鹿が。

> 本題にはいるが、マーチンが書きたかったのは運用に入る前の設計方法で
> 俺が聞いているのは運用後の設計方法、まったく違う。
ではそのマーチンなら運用後の設計方法はどうすると思う?そんなの本人しか分からない?
確かにそうだけどおかしいとは思わないか?
OCPは20年以上前からあり、>>431のような疑問も当然現れてくるはず。なのに運用後
のことは何も言及されていないということになる。
マーチンだけじゃない。OCPに関してはたびたび目にするが>>431のような質問は俺は見た
ことも聞いたこともない。ここで初めて目にした。
もし既にあるというのなら教えて欲しい(そして何故そこでの解決法で満足せずここで
質問したのかということも)。

最後に一つ答えて欲しい。お前は>>480の最後で
> まったく、俺の聞いたことの入り口すら理解出来ないのか?
と書いているが、お前は天才で、20年以上にわたり誰も考えつかなかった>>431の解決策を
世界で初めて考え出し、それを理解できない多くの凡人の方がおかしいということか?
ここで「はいそうです」と答えてくれると嬉しいね。話が噛み合わない原因がはっきり
するから。
0490デフォルトの名無しさん2011/03/10(木) 08:21:07.60
>>484
それってまんまSmalltalkとかRubyの事だな

ところで、メタクラスという言葉はクラスのクラスの事を指してるんだよな
なんでクラスを入れ替えるとか機能追加とかそういう話になるんだ?
もしかしてこの認識がなんか間違ってるのか
0491デフォルトの名無しさん2011/03/10(木) 09:56:55.73
Shapeインターフェースにdraw()メソッドがあって、TriangleやCircleなどの
具象クラスがそれを実装してるとする。draw()の他にrotate()を追加したいとする。
OCPに従うならRotatableShapeインターフェースを新規作成して
RotatableTriangle等の具象クラスを作成する。でも仕様変更ですべての具象クラスが
Rotatableになる必要があるならリファクタリングしてShapeに手を入れた方がいい。
OCPはOOPの基本的な原則であって、予測してなかった仕様変更に対してまで
頑なに守るようなルールじゃないし、あらかじめShapeにメソッドが追加されることを
前提にしたところでShapeの設計は変わらない。

>たまに継承を使うなと言う人がいるけど
継承を使うなは論外だと思うけど、継承より委譲が大原則。理由はより疎結合になるから。
サブルーチン的な発想で共通機能をベースクラスに押し込んで継承するのは間違いなんだけど
割とやりがち。Shapeの例だとそれぞれのインスタンスをファイルに保存することが出来たとして、
AbstractShapeクラスを作ってそこにsave()メソッドを実装して継承するのは駄目で、
ShapeSaverクラスを作ってそっちに委譲する、というイメージ。

0492デフォルトの名無しさん2011/03/10(木) 10:02:07.87
フィールドのgetter/setterを書くって矛盾してるぞ
絶対に変更しないんだろ? だったらフィールドをそのまま公開してるのと同じだ
0493デフォルトの名無しさん2011/03/10(木) 20:16:53.89
OCPは設計時に達成すべき目標を示したものであって、
インタフェースを用いるというのはその実現手段のひとつでしかない。
もし操作が追加されると予測されるなら、switch〜case方式にする手もあるし、
操作の共通インタフェースを導入するという手もある。
メタクラスを使ってクラスごと入れ替えるというのも、
乱暴だが、選択肢のひとつではあるだろう。
0494デフォルトの名無しさん2011/03/10(木) 20:29:07.49
クラス入れ替えるって
既存クラスのソースファイルをビルドから除外して
かわりに別のファイルに差し替えるのとどう違うの?
0495デフォルトの名無しさん2011/03/10(木) 21:41:21.34
>>493
switch〜case方式に戻してどうすんだよ
OOPにおけるOCPは「いかにswitch文を除去するか?」が最重要テーマと言っても良いくらいなのに
OCPが分からないなら黙っておいた方がいいよ
04964312011/03/11(金) 02:04:56.19
個別に対応は神経的に疲れて良くないから、質問をもう少し具体的に書いて整理してみる。

共通モジュールServiceAクラスがあり
それがClientBクラスなどいろいろな箇所で使われている。
ClientBクラスはServiceAクラスをコンポジション(委譲)して使っている。
なので、ClientBクラスはServiceAクラスのインスタンス生成・破棄を管理している。

ある日仕様変更があり、ServiceAクラスに新機能を追加することになった。
現在使用しているクライアントにも、新仕様を適用したクラスを使用させたい。

この場合、修正のやり方として一番簡単なのはServiceAクラスを直接修正。
新しいメソッドを追加する、しかしこれではServiceAクラスがOCP違反になる。

次にServiceAクラスを継承して修正した場合、ServiceAクラスはOCPを満たすが
ClientBクラスなど修正が必要になりOCP違反になる。

では、ServiceAクラス・ClientBクラスともに継承して修正すれば良いのではと考えるが
しかしこれも「依存するモジュールに変更が連鎖して広がっている」のでOCP違反。
04974312011/03/11(金) 02:05:38.53
つづき

では、なぜ変更の連鎖が起きるのか?
ClientBクラスとServiceAクラスとの関係がDIP違反だから起きている。
ClientBクラスがServiceAクラスをコンポジションしているから
ClientBクラスが上位(高次)モジュールなのに
ServiceAクラスと言う下位モジュールの具象クラスに依存している。

DIPを守るには、上位と下位の繋がりを抽象化すればいい。
これを解決するには一つの方法は、クラスを抽象化(メタクラス)すればいい。

ここでメタクラスを簡単に説明すると、普通クラスからインスタンスを作成する。
これがメタクラスだと、クラス(オブジェクトじゃなく型自体)を入れる変数を想像してくれ
その変数を使ってインスタンスが作れる、変数だからいろいろなクラスが設定出来る
インスタンスを作る方では、実際にどのクラスからインスタンスが作られたのか分からない。
つまり、クラスが抽象化される。
0498デフォルトの名無しさん2011/03/11(金) 08:47:31.92
メタクラス関係無いじゃん
0499デフォルトの名無しさん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
>>498
なぜ関係がないと思うんだ? まっ一つの方法でしかないが。

>>499
>だったら最初からそう言えよ
>で、DIによって実装クラスを入れ替えるのが
最初から言っている、具体例にしただけだ。
ところで、DIって何だ? わからないんだが。

>>500
>いまいち理解出来んが
簡単に書いたつもりだが...


しかし、東北から関東まで大変そうだな。
0502デフォルトの名無しさん2011/03/11(金) 22:18:31.68
DI = Dependency Injection
>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
502だが、>431と>496は同じこと書いてると思うよ。
既存クラスには絶対手を入れない、という方針の是非はともかく。

>496の例ならDIですむが、設計時に予測していないような修正だったら
メタレベルでクラス間のつながりを変更するしかないかもしれん。
なんかもっと難しそうな例はないのか? >496
0505デフォルトの名無しさん2011/03/12(土) 12:51:07.48
>>504
じゃあ通訳して
特に431の方
0506デフォルトの名無しさん2011/03/12(土) 13:13:33.62
OCPやLSPやDIPは知ってるのにDI知らんて
どういう勉強したらそんなことになるのか
0507デフォルトの名無しさん2011/03/12(土) 21:50:59.26
>>502,504
>メタレベルでクラス間のつながりを変更するしかないかもしれん。
なるほど、だから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.85
間違えた。

DIで実装してもいいが、それは変更があると分かっているときで
メタクラス実装なら無条件に、インスタンス生成はクラスではなく
メタクラスで行うと決めていればいい。
メタクラスは設計と言うレベルじゃなく規則レベルで実装できるが
DIは設計がともなう。
0509デフォルトの名無しさん2011/03/13(日) 00:06:31.14
>>508
> メタクラスは設計と言うレベルじゃなく規則レベルで実装できるが
これって一つ間違えるとクラスシステム全体が………
に, なっちゃわね?
clos/mopとかつついてる, と時々,
何やってるんだ? >俺
に, なるんだが………
0510デフォルトの名無しさん2011/03/13(日) 21:07:46.77
OOPのスレでDIを「文脈的に別の意味と思った」とか言い訳する時点で
まともに話して通じるとは思えない。DIコンテナなんか何一つ使ったことないんだろう。
OCPに固執するのは会社のルールで明文化されてるのかな
0511デフォルトの名無しさん2011/03/13(日) 21:10:26.40
>>497に対するレスでDIと書かれているのを
文脈的に別の意味と思うのは難しいな
0512デフォルトの名無しさん2011/03/13(日) 22:44:51.97
>>510,511
低いレベルだな、がっかりだよ。

>さすがにもういいや。
なんだろう、もう相手しなくていいから。
0513デフォルトの名無しさん2011/03/15(火) 04:18:57.56
略称がDIで意味の違う単語てOOP的に他になにがあるかな?
0514デフォルトの名無しさん2011/03/15(火) 13:14:25.19
クラスを差し替えるなんてそれこそ既存コードを破壊する大修正だと思うが
0515デフォルトの名無しさん2011/03/15(火) 15:49:10.75
>>513
http://ja.wikipedia.org/wiki/DI
無い。

>>514
>>497の例で言えばServiceAを継承して1メソッドの動作を変えたServiceA'を
作成してClientBは無修正に適用できる。こんなことは自動ユニットテストで
当たり前のように行われてること。でも>>491の例にあるShape#rotate()を
追加するようなときはClientB側も変更範囲なのは当たり前の話で
こういうのは変更の連鎖といわない。連鎖はたとえばServiceAのメソッド引数に
パラメータを追加して、挙動に変更のないクラスまで修正を強要すること。
0516デフォルトの名無しさん2011/03/15(火) 18:58:16.02
>>515
それはもっともだが、>>431の言う既存クラスにメソッドを追加してはいけない理由はそもそも
「既存クラスにメソッドを追加する際に既存クラスの他のメンバの動作を変えてしまうかもしれないから」
だ。テストすればいいというなら既存クラスにメソッドを追加すること自体は何の問題も無いよね。
メソッド一個追加するのを避けてクラスごと差し替えるなんて本末転倒じゃん。
0517デフォルトの名無しさん2011/03/15(火) 20:41:13.92
差し替えるのは元のクラスを継承して1メソッド変更したものに置き換えるだけ。
既存のソース部分はそのまま使うので全然本末転倒ではない。

テストすればいいっていう話はOCP守ってそんな見通しの悪い
クラス構成でメンテしていくより綺麗にリファクタリング、つまり元のクラスに手を入れちゃって
それが仕様通りであることをテストで保証すればいいってことじゃないかな。
実際にはUnitTestですべてまかなえる訳じゃないし理想論に過ぎないかもだけど、
見通しのいいソースを維持できる。OCPを守ることが義務づけられでもしていない限り
OCPにこだわってわかりにくいソースをメンテし続ける方が高コスト。
今後のメンテ回数がすくなければOCPの方がいいケースもあるかもしれない。
0518デフォルトの名無しさん2011/03/15(火) 21:18:21.02
継承によって追加するメソッドは、既存スーパークラスのプライベートなメンバにアクセスしないの?
アクセスしないのであれば、クラスの外に静的メソッドとして作ればいいわけだから
当然プライベートメンバへのアクセスが必要なケースということだよな?
そこはどうするの? 最初から全部公開しておく?
0519デフォルトの名無しさん2011/03/15(火) 22:08:02.07
あらかじめ全部protectedなアクセッサを用意しておくという解もあるかもしれないけど、普通はしないよね。
既存ソースを変更しないルールに沿うならprivateメンバーに依存するようなメソッドは全部オーバーライドしないといけない。
そもそもOCPにこだわるのが時代遅れ。
0520デフォルトの名無しさん2011/03/15(火) 22:57:38.04
OCPのための継承は、そこを設計の目的としちゃいけない気がする。
ポリモするのもそりゃいいさ。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はエンバグを防ぐというよりも
既存クラスを使用するクライアントに影響を与えないようにするためのもの

既存クラスを使用するクライアントが無いのなら
OCPにこだわるメリットはあまりなさそう。というか思いつかない
0524デフォルトの名無しさん2011/03/19(土) 10:34:02.84
なんかOCPがどうのこうの言い出してから、
「相談」がしにくい雰囲気だよね。
0525デフォルトの名無しさん2011/03/19(土) 19:31:00.10
kigarunisoudansitekudasai
0526デフォルトの名無しさん2011/03/19(土) 22:53:03.80
OOスレが消化されて、そっちの面子がこっちに移ってきてるんだろう。
0527デフォルトの名無しさん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
observer使ったGUIのイベント処理なんかだと確実に相互参照になるよ(間接的な場合もある)
フォームがボタンのクラスに依存するしボタンのインスタンスを参照する
ボタンはフォームのクラスには依存しないけどフォームのインスタンスを参照する
0531デフォルトの名無しさん2011/04/23(土) 23:22:11.83
もっと俯瞰で見て、多対多の参照が見えてくると問題。
一対一でやれてるかぎりはまだ平気。
0532デフォルトの名無しさん2011/04/25(月) 08:08:55.65
>>529-531
ありがとうございます。
0533デフォルトの名無しさん2011/04/25(月) 08:59:12.40
http://homepage3.nifty.com/satoshis/oo/memo.html#dependency
0534デフォルトの名無しさん2011/04/25(月) 11:26:30.58
委譲って多くの場合相互参照じゃね?
利用側(委譲先)がコンポーネント(委譲元)を参照するのは自然なこと
0535デフォルトの名無しさん2011/04/25(月) 12:24:18.16
C++だとポインタの管理めんどくさいんですよ
0536デフォルトの名無しさん2011/04/25(月) 13:56:58.83
ポインタはめんどくさくない
deleteがめんどくさいんだ
0537デフォルトの名無しさん2011/04/25(月) 14:09:01.29
あとダングイングポインタですかね、
委譲メソッド追加するのもメンドクサイし継承がいいかもしれない・・・
■ このスレッドは過去ログ倉庫に格納されています