オブジェクト指向とDIを分かりやすく例えて教えてくれ 3
■ このスレッドは過去ログ倉庫に格納されています
0001仕様書無しさん
垢版 |
2018/05/19(土) 21:44:19.89
■ オブジェクト指向・デザインパターン(有用)
 
 わかり易い例
 class Dog extends Animal
 class Cat extends Animal

■ DI(ゴミ)

 DIとは?・・・オブジェクト指向の依存関係を"ひとまとめに"定義する部分と、それを利用するために
        オブジェクトを直接newするのではなく、DIコンテナにnewしてもらうパターン

 https://web.archive.org/web/20170707082300/http://kakutani.com/trans/fowler/injection.html

 > Dependency Injection の形式
 > Dependency Injection の基本的な考え方は、独立したオブジェクトを
 > Assembler(組み立て係)として用意し、 MovieFinder インタフェースの実装を
 > MovieLister クラスのフィールドへ適切に設定させるというものだ。
 > 依存関係は図2のようになる。


前スレ

オブジェクト指向とは 分かりやすく教えてくれ
https://medaka.5ch.net/test/read.cgi/prog/1521869966/

オブジェクト指向を分かりやすく例えて教えてくれ 2
https://medaka.5ch.net/test/read.cgi/prog/1525660302/
0004仕様書無しさん
垢版 |
2018/05/19(土) 22:00:18.05
■ DIの例

それから、PicoContainerはそれぞれのインタフェースがどの実装クラスと結び付けられるのかを通知してもらう必要がある。 MovieFinder にどういうファイル名がインジェクトされるのかについても同様だ。

private MutablePicoContainer configureContainer() {
MutablePicoContainer pico = new DefaultPicoContainer();
Parameter[] finderParams = {new ConstantParameter("movies1.txt")};
pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);
pico.registerComponentImplementation(MovieLister.class);
return pico;
}
この設定コードは、本来ならば別の設定クラスで記述されるべきものだ。
0005仕様書無しさん
垢版 |
2018/05/19(土) 22:00:41.52
■ コンストラクタインジェクションの例

PicoContainer を利用するためには、以下のようなコードを書く。

public void testWithPico() {
MutablePicoContainer pico = configureContainer();
MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);
Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}
なお、このサンプルではコンストラクタ・インジェクションを利用しているが、 PicoContainer では
セッター・インジェクションもサポートしている (開発者たちはコンストラクタ・インジェクションのほうが好みのようだけれど)。
0006仕様書無しさん
垢版 |
2018/05/19(土) 22:02:30.37
■ Spring でのセッター・インジェクションの例
Spring Framework は エンタープライズ Java 開発向けの守備範囲の広いフレームワークだ。
トランザクション、永続化フレームワーク、Web アプリケーション開発や JDBC に関する抽象レイヤがある。

MovieLister がインジェクションに対応できるように、 サービス設定用の setter メソッドを定義しなければならない。
(省略)

同様に、MovieFinder には文字列の setter を定義する。
(省略)

3番目のステップとして、ファイルに設定を記述する。Spring での設定は XML ファイルでもコードでも可能だが、 XMLで行うことが望ましいとされている。

<beans>
<bean id="MovieLister" class="spring.MovieLister">
<property name="finder">
<ref local="MovieFinder"/>
</property>
</bean>
<bean id="MovieFinder" class="spring.ColonMovieFinder">
<property name="filename">
<value>movies1.txt</value>
</property>
</bean>
</beans>

テストはこんな感じだ。
public void testWithSpring() throws Exception {
ApplicationContext ctx = new FileSystemXmlApplicationContext("spring.xml");
MovieLister lister = (MovieLister) ctx.getBean("MovieLister");
Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}
0007仕様書無しさん
垢版 |
2018/05/19(土) 22:03:15.98
結局手抜きしてフィールドインジェクションしてるわ
0008仕様書無しさん
垢版 |
2018/05/20(日) 03:13:45.22
XMLもsetterもキモイから嫌い
コードで配線の設定書いてコンストラクタでインジェクションしてる
0010仕様書無しさん
垢版 |
2018/05/20(日) 07:18:45.20
>>9
クラスやインターフェースの定義の話じゃないぞ?

DIの依存関係の定義っていうのはコードもしくは設定ファイル
なんだから、お前が勘違いした実装というのは
「コードで書いたDIの依存関係の」定義だろ
0011仕様書無しさん
垢版 |
2018/05/20(日) 09:10:00.65
>>6
ついにここまで来たか
学習能力高いな
アノテーション定義もやってみよう
0012仕様書無しさん
垢版 |
2018/05/20(日) 19:34:27.18
さて、前スレのなぜDIを使うとライフサイクルの事まで
考えなければいけなくなるのか?の答

惜しい所まで来てるんだけど、あと一歩足りない
DIを悪く言えないから、気づいてしまったけど
口に出して言えないのかもしれないねw

DIを使うとライフサイクルの事まで考えなければいけなくなるのは
DIがなにをやってくれるものなのかに気づく必要がある

再掲すると

 DIとは?・・・オブジェクト指向の依存関係を"ひとまとめに"定義する部分と、それを利用するために
        オブジェクトを直接newするのではなく、DIコンテナにnewしてもらうパターン

 https://web.archive.org/web/20170707082300/http://kakutani.com/trans/fowler/injection.html

 > Dependency Injection の形式
 > Dependency Injection の基本的な考え方は、独立したオブジェクトを
 > Assembler(組み立て係)として用意し、 MovieFinder インタフェースの実装を
 > MovieLister クラスのフィールドへ適切に設定させるというものだ。
 > 依存関係は図2のようになる。

一言で言うならば、newを代わりにやってくれるものと考えればいい
それだけ。そう、それだけなんだよ。

だからどんな用途にも使える。これは一見優れているように見えるかもしれないが、
汎用的な解決方法しか提供できないため、逆に特定の問題をシンプルに解決することができない

フレームワークは一般的に特定の問題(例えばウェブアプリ)を解決するために作られたものなので
ライフサイクルの管理もフレームワークで管理して、特定の問題の解決に必要な部分のみを
プログラマが記述すれば良くなる。
0013仕様書無しさん
垢版 |
2018/05/20(日) 19:36:15.35
もちろんDIを使っていてもフレームワークが
DIを内部に隠蔽することでライフサイクルの管理を
プログラマがしなくてすむようにできるだろうけど、
そうするとプログラマがDIを直接使うのが難しくなってしまう
0019仕様書無しさん
垢版 |
2018/05/20(日) 20:12:33.22
DI(フレームワーク)がライフサイクル管理してくれるんだろ?
プログラマは意識しなくていいやん
0020仕様書無しさん
垢版 |
2018/05/20(日) 20:13:28.86
まだやってたのか!?
おまえ等がDI大好きなのはわかった…
0021仕様書無しさん
垢版 |
2018/05/20(日) 20:13:56.23
DIはフレームワークじゃないよ。パターン。
DIパターンを使ったフレームワークと勘違いしてね?
0023仕様書無しさん
垢版 |
2018/05/21(月) 01:21:20.44
>>22
自分が?まあ反論してないってことはそういうことなんだろうけど
0024仕様書無しさん
垢版 |
2018/05/21(月) 01:32:01.57
むしろ今までライフサイクル意識せずピュアな実装してたとか恐怖でしかない
0025仕様書無しさん
垢版 |
2018/05/21(月) 01:45:49.89
そういうのはフレームワークが隠蔽すべきものだからね
0027仕様書無しさん
垢版 |
2018/05/22(火) 09:05:53.76
なんかね、説明が下手くそでよくわかんない。
もっとわかりやすく丁寧にDIが何故ダメなのか教えて欲しい。

ググって出てくる記事の方がわかりやすくて「DIって便利だなー」って思っちゃう。
0028仕様書無しさん
垢版 |
2018/05/22(火) 11:17:17.10
とても簡単な自宅で稼げる方法
参考までに書いておきます
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』

U3ANT
0029仕様書無しさん
垢版 |
2018/05/22(火) 13:48:41.48
helloworldや数当てゲーム、石取りゲームなんかにゃ過剰。
どっかの業務基幹システムを、低品質な人海戦術でやっつけようなんて時は有用。
0031仕様書無しさん
垢版 |
2018/05/22(火) 19:42:25.80
DIはモックフレームワークが出てきて完全に価値がなくなったね
0033仕様書無しさん
垢版 |
2018/05/22(火) 20:42:42.30
モックの仕組みが理解できない低脳が
ユニットテストやるためにはDIしか選択肢がないから
無価値ではないか
0034仕様書無しさん
垢版 |
2018/05/23(水) 02:27:01.57
DIは過剰な設計で開発を楽にはしてくれない
0035仕様書無しさん
垢版 |
2018/05/23(水) 05:45:13.15
DIなんて実装の一作法でしか無いのに、まるでオブジェクト指向の根幹みたいな勘違いさせるスレタイってw
…あ、隔離スレかww
0036仕様書無しさん
垢版 |
2018/05/23(水) 05:51:18.30
DIってプロジェクト全体の依存関係の定義を一箇所で
行うから、グローバル定義になって、
オブジェクト指向とは真逆の技術なんだよね
0037仕様書無しさん
垢版 |
2018/05/23(水) 07:12:04.03
DI採用しないとかCOBOLとかC言語なんだろ

まあ手続きで良いと思う
0038仕様書無しさん
垢版 |
2018/05/23(水) 07:48:55.96
COBOLは知らんけど今時のCはOOPで書くものだよ
ユニットテストではモックに差し替えるしDIももちろん使う
0039仕様書無しさん
垢版 |
2018/05/23(水) 07:55:14.24
どのクラスをnewして使うべきか、というのもオブジェクトの大事な責務なのに、
それを外出しして一つにまとめて神クラス作るのがDI
DI褒めてるやつはオブジェクト指向を分かってない
0041仕様書無しさん
垢版 |
2018/05/23(水) 08:01:09.58
>>39
大事なものだからシステマチックに管理する
DIを使わないとオブジェクトのオーケストレーションという責務がアプリケーションの全体に分散してハードコーディングされてしまう
0044仕様書無しさん
垢版 |
2018/05/23(水) 09:36:26.19
>>41
> オブジェクトのオーケストレーションという責務

なんで責務を増やすの?
そんなの不要なものなのに
0045仕様書無しさん
垢版 |
2018/05/23(水) 12:13:12.43
>>43
グローバルかつスタティックにnewを管理したいんでしょ?
スタティックおじさんじゃん
0047仕様書無しさん
垢版 |
2018/05/23(水) 12:42:27.86
クラス図描かないから相関関係が曖昧になって、どこからでもインスタンス捕まえられる様にまとめて1箇所でnewするんだよ。
スタティックおじさんよりタチが悪い。
0048仕様書無しさん
垢版 |
2018/05/23(水) 12:57:45.67
どこからでもインスタンス捕まえられる様にまとめて1箇所でnewするという発想

なるほどこいつにはDIコンテナを与えない方がよさそうだ
0049仕様書無しさん
垢版 |
2018/05/23(水) 13:14:29.61
テストに有用って結局インスタンス捕まえられるからだろ?
0051仕様書無しさん
垢版 |
2018/05/23(水) 15:37:37.21
ヒーブ管理を拡張して、オブジェクト生成時にユニークなID振るようなツール使えばインスタンスを捕まえる必要も無いけどな。
0052仕様書無しさん
垢版 |
2018/05/23(水) 18:12:16.86
スタティックおじさんというよりグローバル変数おじさん
0053仕様書無しさん
垢版 |
2018/05/23(水) 19:22:58.08
実際には全く逆
全てローカルで解決するにはDIするしかない
newはインスタンスがどこからともなく湧いてきていきなり管理外になってしまう
よりグローバル的な解決手段と言える
0054仕様書無しさん
垢版 |
2018/05/23(水) 19:31:06.73
DI使っても使う所で
newもしくは、DIコンテナから取得
するっていうのはわかるね?

newはあちこちに散らばある。
DI使えばnewが一箇所にまとまると言うが、
newの代わりにDIコンテナからの取得が
散らばるだけだっていうのは気づいてるよね?

おそらく気づいてないんだと思う。
だってDI使ってないだろ?w
0055仕様書無しさん
垢版 |
2018/05/23(水) 19:37:06.15
>>54
DIからの取得は野放しnewとは異なり完全に集中管理統制されている
0058仕様書無しさん
垢版 |
2018/05/23(水) 19:55:21.53
>>57
やっぱり分かってないみたいねw
依存関係を登録した後のそのオブジェクトの使い方はこう
何もしないでも勝手にオブジェクトが作られるわけないよ
当たり前だけど

■ コンストラクタインジェクションの例

PicoContainer を利用するためには、以下のようなコードを書く。

public void testWithPico() {
MutablePicoContainer pico = configureContainer();
MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);
Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}
0059仕様書無しさん
垢版 |
2018/05/23(水) 19:56:07.68
MovieLister lister = new MovieLister の代わりが
MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);
になる
0061仕様書無しさん
垢版 |
2018/05/23(水) 20:22:49.60
そもそもDIコンテナ使うところってmainじゃないの?
DIコンテナをコンポジションしちゃうわけ?
0062仕様書無しさん
垢版 |
2018/05/23(水) 20:32:12.73
DI使っているフレームワーク見ればすぐ分かるのに…
0065仕様書無しさん
垢版 |
2018/05/23(水) 21:58:39.41
>>61
お前はDIコンテナのことをまったく知らずに発言してるという理解で間違いないか?
0066仕様書無しさん
垢版 |
2018/05/23(水) 22:38:16.78
>>61叩かれてるの何で?
DIコンテナに直接インスタンスをおねだりするケースはあまり無いと思うんだけど...

一般人が書くコードの中じゃ、@AutoWiredみたいなメタデータか設定ファイルで定義して、インスタンスを注入すれば良い。
要件が特殊か設計がマヌケな場合に、ApplicationContext.getBean()みたいなの書くハメになる。
0067仕様書無しさん
垢版 |
2018/05/23(水) 23:13:12.95
>>61
mainでやるのは依存関係の定義
mainでオブジェクトを全部生成してしまったら
それはライフサイクルが固定されてしまう
mainでnew(の代わりのDIコンテナからのオブジェクトの生成)をやるわけがない。
その時点でDI分かってないんだなーって思うよw
0068仕様書無しさん
垢版 |
2018/05/23(水) 23:35:33.88
ライフサイクルは盲点だった
DIコンテナで扱うのなんて全部ステートレスでシングルトンなサービスクラスだと思ってたよ
0069仕様書無しさん
垢版 |
2018/05/23(水) 23:50:52.87
>>58
案の定、使い方わからずに文句言ってただけだったなこいつ
0070仕様書無しさん
垢版 |
2018/05/23(水) 23:56:40.22
通常はフレームワークが生成ルートになるから、DIの生成メソッドを呼ぶなどというマヌケな事にはならない
0071仕様書無しさん
垢版 |
2018/05/24(木) 03:13:24.84
>>70
でもその理屈だと、newだって一緒なんだよねw
ほらね。DIだからっていうのが無くなった
0077仕様書無しさん
垢版 |
2018/05/24(木) 07:15:37.10
DIコンテナをコンポジションするのが一般的なDIの使い方だとした場合、DIっファクトリと何が違うのん?
0078仕様書無しさん
垢版 |
2018/05/24(木) 07:42:02.81
>>77
何回も書いてあるだろ

再掲すると

 DIとは?・・・オブジェクト指向の依存関係を"ひとまとめに"定義する部分と、それを利用するために
        オブジェクトを直接newするのではなく、DIコンテナにnewしてもらうパターン

 https://web.archive.org/web/20170707082300/http://kakutani.com/trans/fowler/injection.html

 > Dependency Injection の形式
 > Dependency Injection の基本的な考え方は、独立したオブジェクトを
 > Assembler(組み立て係)として用意し、 MovieFinder インタフェースの実装を
 > MovieLister クラスのフィールドへ適切に設定させるというものだ。
 > 依存関係は図2のようになる。

ファクトリはプログラマが適切なタイミングで必要なオブジェクトを
ファクトリ経由で生成してもらう。依存関係はその場に記述する

DIは依存関係をひとまとめに定義する部分が独立して存在する
DIコンテナはファクトリに似ているが、関連するオブジェクトのみを扱うファクトリとは違って
DIコンテナは、全てのオブジェクトと取り扱うプロジェクトで唯一のグローバルなファクトリ
0079仕様書無しさん
垢版 |
2018/05/24(木) 13:32:26.01
>>78
その引用わかりにくいし、スレタイが「わかりやすく例えて教えてくれ」ってことなので、もう少し情報まとめて語ってくれません?
0080仕様書無しさん
垢版 |
2018/05/24(木) 13:36:28.37
>>79
わかりやすいだろ
っていうか、お前がその定義は嫌だ
認めたくないって言いたいだけだろ
あきらめろ。これがDIの定義だ
0081仕様書無しさん
垢版 |
2018/05/24(木) 14:14:19.85
つか、オブジェクトをnewすっから変な話になるんだよ。
全てのクラスはファクトリーが生成、戻り値はユニークなハンドルIDにして、クラス間はハンドルIDにメッセージ送って処理する様にすれば、DIが無意味な事が分かるだろ。
この仕組みなら各オブジェクトが同一CPU内に無くても巨大なネットワークの任意の場所で動いていても動かせる。
…って考えると、DIは小規模なシステムで使うくらいしか役目がないって事だ。
0084仕様書無しさん
垢版 |
2018/05/24(木) 16:38:17.64
メッセージ型のオブジェクト指向言語だと意味が無いってのは確か。
0085仕様書無しさん
垢版 |
2018/05/24(木) 17:15:01.39
あるオブジェクトがAに依存してますって時、
そのAをオブジェクト内部で作ろうが外部から渡そうが
何も違いないじゃん。なら余計な仕組みが要らない方がいいよね
0086仕様書無しさん
垢版 |
2018/05/24(木) 17:22:25.63
実装方法なんか言語仕様の範囲内でどうにでもなるんだから、瑣末な問題の重箱の隅をいつまてつついてるんだ?って話だ罠
0087仕様書無しさん
垢版 |
2018/05/24(木) 17:44:06.68
実装方法? 別に何かを実装しなければいけないなら
余計な仕組みがないほうが良いですよね。
0088仕様書無しさん
垢版 |
2018/05/24(木) 17:51:59.74
>>85
内部で作るってことはメモリとCPUが一枚の基盤に載ってるようなものでクッソ使いにくいわけだ
0089仕様書無しさん
垢版 |
2018/05/24(木) 17:53:52.08
>>88
その理屈はおかしい。
今やCPUにGPUがバンドルされる時代だぞ?
昔は外付けで必要だったLANカード、サウンドボードだって
随分前からマザーボードに内蔵されてる
使いにくい?逆だろう?
0090仕様書無しさん
垢版 |
2018/05/24(木) 18:01:42.43
>>89
そのバンドルをDIコンテナがやってんだよ
オールインワンで購入しても蓋開けたらそれぞれの部品は外して独立化できるだろ?
プログラムもそれと同じ
独立性の高い部品を個別に用意してバンドルしてシステムとして機能させる

newするってことはすべてのパーツを物理的に分離不能にくっ付けるようなもの
メモリとCPUが1枚の基盤にハンダでがっちり固められてしまったらもう使い物にならん
0091仕様書無しさん
垢版 |
2018/05/24(木) 18:10:11.41
パソコン例えだと使用時より製造時の方が深刻だな
メモリCPUディスプレイキーボードハードディスク…あらゆるものが結合してて同じ工場の生産ラインに異なる領域のすべての生産能力を持たせないといけない
これじゃ生産コストが高すぎる
0092仕様書無しさん
垢版 |
2018/05/24(木) 18:18:28.17
>>90
> オールインワンで購入しても蓋開けたらそれぞれの部品は外して独立化できるだろ?
独立化できねーよ。
お前やっぱり分かってないな。
0094仕様書無しさん
垢版 |
2018/05/24(木) 18:26:57.35
>>91
> メモリCPUディスプレイキーボードハードディスク…あらゆるものが結合してて同じ工場の生産ラインに異なる領域のすべての生産能力を持たせないといけない
例えが的はずれすぎる

なんで同じ工場でメモリを作らないのいけないのか?
マザーボードを作る工場で、外部から購入したメモリを
マザーボードに取り付けるだけだろ

他のもマザーボードには様々チップ、抵抗、コンデンサ等を
搭載しているが、それらを作ってるわけじゃない。
買ってきて取り付けてるだけだ

そうやって、いろんなものが統合されてるマザーボードが出来上がる
0095仕様書無しさん
垢版 |
2018/05/24(木) 18:40:23.17
>>77
> DIコンテナをコンポジションするのが一般的なDIの使い方だとした場合、DIっファクトリと何が違うのん?

DIはひとまとめに依存関係を定義するので
実行中に動的に違うオブジェクトに変更できない

ファクトリだったら例えば読み込む設定ファイルを
変更するだけで、使用するオブジェクトを変更できるが
DIは決まったものから変更できない
0096仕様書無しさん
垢版 |
2018/05/24(木) 18:56:04.15
>>93
な?
メンテナンスしにくいだろ?
CPUだけ新しいものに変えてテストできんの?
そういうこと
0097仕様書無しさん
垢版 |
2018/05/24(木) 18:57:40.20
>>96
? メンテナンスしないものに対して
メンテナンスできるようにするのは過剰だろ。

それに他のオブジェクトに変えたければ
再コンパイルすればいいだけ

> CPUだけ新しいものに変えてテストできんの?
じゃあもう固定で埋め込んで変えられないようにしたほうが良いですねw
0098仕様書無しさん
垢版 |
2018/05/24(木) 18:57:41.21
>>94
それはまさにDIの考え方
部品は別に作って組み合わせるまさにDI
newは同じ工場で作ることにあたる
0099仕様書無しさん
垢版 |
2018/05/24(木) 18:59:55.99
>>98
> 部品は別に作って組み合わせるまさにDI

だから、それはDIじゃねーって言ってるだろ

 DIとは?・・・オブジェクト指向の依存関係を"ひとまとめに"定義する部分と、それを利用するために
        オブジェクトを直接newするのではなく、DIコンテナにnewしてもらうパターン

 https://web.archive.org/web/20170707082300/http://kakutani.com/trans/fowler/injection.html

 > Dependency Injection の形式
 > Dependency Injection の基本的な考え方は、独立したオブジェクトを
 > Assembler(組み立て係)として用意し、 MovieFinder インタフェースの実装を
 > MovieLister クラスのフィールドへ適切に設定させるというものだ。
 > 依存関係は図2のようになる。
0100仕様書無しさん
垢版 |
2018/05/24(木) 19:02:45.70
工場で例えるなら、

■DIを使わない場合
マザーボードメーカー「メモリを作ってください。作り方や材料の調達は任せます」

■DIを使った場合
マザーボードメーカー「メモリを作ってください。作り方は私が指定します。材料も私が調達します」
0101仕様書無しさん
垢版 |
2018/05/24(木) 19:10:14.38
>>88>>90
ICチップだって元々はトランジスタとかコンデンサを一つづつ組み上げたものなんだけど、いまは一体化してるよね
あんたはCPUをバラして中からトランジスタ取り出せないから使い物にならないって言いたいの?
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況