オブジェクト指向とDIを分かりやすく例えて教えてくれ 3
■ このスレッドは過去ログ倉庫に格納されています
■ オブジェクト指向・デザインパターン(有用)
わかり易い例
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/ ■ DIの例
Dog baby = new Dog(mom.cunt, uncle.dick); >>2
間違い。DIではnewを使わない(DIコンテナが行う) ■ 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;
}
この設定コードは、本来ならば別の設定クラスで記述されるべきものだ。 ■ コンストラクタインジェクションの例
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 では
セッター・インジェクションもサポートしている (開発者たちはコンストラクタ・インジェクションのほうが好みのようだけれど)。 ■ 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());
} XMLもsetterもキモイから嫌い
コードで配線の設定書いてコンストラクタでインジェクションしてる >>9
クラスやインターフェースの定義の話じゃないぞ?
DIの依存関係の定義っていうのはコードもしくは設定ファイル
なんだから、お前が勘違いした実装というのは
「コードで書いたDIの依存関係の」定義だろ >>6
ついにここまで来たか
学習能力高いな
アノテーション定義もやってみよう さて、前スレのなぜ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を代わりにやってくれるものと考えればいい
それだけ。そう、それだけなんだよ。
だからどんな用途にも使える。これは一見優れているように見えるかもしれないが、
汎用的な解決方法しか提供できないため、逆に特定の問題をシンプルに解決することができない
フレームワークは一般的に特定の問題(例えばウェブアプリ)を解決するために作られたものなので
ライフサイクルの管理もフレームワークで管理して、特定の問題の解決に必要な部分のみを
プログラマが記述すれば良くなる。 もちろんDIを使っていてもフレームワークが
DIを内部に隠蔽することでライフサイクルの管理を
プログラマがしなくてすむようにできるだろうけど、
そうするとプログラマがDIを直接使うのが難しくなってしまう DI(フレームワーク)がライフサイクル管理してくれるんだろ?
プログラマは意識しなくていいやん まだやってたのか!?
おまえ等がDI大好きなのはわかった… DIはフレームワークじゃないよ。パターン。
DIパターンを使ったフレームワークと勘違いしてね? >>22
自分が?まあ反論してないってことはそういうことなんだろうけど むしろ今までライフサイクル意識せずピュアな実装してたとか恐怖でしかない そういうのはフレームワークが隠蔽すべきものだからね なんかね、説明が下手くそでよくわかんない。
もっとわかりやすく丁寧にDIが何故ダメなのか教えて欲しい。
ググって出てくる記事の方がわかりやすくて「DIって便利だなー」って思っちゃう。 とても簡単な自宅で稼げる方法
参考までに書いておきます
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
U3ANT helloworldや数当てゲーム、石取りゲームなんかにゃ過剰。
どっかの業務基幹システムを、低品質な人海戦術でやっつけようなんて時は有用。 DIはモックフレームワークが出てきて完全に価値がなくなったね モックの仕組みが理解できない低脳が
ユニットテストやるためにはDIしか選択肢がないから
無価値ではないか DIなんて実装の一作法でしか無いのに、まるでオブジェクト指向の根幹みたいな勘違いさせるスレタイってw
…あ、隔離スレかww DIってプロジェクト全体の依存関係の定義を一箇所で
行うから、グローバル定義になって、
オブジェクト指向とは真逆の技術なんだよね DI採用しないとかCOBOLとかC言語なんだろ
まあ手続きで良いと思う COBOLは知らんけど今時のCはOOPで書くものだよ
ユニットテストではモックに差し替えるしDIももちろん使う どのクラスをnewして使うべきか、というのもオブジェクトの大事な責務なのに、
それを外出しして一つにまとめて神クラス作るのがDI
DI褒めてるやつはオブジェクト指向を分かってない >>39
大事なものだからシステマチックに管理する
DIを使わないとオブジェクトのオーケストレーションという責務がアプリケーションの全体に分散してハードコーディングされてしまう >>41
スタティックおじさんは正しかったって事? >>41
> オブジェクトのオーケストレーションという責務
なんで責務を増やすの?
そんなの不要なものなのに >>43
グローバルかつスタティックにnewを管理したいんでしょ?
スタティックおじさんじゃん クラス図描かないから相関関係が曖昧になって、どこからでもインスタンス捕まえられる様にまとめて1箇所でnewするんだよ。
スタティックおじさんよりタチが悪い。 どこからでもインスタンス捕まえられる様にまとめて1箇所でnewするという発想
なるほどこいつにはDIコンテナを与えない方がよさそうだ テストに有用って結局インスタンス捕まえられるからだろ? ヒーブ管理を拡張して、オブジェクト生成時にユニークなID振るようなツール使えばインスタンスを捕まえる必要も無いけどな。 スタティックおじさんというよりグローバル変数おじさん 実際には全く逆
全てローカルで解決するにはDIするしかない
newはインスタンスがどこからともなく湧いてきていきなり管理外になってしまう
よりグローバル的な解決手段と言える DI使っても使う所で
newもしくは、DIコンテナから取得
するっていうのはわかるね?
newはあちこちに散らばある。
DI使えばnewが一箇所にまとまると言うが、
newの代わりにDIコンテナからの取得が
散らばるだけだっていうのは気づいてるよね?
おそらく気づいてないんだと思う。
だってDI使ってないだろ?w >>54
DIからの取得は野放しnewとは異なり完全に集中管理統制されている >>55
newがnew'になるだけだって言ってるのがわからない? >>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());
} MovieLister lister = new MovieLister の代わりが
MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);
になる そもそもDIコンテナ使うところってmainじゃないの?
DIコンテナをコンポジションしちゃうわけ? DI使っているフレームワーク見ればすぐ分かるのに… >>61
お前はDIコンテナのことをまったく知らずに発言してるという理解で間違いないか? >>61叩かれてるの何で?
DIコンテナに直接インスタンスをおねだりするケースはあまり無いと思うんだけど...
一般人が書くコードの中じゃ、@AutoWiredみたいなメタデータか設定ファイルで定義して、インスタンスを注入すれば良い。
要件が特殊か設計がマヌケな場合に、ApplicationContext.getBean()みたいなの書くハメになる。 >>61
mainでやるのは依存関係の定義
mainでオブジェクトを全部生成してしまったら
それはライフサイクルが固定されてしまう
mainでnew(の代わりのDIコンテナからのオブジェクトの生成)をやるわけがない。
その時点でDI分かってないんだなーって思うよw ライフサイクルは盲点だった
DIコンテナで扱うのなんて全部ステートレスでシングルトンなサービスクラスだと思ってたよ >>58
案の定、使い方わからずに文句言ってただけだったなこいつ 通常はフレームワークが生成ルートになるから、DIの生成メソッドを呼ぶなどというマヌケな事にはならない >>70
でもその理屈だと、newだって一緒なんだよねw
ほらね。DIだからっていうのが無くなった >>67
わかってないから聞いたんじゃん
何その言い方 DIコンテナをコンポジションするのが一般的なDIの使い方だとした場合、DIっファクトリと何が違うのん? >>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コンテナは、全てのオブジェクトと取り扱うプロジェクトで唯一のグローバルなファクトリ >>78
その引用わかりにくいし、スレタイが「わかりやすく例えて教えてくれ」ってことなので、もう少し情報まとめて語ってくれません? >>79
わかりやすいだろ
っていうか、お前がその定義は嫌だ
認めたくないって言いたいだけだろ
あきらめろ。これがDIの定義だ つか、オブジェクトをnewすっから変な話になるんだよ。
全てのクラスはファクトリーが生成、戻り値はユニークなハンドルIDにして、クラス間はハンドルIDにメッセージ送って処理する様にすれば、DIが無意味な事が分かるだろ。
この仕組みなら各オブジェクトが同一CPU内に無くても巨大なネットワークの任意の場所で動いていても動かせる。
…って考えると、DIは小規模なシステムで使うくらいしか役目がないって事だ。 オブジェクトをnewする
↓
日本凄い
↓
俺凄い メッセージ型のオブジェクト指向言語だと意味が無いってのは確か。 あるオブジェクトがAに依存してますって時、
そのAをオブジェクト内部で作ろうが外部から渡そうが
何も違いないじゃん。なら余計な仕組みが要らない方がいいよね 実装方法なんか言語仕様の範囲内でどうにでもなるんだから、瑣末な問題の重箱の隅をいつまてつついてるんだ?って話だ罠 実装方法? 別に何かを実装しなければいけないなら
余計な仕組みがないほうが良いですよね。 >>85
内部で作るってことはメモリとCPUが一枚の基盤に載ってるようなものでクッソ使いにくいわけだ >>88
その理屈はおかしい。
今やCPUにGPUがバンドルされる時代だぞ?
昔は外付けで必要だったLANカード、サウンドボードだって
随分前からマザーボードに内蔵されてる
使いにくい?逆だろう? >>89
そのバンドルをDIコンテナがやってんだよ
オールインワンで購入しても蓋開けたらそれぞれの部品は外して独立化できるだろ?
プログラムもそれと同じ
独立性の高い部品を個別に用意してバンドルしてシステムとして機能させる
newするってことはすべてのパーツを物理的に分離不能にくっ付けるようなもの
メモリとCPUが1枚の基盤にハンダでがっちり固められてしまったらもう使い物にならん パソコン例えだと使用時より製造時の方が深刻だな
メモリCPUディスプレイキーボードハードディスク…あらゆるものが結合してて同じ工場の生産ラインに異なる領域のすべての生産能力を持たせないといけない
これじゃ生産コストが高すぎる >>90
> オールインワンで購入しても蓋開けたらそれぞれの部品は外して独立化できるだろ?
独立化できねーよ。
お前やっぱり分かってないな。 > メモリとCPUが1枚の基盤にハンダでがっちり固められてしまったらもう使い物にならん
最近のMac Book Proが基盤にハンダで取り付けられてるって知らないの?
https://gigazine.net/news/20161117-macbook-pro-touch-bar-teardown/
使いものにならないわけがないことは
証明済みですよね >>91
> メモリCPUディスプレイキーボードハードディスク…あらゆるものが結合してて同じ工場の生産ラインに異なる領域のすべての生産能力を持たせないといけない
例えが的はずれすぎる
なんで同じ工場でメモリを作らないのいけないのか?
マザーボードを作る工場で、外部から購入したメモリを
マザーボードに取り付けるだけだろ
他のもマザーボードには様々チップ、抵抗、コンデンサ等を
搭載しているが、それらを作ってるわけじゃない。
買ってきて取り付けてるだけだ
そうやって、いろんなものが統合されてるマザーボードが出来上がる >>77
> DIコンテナをコンポジションするのが一般的なDIの使い方だとした場合、DIっファクトリと何が違うのん?
DIはひとまとめに依存関係を定義するので
実行中に動的に違うオブジェクトに変更できない
ファクトリだったら例えば読み込む設定ファイルを
変更するだけで、使用するオブジェクトを変更できるが
DIは決まったものから変更できない >>93
な?
メンテナンスしにくいだろ?
CPUだけ新しいものに変えてテストできんの?
そういうこと >>96
? メンテナンスしないものに対して
メンテナンスできるようにするのは過剰だろ。
それに他のオブジェクトに変えたければ
再コンパイルすればいいだけ
> CPUだけ新しいものに変えてテストできんの?
じゃあもう固定で埋め込んで変えられないようにしたほうが良いですねw >>94
それはまさにDIの考え方
部品は別に作って組み合わせるまさにDI
newは同じ工場で作ることにあたる >>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のようになる。 工場で例えるなら、
■DIを使わない場合
マザーボードメーカー「メモリを作ってください。作り方や材料の調達は任せます」
■DIを使った場合
マザーボードメーカー「メモリを作ってください。作り方は私が指定します。材料も私が調達します」 >>88>>90
ICチップだって元々はトランジスタとかコンデンサを一つづつ組み上げたものなんだけど、いまは一体化してるよね
あんたはCPUをバラして中からトランジスタ取り出せないから使い物にならないって言いたいの? ■ このスレッドは過去ログ倉庫に格納されています