-OOP限定-プログラム設計相談室
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2005/09/24(土) 16:35:590377デフォルトの名無しさん
2010/09/29(水) 08:11:02スクリプト書いて対処したりとか、プログラムの美しさを損なうやつ。
0378デフォルトの名無しさん
2010/09/29(水) 08:41:110379デフォルトの名無しさん
2010/09/29(水) 13:58:19WEBプログラムのクライアントサイドこそバッドノウハウの宝庫だな。
あとはJavaのVMごとにあるバグの回避で実装変えたりとかな。
0380デフォルトの名無しさん
2010/09/29(水) 14:24:03>JavaのVMごとにあるバグの回避で実装変えたり
したことないなあ。どんなのあった?JVMにバグがある場合は
アップデートで乗り切ってるなウチは。tomcatのHttpSession#getSessionId()で
バージョンによってセッション切れの時の挙動が違って回避プログラム書いたけど
まさにバッドノウハウだよね。OOとも何の関係もない
0381デフォルトの名無しさん
2010/09/29(水) 14:39:42でも8年くらい前の話だ。
0382デフォルトの名無しさん
2010/10/10(日) 00:44:37例えば運動方程式を解いて物体の運動を視覚的に表示するプログラムを考えます。
DirectXやOpenGLのようなものは使わず、普通のウィンドウシステムの上で動かすとします。
このとき、フレームレートとか画面の大きさというような情報は誰が持つべきなのでしょうか?
Mがフレームレートの情報を持って、自分からイベントループにコールバックを登録する構造なら、
物体が自律的に運動するさまを自然に表現できますが、
反面、Mがウィンドウシステムに依存することになり、何か変な感じもします。
逆にこれをCが持つとすれば、Mは位置と運動量と時刻くらいしか持たないことになり、
ちょっとMの仕事が少なすぎる気がします。
画面の大きさに関しては、常識的にはVの領分でしょうが、現在の位置に加えて軌跡も表示したい場合、
どこかに画面と同じ大きさのビットマップを持つ必要が出てきます。これはMにあたるでしょう。
0383デフォルトの名無しさん
2010/10/10(日) 20:10:55つか、ビットマップはVだろ…
いや軌跡をビットマップにプロットするモデルと、ビットマップを表示するビューに分ける、
とか考えられなくもないけど、そこまでするほどの例題とも思えない。
0384デフォルトの名無しさん
2010/10/10(日) 23:48:35Mに持たせるインターフェイスのデザインをどうするか、どんなものが好ましいのかにもよりますが、
VCペアが問い合わせてくる、ある時刻での物体の正確な位置を返す仕事であれば、Mの責務です。
0385デフォルトの名無しさん
2010/10/11(月) 00:08:48モデル側にあるってことは、交換可能な全てのモデルに位置を画像で返す機能をつけることになるが…。
数値だけ返して、画像への描画は別の部分が担当するのではまずいの?
0386デフォルトの名無しさん
2010/10/11(月) 00:32:40ウィンドウサイズなどの情報を抽象化するMを設ける
0387デフォルトの名無しさん
2010/10/11(月) 02:16:400388デフォルトの名無しさん
2010/10/11(月) 10:22:43Model(M)からは、軌跡の集まりを返すだけにし、その表現はPresentation Model(PM)から返すようにするってのは?
V <-- PM <-- M
PMが不要なプロパティを表示する時は、単に無視するか、透過的に扱うようにする。
0389382
2010/10/12(火) 21:36:29軌跡が初等関数で書けるようなものであれば係数を求めて渡すだけですが、
そうでない場合、まさか全ての時刻での座標を覚えておくわけにもいきませんから、
ビットマップを埋めることで軌跡を「求める」ことになるでしょう。
もっと極端な例では、マンデルブロ集合のモデルは必然的に解像度の情報を持つことになります。
0390デフォルトの名無しさん
2010/10/12(火) 21:38:480391デフォルトの名無しさん
2010/10/13(水) 00:57:24> まさか全ての時刻での座標を覚えておくわけにもいきませんから、
むしろ、保持しておいた方がいいと思うけどね。
オンメモりに乗らないくらいの巨大データなら、ファイルなり、DBなりに保存(キャッシュ)する。
または、間引いて保持する。
また、適当な間隔で間引かれたサンプリングデータをもとに、
オンデマンドで表示領域分のデータを計算すれば、全領域を保持する必要はなくなると思うよ。
この辺は、OOPとは関係ない実装の泥臭い部分になるけど。
0392デフォルトの名無しさん
2010/10/13(水) 10:06:32ビットマップの方がメモり喰うのわかってないの?
MVCのVがモニタだろうがプリンタだろうがMは影響を受けないように作るべきで、
どんなサイズでどういう風に表示するかはVが決める。表示内容はMだけど
見た目はVが決める。ビットマップで持ったらVで見た目決められないし
0393デフォルトの名無しさん
2010/10/13(水) 19:39:58全ての座標とは、軌跡上の全ての座標を保持するという意味で書いたんだ。
軌跡以外の点までは保持する必要はないってことね。
例えば、放物線なら、放物線上の点の集まりのみを保持する。
うまく伝えられなくてゴメンね。
0394デフォルトの名無しさん
2010/10/13(水) 19:50:14座標とは、UI上の座標ではなく、ある時刻の計算値のことね。
運動方程式なら、パラメーターを設定すれば、(時刻, X, Y, Z)の集合が計算できるので、その値を保持。
表示する際は、範囲と倍率を考慮して、UI座標に座標変換する。
0395デフォルトの名無しさん
2010/10/14(木) 07:37:500396デフォルトの名無しさん
2010/10/14(木) 11:17:130397デフォルトの名無しさん
2010/10/14(木) 23:04:15最終的に1034x768のbmpに納めればいい情報ならshortのx,yの2点でいいし、
bmpで持つくらいなら1024x768のbooleanの配列で持った方がまだマシ。
同じだけの情報記録できてサイズが小さくてデータが利用しやすいから。
Viewの実装がなんだろうとModelのビジネスロジックは変わらない、
それがMVC。Mの時点で最終表示系を決めたらVの仕事はなんだよw
0398デフォルトの名無しさん
2010/10/14(木) 23:11:25扱いが面倒で記憶域の無駄遣い
0399デフォルトの名無しさん
2010/10/15(金) 13:40:38おまえは何を言っているんだ?w
0400デフォルトの名無しさん
2010/10/15(金) 20:28:50要求がはっきりしないけど、例えば同じ座標を通った回数を区別する必要がある場合はどうする?
その必要がないとしても、boolean使ったからってそれほど節約にはならないよ。1バイトなんだから。
そもそも、軌跡を描画するなら普通に考えてビットマップに描いていくのが効率がいいので
内部で二重にバッファ持つ意味がない
0401デフォルトの名無しさん
2010/10/15(金) 20:59:43UIで、スケール変更して、拡大表示するときは、どうするの?
ビットマップから切り出して、拡大表示させる?
ジャギーでるよ。
その都度、再計算させる?
再計算のコストが高かったら?
レスポンス悪くなるよ。
軌跡の計算結果をもつことは、メモリ効率を悪くしてるかもしれないけど、
最悪、拡大時は補間してレスポンスの悪化を防ぐことも一応可能よ。
ビットマップもジャギー出さずに、補間して拡大するアルゴリズムあるのかな?
0402デフォルトの名無しさん
2010/10/15(金) 21:06:28ビットマップである以上拡大すればジャギはでる。
あきらめろ。
レスポンス問題は昨今なら別スレッドを使用すれば、
そこそこ隠蔽できるだろ。
GPU使えるならそっちを使えばよいとおもうけどな。
つかぜんぜんOOPと関係ねえからやめろ。
0403デフォルトの名無しさん
2010/10/15(金) 21:16:34曲線上の点を選択して、その値を調べたいときは、どうするの?
ビットマップに落とし込んだ時点で丸められてるから、
正確な値取れないよ。
その程度なら、再計算すればいいっていわれそうだけど、
運動方程式(微分方程式)の解が漸化式になつてしまったら、単純にその値だけ再計算できないよね?
0404400
2010/10/15(金) 21:23:01軌跡を描画に使うだけならビットマップで十分な場合は多いだろうし
ちゃんとしたシミュレーションで軌跡のデータが必要ならそのまま保持しといたほうがいいだろうし
要件がわからないのに議論しても仕方ない。
0405デフォルトの名無しさん
2010/10/16(土) 01:03:29おかしいって事だよ。なんで主題と関係ないトコで広げてるんだ?
0406デフォルトの名無しさん
2010/10/18(月) 20:53:230407デフォルトの名無しさん
2010/10/19(火) 09:17:23だがMでビットマップを作ることがMVCらしくない事には変わりない。
このスレでOOPとしてあるべき姿の話をするのか、効率を含めた妥協点を
探る話をするのかと言えば前者だろ。
0408デフォルトの名無しさん
2010/10/19(火) 11:30:41VはVRAMに表示する為に決められたフォーマットのデータを。
CにはMを展開してVに適用する手続きを。
おれはこう考えたが・・・。
0409デフォルトの名無しさん
2010/10/19(火) 18:40:340410デフォルトの名無しさん
2010/10/19(火) 19:37:110411デフォルトの名無しさん
2010/10/20(水) 00:29:450412デフォルトの名無しさん
2010/10/20(水) 09:05:570413デフォルトの名無しさん
2010/12/08(水) 02:00:510414デフォルトの名無しさん
2010/12/08(水) 16:48:17経験がないとセンスがあっても難しい。
センスがなければ経験があっても応用は難しい。
0415デフォルトの名無しさん
2010/12/09(木) 19:29:05一人で悩んでも良いけど情報収集は必要。
要件の分析や、他人の解説や設計を読んだりして新しい視点が見つかることも多い。
一人で設計ばかりしていると思考の堂々巡りに陥ることがあるのが辛い。
そんなときは、実際に作ってみたり、誰かに話してみると改善点が見つかったりする。
大規模なものは知らないけど、一人で設計やってるものとしては、こんな感じ。
0416デフォルトの名無しさん
2010/12/09(木) 23:25:57とりあえず作ってみるってのはいいですね。
だぶったっていいわけだし
0417デフォルトの名無しさん
2011/01/15(土) 00:38:50保険商品ってあるカテゴリで共通してる属性があったり、
その商品単独でしか持ち得ないような属性もあったりします。
Javaではinterfaceで共通部分を定義して、abstractで一般的な値を設定、
特有の属性や例外的な処理はそれぞれ具象クラスでってパターンにしようと思っていますが、
この保険商品をDBのテーブルで表す際にどうするか悩んでいます。
1.1つの「保険商品」テーブルに入れてしまう。joken1、joken2みたいなカラムで固有属性をカバーする
→ 明らかにおかしい
2.商品ごとにテーブルを分ける。
→ 数が多くなりすぎる。保険商品一覧を取りたい時に大変。
3.共通部分のテーブルと固有部分のテーブルで分ける
→ joinが多発する(5〜8テーブル位)。商品固有テーブルだけでも10テーブル位作らなきゃだめそう。
個人的には3しかないかなと思っていますが、何かいい案はありますでしょうか。
ちなみに会社の人間は1を勧めてきました。
0418デフォルトの名無しさん
2011/01/15(土) 12:17:401の派生型だけど、固有属性の多い商品が増えたからといってDDL変えることもないし
エンティティクラスのアクセッサでその属性を管理してあげればいいだけだから簡単。
固有属性が結構複雑で属性名も大事だったりするなら「固有属性テーブル」を一つだけつくって
保険商品ID、属性名、属性値の3カラム構成、PKは保険商品ID+属性名。
エンティティクラスではMap<属性名, 属性値>という型で固有属性マップを持つ。
このどちらでも属性tのget/setのために具象クラスにわける必要ないよ。
計算式とか含むなら分けた方がいいけど
0419デフォルトの名無しさん
2011/01/15(土) 14:47:27RDB?とJava(オブジェクト指向)のデータの持ち方で悩んでいる?
それなら「O/Rマッピング」の製品や書籍があるからそちらを参考にしてみては。
基本は製品を買ったほうが工数も掛からないし信用性もあるからいいと思いますけど
なかなか製品購入を許してくれる会社も少ないからな...
ここからは個人の意見で(何がベストなのかは環境によっても違うと思うので)
>2.商品ごとにテーブルを分ける。
これがいいと思う、データは会社の経営資源(リソース)だけどシステムは道具に過ぎない。
データは正しい構造(正規化)でもっていなければならない。道具に合わせたデータ構造は間違ってと思う。
>→ 数が多くなりすぎる。保険商品一覧を取りたい時に大変。
viewやプロシージャでも作っておけば?データに関してはDBMSに任せるのも手だと思う。
俺的にやっぱりベストなやり方は、RDBは正しく正規化で作り、システムも正しくオブジェクト指向で作り
「O/Rマッピング」の製品を買って繋ぎ合わせるのが一番だと思う。
0420417
2011/01/18(火) 00:17:36>>418
>保険商品ID、属性名、属性値の3カラム構成、PKは保険商品ID+属性名。
>エンティティクラスではMap<属性名, 属性値>という型で固有属性マップを持つ。
なるほど、こうすれば雑多な項目を格納できそうですね。
属性名(属性ID)を外部キーとして属性マスタを作れば正規化も満足できそうです。
そういえば以前に関わった案件ではこのやり方でした。
>>419
「Javaでは…」のせいで質問のポイントを不明瞭にしてしまいました。
すみません。蛇足でした。
>2.商品ごとにテーブルを分ける。
>これがいいと思う、データは会社の経営資源(リソース)だけどシステムは道具に過ぎない。
うーん、そうですね。それは正しいように思います。
テーブル数が相当数になりますが、だからといって、
それを少なく管理しようとする試みも、また合目的的ではなさそうです。
もちろん、結果的に少なくなったというのであれば、それは歓迎すべきでしょうが…。
0421デフォルトの名無しさん
2011/01/18(火) 10:37:46商品名、担当部署とか共通の項目が多いのであれば商品毎のテーブルは
OO的にも正しくないと思うよ。固有属性専用テーブルはいわゆるサマリ-詳細テーブルの
関係だからよくある形じゃないかな
0422デフォルトの名無しさん
2011/02/06(日) 00:17:07例えばWindowクラスのOS別実装するときどうしますか?
ソース互換にするためには
Window w = new Window();
ってやりたいんですが、Windowの実装はWin32Window、LinuxWindowとか
別クラスで実装するのが普通なんでしょうか
この場合Windowをインターフェースにして
Window w = new Win32Window();とかになるんでしょうか
でもこうするとソース互換なくなるしWin32Windowを後悔しちゃうとOS依存の内部実装が見えてしまうので
良くないですよね?普通はこういう場合どう設計するんでしょうか
0423デフォルトの名無しさん
2011/02/06(日) 00:47:26その中で、環境別にWin32WindowなりLinuxWindowなりをnewして返す。
0424デフォルトの名無しさん
2011/02/06(日) 01:53:38C#のGraphics.FromImageみたいなものですか・・なるほど・・
0425デフォルトの名無しさん
2011/02/06(日) 01:56:24>Window w = new Win32Window();とかになるんでしょうか
そこでDIですよ
0426デフォルトの名無しさん
2011/02/06(日) 01:57:280427デフォルトの名無しさん
2011/02/06(日) 12:52:31デザパタ本にまんまあるな。
0428デフォルトの名無しさん
2011/02/09(水) 16:24:43ヒープが少々必要な事と Cでのコーディングは少々手間が掛かるが完成後のメンテは楽チン
0429デフォルトの名無しさん
2011/02/16(水) 13:23:490430デフォルトの名無しさん
2011/02/20(日) 11:39:01.75メンテと新規機能の追加は楽です
ARMとdsPIC専門で16KB以上のSRAMがあるマイコンの場合に限定して採用していますが
ヒューマンインターフェースが入るファームウェアはPCアプリ感覚が生きてきますので
今までより開発スピードと質がワンランク上がりました
RTOSが必要無くなったのは 必然的にイベントベースになり クラス間が
スタティックカップリングからダイナミックカップリングに変わる為ですね
同時に意図的にですが かつてのウォータフォールスタイルの開発も無くなりました
小さいPICマイコンでは今までの構造化ですが w
0431デフォルトの名無しさん
2011/03/02(水) 14:25:17.04既存クラスに機能追加した時に、OCPを守った上で一番良い方法は?
スーパークラスも機能追加したい場合がよくあると思いますが
OCPだと既存クラスに手を入れるのは基本NGになる。
そうなると、やっぱりメタクラスで実装するのが一番なのか?
しかし、メタクラスを実装していない言語も多い。
あとは、スーパークラスをNULLオブジェクトとして設計する。
既存クラスに手を入れるが、NULLオブジェクトだからロジックには手が入らない。
実用上問題ないと考える。
みなさんはメソッド追加を見越して、どのようなクラス設計をしていますか?
そもそもスーパークラスにメソッド追加自体を許さないとか?
0432デフォルトの名無しさん
2011/03/02(水) 14:35:13.64がまずは第一だと思うよ
0433デフォルトの名無しさん
2011/03/02(水) 14:56:45.16複数の実装クラスで同じロジックを一杯実装しなきゃならんようになったら、abstractでデフォルト動作を規定して、それを継承って感じ。
0434デフォルトの名無しさん
2011/03/02(水) 15:07:07.41既存のメンバの動作を変更しない限りは別に問題ない
0435デフォルトの名無しさん
2011/03/02(水) 15:13:48.68「メソッド追加を見越したクラス設計」って、
何かよくわからんが嫌なにおいがする。
0436デフォルトの名無しさん
2011/03/02(水) 15:18:18.33それなら妥協して普通の仮想メソッドにして既定の実装を提供しておくだけ
たぶん>>431の言葉でいえばNULLオブジェクト
0437デフォルトの名無しさん
2011/03/02(水) 18:13:09.19>継承を前提にした設計を可能な限り減らす
その理由は? たまに継承を使うなと言う人がいるけど納得出来る理由を聞いたことがない。
>>433
>まずinterfaceの抽出からだな。
説明が悪かったのかな? 既存の動いているシステムに機能追加する場合を想定している。
また親・子クラス関係なく多態で扱いたい。
>>434
>既存クラスにメソッドを追加してはいけないというのがまずおかしいでしょ
なるほど、たしかに既存動作に影響しないけど、それを証明するのは?
まったく手を入れなければ、証明する必要もないけど、手を入れた以上は
影響が無いと思ってもコーディングミスもあるし既存機能が正しく動くことを
証明しないと。
OCPではそれも含めて修正は禁止していると思っているんだが。
>>436
>もしかして抽象メソッドを追加する場合のことを言ってるのか?
逆で、システム開発後に動いているスーパークラスに具象クラスを追加して
既存処理に影響が出ないかたちでスーパークラスのメソッド(多態)として使いたい。
何か話が噛み合っていないような。
OCPの原則は、動いているシステムに適用するものだと思っているのだが
ほとんどの返信内容が新規作成時の事を言っているように感じる。
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>単体テストをしっかり書いてからリファクタリング
>クラス設計だけじゃ無理だと思うよ
余計なテストをしなくて済む為のOCPだと思うけど。
>>439
>どっちみちテストは必要
余計なテストをしなくて済む為のOCPだと思うけど。
>>440
>継承を許している以上、新たにサブクラスが追加されることによって既存のコードが動かなくなる可能性は常に存在する。
既存コードに影響が無い作りをする為のOCPでしょう。
それに、サブクラスが追加しても親クラスには何ら影響はないでしょう。(あるなら教えて欲しい)
俺が聞きたいのは、OCPを適用したら既存部分はまったく影響ないけど
既存コードを修正したい場合があるから、OCPが崩れる。
その影響を最小限にするクラス設計をみんなどうしているのか?を聞きたい。
0442デフォルトの名無しさん
2011/03/02(水) 22:03:48.050443デフォルトの名無しさん
2011/03/02(水) 22:29:11.28変更時に既存動作に影響がないか確認するためのテストファーストです。
リファクタリングしようがしまいがテストは書かなきゃ駄目。
余計なテストなんてものはない
>影響を最小限にするクラス設計をどうしているのか?
だから>>438
0444デフォルトの名無しさん
2011/03/02(水) 22:51:01.38でも、サブクラスが増えると、それが混ざる可能性のある場所全てが誤動作する可能性がある。
程度問題だが、そういう見方も可能。
0445デフォルトの名無しさん
2011/03/02(水) 23:14:23.18それが「修正に対して閉じている」ということだから。
でも、それをどうやって証明する? 結局テストするしかないじゃないかw
0446デフォルトの名無しさん
2011/03/03(木) 02:03:12.57>ここまでOCP,OCP言う人初めて見たわ。俺、そこまで深く考えてないわ。
んっ? 質問だけど、クラス設計の時は何を目指してやっているの?
例えばデザインパターンを使って設計していても根底にはOCPがあると思うけど。
>>443
>変更時に既存動作に影響がないか確認する
OCPは変更(修正)しては駄目と言う原則だけど。
機能追加する部分はテストファーストやTDDでやってもいいけど、質問している事と違うだが...
>>444
>でも、サブクラスが増えると、それが混ざる可能性のある場所全てが誤動作する可能性がある。
「サブクラスが増える」と「それが混ざる」 何が混ざると?影響が混ざると言うこと?
>>445
>でも、それをどうやって証明する? 結局テストするしかないじゃないかw
機能追加だけ行えば既存機能は影響がないと思うけど。
言語にもよるけど、継承元クラスのコードが無くても(バイナリで提供)
継承したクラスを作ることが出来る言語もある。
親クラスをバイナリ・レベルで提供だから、動作には変更が無いことを証明していると思うけど。
0447442
2011/03/03(木) 08:06:53.95>んっ? 質問だけど、クラス設計の時は何を目指してやっているの?
普通に>>432とか>>433とか。OCPは単なる原則であって規制だという認識じゃないんで、
OCPを守る為に設計、OCPはテストをしなくて済む為のもの、とかまで拡大解釈してない。
0448デフォルトの名無しさん
2011/03/03(木) 09:30:51.37を受ける既存メソッドの引数に、新しいサブクラスのインスタンスを渡すこと。
それによってそのメソッドが正しく動作しないケースは実際にある。
LSPって知ってる?
0449デフォルトの名無しさん
2011/03/03(木) 13:38:08.79それは手法であって、目的や目標がじゃない気がする。
設計に目的や目標は、いらないと考えている?
>>448
Liskovは知っているけど、それを守る為のOCPでしょう。
機能追加はもちろんテストしないといけないけど
それ以外に影響を出さない為のOCPで
LSPはモジュールを置き換えたときに適切な動作しないといけないと言うだけで
当たり前の事を言っているだけ(だから原則なのかもしれないけど)
そのことは、今回来ていない。
何か話しが噛み合わないな...
0450デフォルトの名無しさん
2011/03/03(木) 13:41:26.470451デフォルトの名無しさん
2011/03/03(木) 15:10:04.82なんでその証明は不要なのに、既存クラスにメソッドを追加したときに
その既存クラスの動作に影響を与えないことの証明は必要なの?
0452451
2011/03/03(木) 15:38:42.43431が主張する「サブクラスが追加されても既存のコードは正しく動作する」はLSPが大前提なわけ。
でもそれって自明なことじゃないでしょ? やってみないとわからない。
サブクラスの実装に問題が無くても、既存のコードが暗に既存サブクラスの細かい仕様外の動作を前提にしてしまっていて
それがサブクラスを追加することで明るみに出るかもしれない。
それって、既存クラスにメソッドを追加することのリスクと本質的に何が違うの?
0453デフォルトの名無しさん
2011/03/03(木) 17:34:25.32普通OODだと、変更に強い設計にするとか再利用しやすい設計とか。
>>451,452
>だからLSPが守れていることはどうやって証明するの?
機能追加にLSPは関係ないと思う。、
修正なら使っているクライアントにLSPを保障しないといけないけど
機能追加は、その時点で誰も使っていないから「置換」は発生しない。
431の例で誰に対するLSPを証明するの? LSPは関係ないと思うけど。
>サブクラスの実装に問題が無くても、既存のコードが暗に既存サブクラスの細かい仕様外の動作を前提にしてしまっていて
もし前提にしてたとしても、それはその時点で実装されているメソッドに対してでしょう?
新しく実装されるメソッドを前提にクラスが作られているとは思えない。
0454デフォルトの名無しさん
2011/03/03(木) 18:58:27.53>機能追加する部分はテストファーストやTDDでやってもいいけど、質問している事と違うだが...
じゃあ確認するけど
>既存クラスに機能追加した時に、OCPを守った上で一番良い方法は?
>みなさんはメソッド追加を見越して、どのようなクラス設計をしていますか?
>既存の動いているシステムに機能追加する場合を想定している。
>OCPではそれも含めて修正は禁止していると思っているんだが。
>既存処理に影響が出ないかたちでスーパークラスのメソッド(多態)として使いたい。
これでいいよね?
メソッドの追加はOCP違反なんでしょ?
だから、既存部分の動作が変わっていないか確認するためにテストを書いたら、と言ってるんだよ
OCPを守っていればテストが不要というわけじゃないけどね
>何か話しが噛み合わないな...
OCPはこうあるべきという原則であって、守っていれば既存の動作が変更されないということを
保証する技術じゃないよ。かみ合わない原因はこれ
0455デフォルトの名無しさん
2011/03/03(木) 22:49:19.890456デフォルトの名無しさん
2011/03/03(木) 23:12:07.54失礼、アンカーが抜けてた
>>438
>クラス設計だけじゃ無理だと思うよ
0457デフォルトの名無しさん
2011/03/04(金) 01:46:33.11「余計」ちゅーのがそもそも間違い
0458デフォルトの名無しさん
2011/03/04(金) 10:41:27.59>機能追加に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機能追加に伴って顕在化するようなバグや設計上の問題が
既存コードには全く存在しないことを仮定している。
それに対して、他の人はその前提がおかしいと言っている。
そういうことを前提にしていいのであれば、カプセル化の原則が厳密に守られていることを前提にすれば
メソッドを既存クラスに追加しようが全く問題ないことになるよね。
0461デフォルトの名無しさん
2011/03/04(金) 18:20:06.72>なぜ、こんなに話が噛み合わないかな...
なぜ噛み合わないのか?それは聞いた場所が悪いんじゃないのか。
OCPやカプセル化すら理解出来ていない奴に聞いてもしょうがないだろう。
ここじゃなく知恵袋で聞いて来い。
あっちは一瞬で京大の問題まで解いてくれるから、まともな答えが返ってくるぞw
0462デフォルトの名無しさん
2011/03/04(金) 18:42:07.42もう何度もいってるし460もいってるけど前提が間違ってる
OCPは動作が変更されないことを保証しない。
追加したメソッドがメンバ変数(あるいはグローバル変数)に干渉していて
既存メソッドが正常に動作する前提を崩している可能性がある。
これはスーパークラスに追加した場合でも継承してサブクラスに
追加(君の言うOCPを適用)した場合でもかわらないし、追加メソッドのテストだけでは確認できない。
別に反論してくれなくてもいいけど、反論するなら
>OCPを守っていれば既存コードには影響ないと思っている。
みたいな感想ではなく、根拠をしめしてね
ついでに、勘違いしてる人と定義論争したくないから今まで黙ってたけど
君のOCPの定義は間違ってるよ
>OCPは変更(修正)しては駄目と言う原則
とか
>OCPを守っていれば単体テストの範囲は追加機能分だけ
>余計な単体テストは不要になる
とかはメイヤーさんが聞いたら泡吹いて卒倒するレベルだからよそでは言わないほうがいいよ
こっちは反論を受け付けません。ちゃんとしりたかったらメイヤーのオブジェクト指向入門読んでね
0463デフォルトの名無しさん
2011/03/04(金) 22:56:26.20それは結果としてOCPを破ってる(正しく開かれてない)と言うこともできるんじゃないの?
どっちにしろ彼は既存コードが拡張に対して絶対に正しく動作するという理想的な状況を仮定しているわけだから
そんなものを作れる完璧超人が既存クラスにたかがメソッド一個追加するときに
誤って既存メンバの動作を変えてしまうようなヘマをするとは思えないけども
0464デフォルトの名無しさん
2011/03/05(土) 13:07:00.87他の所で聞いてもいいけど、別に正解だけを聞きたいだけじゃないからな。
正解は複数あると思うし、その環境にベストな答えは自分で考えないといけないと思っている。
>>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長くなったので二分割
>>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>派生先メソッドの事前事後条件が派生元のそれより弱いということになる
>これは派生クラスの事後条件が基底クラスより弱くなってはいけないという意味の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(開放-閉鎖原則)」というPDFがあるから、>>431(と分かってなさそうなその他数名)は
読んどけよ
相当やさしく書かれているから、これで理解できなければ救いようがないわ
0472デフォルトの名無しさん
2011/03/08(火) 11:36:59.45>動作を変更しないことを証明するのは難しい
そういうことでしょ
特に、修正は原則として既存クラスのメンバをオーバーライドして動作を変更する
(つまりカプセル化を破る)ことで行うというポリシーが前提なので
細かい動作の変更が大きな影響を及ぼす恐れがある
そのポリシーの是非は今は問題にしていない
0473デフォルトの名無しさん
2011/03/08(火) 20:35:02.43>何のテストを行うのか?
サブクラスがスーパークラスから継承しているメソッド(非オーバーライドも含め)
ほかにもいろいろあるけどもういいや
OCPを適用した場合に省くことできる「余計なテスト」の例とその根拠だけ解説してくれ
あればweb上で参照できるソースも
0474デフォルトの名無しさん
2011/03/08(火) 20:37:00.95>メソッドの追加自体は修正とちがうんでない?
クラス単位で見た場合に修正となる。
>動作を変更しないことを証明するのは難しいから追加も修正とみなして禁止?
追加を修正とみなして禁止ではない、実際メソッドの修正なら元のソースを修正するが
追加なら元のソースは無くても出来る。(言語にもよるが)
大雑把に言えば現在のソースに直接手を入れるのが修正。
>>471
なぜ自分の意見で書かない自信がないのか?
>open-closed principle を満たすプログラムでは新しいコードを追加するだけで機能を追加すること
>になるので、既存のコードを変更することはありません。ですから、この原則を満たさないプログラム
>で見受けられるような変更の連鎖を経験することもないのです。
「変更の連鎖を経験することもない」この意味が分かるか?
OCPを守っていれば、「変更の連鎖がない」つまり親クラスに影響を与えないと言うことだ。
>>472
>特に、修正は原則として既存クラスのメンバをオーバーライドして動作を変更する
>(つまりカプセル化を破る)ことで行うというポリシーが前提なので
「オーバーライドして動作を変更する」オーバーライドしたら、それは修正じゃないだろう。
0475デフォルトの名無しさん
2011/03/08(火) 23:27:35.37あんたら的にはどう思う?
0476471
2011/03/08(火) 23:43:52.62お前は誰と戦ってんだよ?
俺はOCPを誤って理解してる馬鹿がいたから分かりやすい文書を教えてやっただけのこと
くだらん煽りはいいから早く続きを読め
まだ途中までしか読んでないんだろ?
お前が引用した箇所のすぐ下、「戦略的閉鎖」まで読めば誤りに気がつくだろ
(普通はもっと早く気がつくだろうけど)
俺はこのPDFほど優しく教えられないからな、素直に読んでくれることを望むよ
0477デフォルトの名無しさん
2011/03/09(水) 00:11:38.05>open-closed principle を満たすプログラムでは新しいコードを追加するだけで機能を追加すること
>になるので、既存のコードを変更することはありません。ですから、この原則を満たさないプログラム
>で見受けられるような変更の連鎖を経験することもないのです。
下にも書いたこれでいいか、影響範囲が特定出来れば「余計なテスト」はいらない。
>>475
俺は知らない。
>>476
まったく、メイヤーを読めとかマーチンを読めとかお前が読めよ。
理解出来ていないのは、お前だから早く気づけ。
自分の言葉で説明出来ない黙っていろよ。
今日は、まともなに話が出来る人間はいなかったな。
■ このスレッドは過去ログ倉庫に格納されています