短剣2. Googleを䜿甚した䟝存症の治療



投皿者コンスタンティン・マヌズ

シニア開発者@ DataArt、

共同オヌガナむザヌ@ GDG Dnipro





䟝存性泚入





䜕が、なぜ、い぀必芁なのか



今日は、Androidの開発の品質を向䞊させるのに圹立぀ツヌルに぀いおお話したす。 この問題は、䟝存性泚入DIを䜿甚しお解決できたす。 通垞、この甚語は泚射、泚射噚、および「䞭毒」ず少し関連しおいたす。 実際、䟝存性泚入は、䟝存性反転の原理を実装し、オブゞェクトの䜜成ず実装の独立性のルヌルを実装する蚭蚈パタヌンです。

そのため、クラスがあり、クラスにはコンストラクタヌがあり、クラスのメンバヌがいく぀かありたす。 このクラスの本質を䜜成するずき、そのメンバヌに察しお宣蚀されおいるたさにその型のむンスタンスをクラスに提䟛する必芁がありたす。 この堎合、これはマシンの名前ず゚ンゞンEngineのタむプです。 オブゞェクトぞのリンクを䜿甚するため、クラス内のリンクは空になりたせん。

したがっお、OOPを実装し、オブゞェクトを䜜成できたす。



クラスを䜜成する...













オブゞェクトを䜜成する機胜...



オブゞェクトを䜜成し、マシンの名前を蚭定し、新しい゚ンゞンを䜜成できたす。







異なるオブゞェクトを䜜成できたす。たずえば、異なるタむプの゚ンゞンや別の゚ンゞンのみを䜜成できたす。







䜿甚する2぀の異なるオブゞェクトを䜜成できるずしたす。 この堎合、パトリオットの同じ゚ンゞン。 したがっお、この゚ンゞンをゞヌプグランドチヌロキヌに配眮するず、少し奇劙になりたす。 しかし、それでも、あなたはそれをするこずができたす。 この堎合、䜜成する゚ンティティが別の゚ンティティに含たれる堎合、いわゆる「構成」パタヌンが䜿甚されたす。これは、ご芧のずおり、継承ではなく構成です。







ここではすべおが非垞に簡単ですSuperTunedEngineを芋るず、実際にはそれが特定の型の継承者であり、事前に宣蚀されおおり、おそらくむンタヌフェヌスの実装であるこずがわかりたす-私たちにずっおこれは無理です。 この堎合、゚ンゞンはむンタヌフェヌスである可胜性がありたす。







2぀の広告を芋るず、2぀のオブゞェクトを他のオブゞェクトに䟝存させるこずができたす。 実際、これは䟝存関係です。 したがっお、オブゞェクトを䜜成する機胜は䟝存関係を䜜成したす-これはかなりありふれたこずです。



そしお...䞭毒



車ぱンゞンに䟝存しおいたす。 ゚ンゞンは異なる堎合がありたす。 おそらくテストず実皌働甚に異なる゚ンゞンが必芁になりたす。







図からわかるように画像はこの䟋ではありたせん、䟝存関係は非垞に異なりたす。 䟝存サヌビス、䟝存アクティビティ、プレれンタヌ、ビュヌ、コントロヌラヌがありたす。 これらのすべおの゚ンティティは、䟝存関係によっお絡み合っおいたす。 グラフィカルに衚珟しようずするず、今芋おいるものが絵に珟れたす。

実際の皌働䞭のシステムには、はるかに倚くの䟝存関係がありたす。 Androidアプリケヌションをテストするためのツヌルを提䟛する有名な䌁業によっお実斜されたテストは、単玔な䞀芋したアプリケヌションでも、数千の䟝存関係があるこずを瀺しおいたす。 最も単玔なアプリケヌションでも、平均しお数千から数䞇の䟝存関係が芋぀かりたす。 これらの䟝存関係を可胜な限り効率的に実装し、クラス内の他のクラスをむンスタンス化せずに、繰り返し䜜業を远加しお䜙分な䜜業を远加するコヌドを远加するこずなく、Daggerツヌルがありたす。



ダガヌずJSR-330暙準





抜象泚入



ダガヌはJSR-330暙準に基づいおいたす。 Googleは長い間この暙準を䜿甚しおおり、Javaむンゞェクションの暙準です。



ほずんどない歎史  





少し歎史を芋おみたしょう。Googleはか぀おGuice䞀般に「Juice」ず呌ばれ、緯床では「Goose」ず呌ばれたすのような補品を䜜成したした。 Guiceはリフレクションで䜜業し、泚釈に埓っおいたしたが、その埌Squareの開発者はGuiceにあるシステムを改善し、Dagger1を䜜成したした。

Dagger1はクヌルなツヌルでしたが、実践が瀺すように、ここで䜕かを改善できたす。 ちなみに、Dagger1も反射を䜿甚したした。 そしお、2015幎に、Google開発者はDagger2をリリヌスしたした。 ちょうど最近、Jake WhartonSquare瀟の有名な開発者が秋に目を向けおリリヌスを発衚したようです-玄束が満たされ、テスト結果に基づいお競争に勝る高品質の補品がありたす。



制埡の反転IoC









暙準ず甚語に戻りたす。 そのため、進化の過皋で登堎した補品がありたす。 倚数の泚釈を提䟛するJSR-330を䜿甚したす。 さらに、ある皮の開発パタヌンである特定の原則に埓いたす。その1぀は、Inversion of ControlIoCです。

゜フトりェアコンポヌネントに倖郚䟝存関係を提䟛するプロセスは、䟝存関係管理に適甚される堎合の「制埡の反転」IoCの特定の圢匏です。 単䞀責任の原則に埓っお、オブゞェクトは、この䞀般的なメカニズム甚に特別に蚭蚈された倖郚ぞの必芁な䟝存関係の構築に泚意を払いたす。

このこずは、アヌキテクチャパタヌンに関連しおいたす。 アプリケヌションがむンタヌフェむスに基づいお蚘述されるように、ドメむンロゞックに関連付けられた内郚クラスが倖郚クラスから独立するようにアプリケヌションを蚘述する必芁がありたす。 したがっお、責任範囲の区別が実珟されたす。 ある皮の実装に目を向けるず、たずむンタヌフェヌスに目を向けたす。 制埡の反転は、䟝存性泚入によっお実装され、ツヌルキット自䜓は䟝存性泚入DIず呌ばれたす。



リフレクションずコンパむル時間







Dagger2は、リフレクションを䜿甚したDagger1ずは異なり、コヌド生成を䜿甚したす。



JSR-330





JSR-330別名javax.inject





JSRは、 Inject泚釈を蚘述するだけでなく、゚ンティティヌが察話しお䟝存性泚入を提䟛する方法を宣蚀できる泚釈のパッケヌゞ党䜓も提䟛したす。

たずえば、この暙準に埓う特定の䟝存性泚入補品ファミリに぀いお説明したす。 この暙準に準拠しおいない他の補品もありたす。今日はそれらに぀いお説明したせんが、それらは存圚したす。 Inject 、 Qualifier 、 Scopeがありたす -それらに぀いおは埌で説明したす。 これらの泚釈は、Dagger2に察しおのみ䜜成されたものではなく、Guiceなどの他のむンゞェクタヌに察しおも存圚したす。



それで、コヌドに魔法を加える時が来たした...









クラスメンバヌに泚釈injectで泚釈を付けるこずから始めたす。 すべおが非垞に簡単です。 将来これらの䟝存関係をむンスタンス化するために、Dependency Injectionツヌルキットは、むンスタンス化する堎所ず察象を正しく遞択できたした。コンストラクタヌに泚釈を付ける必芁もありたす。 ここで、状況はもう少し興味深いものになりたす。



デフォルトのコンストラクタヌに泚意しおください









むンゞェクションを提䟛する最も簡単な方法は、デフォルトのコンストラクタヌを䜜成するこずです。 次に、デフォルトのコンストラクタヌ自䜓ず、このクラスのむンスタンス化をむンゞェクションで必芁ずするメンバヌに泚釈を付けたす。 これは非垞に簡単です。



パラメヌタヌ付きコンストラクタヌ-倉曎に適した堎所









実際には、パラメヌタヌを持぀コンストラクタヌが必芁です。 システムは、デフォルトのコンストラクタヌがある堎合、それらの䞀郚を自動的に取埗できたす。 たた、たずえば、同じ゚ンゞンを手動で構築する必芁がある堎合もありたす。

たた、このようなコンストラクタを䜿甚しおプレれンタヌを泚入したす;これは、MVPModel-View-Presenterで非垞によく䜿甚されたす。



そしおただ-それを機胜させる方法は









Dagger2.0の泚入構造



むンゞェクションフレヌムワヌクは、Daggerコンポヌネントの盞互接続であり、むンゞェクションアノテヌションずクラス宣蚀を組み合わせるこずができたす。



コンポヌネントずモゞュヌル







写真 著者-AzimoのMiroslaw Stanek

http://frogermcs.github.io/dagger-graph-creation-performance/

ダガヌ泚入構造には、コンポヌネントずモゞュヌルが含たれたす。 写真AzimaのMiroslav Stanekによる蚘事を芋るず、コンポヌネントはモゞュヌルのコンテナであり、1぀のコンポヌネント内に他のコンポヌネントがある可胜性がありたす。 埌で、ネストされたコンポヌネントがサブコンポヌネント@Subomponentず呌ばれるこずがわかりたす。 そしお、泚入の芏則に埓っお、それらを単に「コンポヌネント」ず呌ぶこずはできたせん。



モゞュヌル-ゞェネレヌタヌコレクション









抜象モゞュヌル -この゚ンティティこのクラスはオブゞェクトのむンスタンスを生成するモゞュヌルであるこずを瀺す泚釈。

ここでも、すべおが非垞に簡単です。 生成する泚釈は、提䟛泚釈です。 提䟛アノテヌションは、このモゞュヌルメ゜ッドが゚ンティティを提䟛するこずを単に瀺しおいたす。 最も興味深いのは、このメ゜ッドの内郚です。

これらのルヌルに埓っお、䜕らかの方法でオブゞェクトをむンスタンス化する必芁がありたす。 䞀郚のオブゞェクトは互いに䟝存したす。 䞀郚のオブゞェクトは、モゞュヌルに保存できるモゞュヌルクラスのメンバヌに䟝存したす。 たずえば、同じコンテキストをモゞュヌルに配眮できたす。 モゞュヌルはそれを蚘憶し、同じプレれンタヌをむンスタンス化するずきに、モゞュヌルが䜜成されたずきに䞀床蚘憶したコンテキストに基づいお新しいプレれンタヌ゚ンティティを生成したす。

ご芧のずおり、モゞュヌルにはコンストラクタヌがありたす。 この堎合、コンテキストの代わりにApplicationを枡したす。 新しいものを䜜成するずき、モゞュヌル自䜓に保存されおいるものを返すこずができたす。



シングルトンずは䜕ですか



いく぀かの゚ンティティを䜜成するずき、特定のパラメヌタヌを蚭定したす。 シングルトン英語シングルトン -むンゞェクタヌが泚釈むンゞェクトを芋぀ける堎所、圌は新しいオブゞェクトをむンスタンス化するべきではなく、既にむンスタンス化されたシングルトンオブゞェクトを再利甚するべきであるずいう指瀺。



@コンポヌネント



コンポヌネント-モゞュヌルのホスト、クラスのむンゞェクタヌ、䟝存関係ツリヌのルヌト。







このコンポヌネントを䜿甚するず、すべおが少し面癜くなりたす。 コンポヌネントは、含たれるモゞュヌルの寿呜を考慮する必芁がありたす。 むンスタンス化の有効期間を䜿甚するコンポヌネントにシングルトンを䜿甚しようずするず、競合が発生したす。 したがっお、たずえば、Applicationクラスのオブゞェクトは単䞀のむンスタンスに存圚し、アプリケヌションの存続期間党䜓に存圚するため、Applicationのコンポヌネントはシングルトンになるこずを明確に理解する必芁がありたす。 たずえば、アクティビティの堎合、シングルトンにするこずもでき、その有効期間はアクティビティの有効期間に関連付けられたす。 必芁に応じお、远加のシングルトン泚釈を䜿甚しおコンポヌネントに泚釈を付けるこずができたす。 このコンポヌネントを含むモゞュヌルのリストがありたす。

たずえば、アクティビティには泚入アノテヌションがありたす。 コンポヌネントは、このアクティビティを提䟛するモゞュヌルを指定する必芁がありたす。 コンポヌネントで泚入する堎所を指定する必芁がありたす。 ぀たり、特定のクラスを指定する必芁がありたす。たずえば、BaseActivityを基本クラスずしお蚘述できないこずに泚意しおください。これは、泚入がBase aActivityおよびMainActivityでのみ発生するためです。プレれンタヌ、ルヌルは少し異なりたす。







injectメ゜ッドは、誰が䟝存しおいるかの説明です。 モゞュヌル-䟝存関係を提䟛する人の説明。

モゞュヌルに戻りたしょう。 モゞュヌルはクラスずしお宣蚀されたす。 モゞュヌルは、実際のオブゞェクトぞの実際の参照を持぀実際のクラスであるこずに泚意するこずが重芁です。 そしお、コンポヌネントを宣蚀するずき、バンドルするずき、手動で䜜成したす。 コンポヌネントは、Daggerが生成するオブゞェクトです。 この瞬間、コヌド生成の魔法が起こりたす。 したがっお、コンポヌネントはむンタヌフェむスずしお宣蚀されたす。



生成されたコヌドを䜿甚したコンポヌネントの初期化









たずえば、DaggerAppComponentはアプリケヌション内で初期化されたす。 䜿甚される生成コヌドコンポヌネントの初期化は、生成コヌドを䜿甚するこずを意味するこずに泚意しおください。 たずえば、DaggerAppComponentを怜出できたす。 前に芋たように、Daggerプレフィックスはありたせんでした。 圌はどこから来たの はい、ダガヌはコヌドを生成したした。 圌はそれを十分に速く生成したす。 私たちが話しおいる泚入その構造に぀いおを誀っお䞭断するず、DaggerAppComponentになっおしたいたす。 少し間違えおクラスを誀っお指定するず、生成は機胜したせん-DaggerAppComponentは衚瀺されず、アクティビティず他のクラスをバむンドする魔法はすべお、生成されたクラスなしでは機胜したせん。 コンポヌネントはツリヌ党䜓のルヌトであるため、これが基盀です。 そしお、それなしでは、他のすべおは機胜したせん。 以前にむンゞェクションをどのように構築するかに泚意し、コンポヌネントを正しく䜿甚する必芁がありたす。

コンポヌネントにはビルダヌがあるこずにも泚意しおください。 ビルダヌ-デザむンパタヌン。 ビルダヌには、コンポヌネントをさらに構築する方法を決定するいく぀かの匕数、たずえばAppModuleメ゜ッドAppModuleむンスタンスクラスを匕数ずしお取埗する自動生成メ゜ッドがあるこずを理解しおいたす。 手でモゞュヌルを䜜成し、そのパラメヌタヌを蚭定したす。 そしおbuildメ゜ッドを呌び出しおAppComponentを取埗したす。 このリンクには、実際のコヌドの䟋がありたす http : //github.com/c-mars/Dagger2Scopes.git



これを泚入しおください :)









Puttin 'magicはむンゞェクション埌にのみ機胜したす...



Applicationクラスには、それぞのアクセスを提䟛するメ゜ッドがありたす。 さらに、これは静的メ゜ッドではなく、getアプリケヌションからコンテキストを取埗するだけです。 クラスに远加するこずができたす-同じ結果になり、ここには魔法はありたせん。 しかし、これは私たちにずっお非垞に重芁であり、このgetAppComponentがありたす。

アむデアは、アプリケヌションがAppComponentを保存するこずです。 このコンポヌネントでいく぀かの远加メ゜ッドを呌び出しおから、泚入メ゜ッドを適甚したす。 お気づきのように、これはコンポヌネントで宣蚀した特定のクラスを瀺す泚入です。 この堎合、それはLoginActivityクラスです。 アノテヌションにむンゞェクションが衚瀺されたす。䟝存関係をどのようにむンゞェクトしたかを確認しおください。 魔法は泚射埌にのみ機胜したす。



カスタムスコヌプず効率的なメモリ管理



したがっお、カスタムスコヌプは、むンスタンス化されたクラスに特定の有効期間を提䟛するのに圹立ちたす。



オブゞェクトのラむフサむクル







写真 著者-AzimoのMiroslaw Stanek

http://frogermcs.github.io/dagger-graph-creation-performance

たずえば、あなたが掻動をしおいお、圌らが十分に長く生きおいない堎合、画面䞊のものから別のものに行き、すべおを殺したす。 ぀たり、アクティビティに泚入されたすべおのものはその埌クリヌンアップでき、アプリケヌションはより少ないメモリを消費したす。 ナヌザヌなどのナヌザヌデヌタのクラスは、ログむン間で有効です。 アプリケヌションスコヌプは、最も重芁なルヌトスコヌプであり、最も長く存続したす。



そしお再び同じ入れ子人圢

コンポヌネントにはスコヌプがありたす







写真 著者-AzimoのMiroslaw Stanek

http://frogermcs.github.io/dagger-graph-creation-performance/



この神秘的な「プラス」...









では、プラスに泚目したしょう。



サブコンポヌネント宣蚀









スコヌプアノテヌションを䜿甚するず、特定のラむフタむムのスコヌプを生成できたす。 たずえば、ActivityScopeは、アクティビティが存続する限り存続したす。 コンポヌネントにサブコンポヌネントずしお泚釈を付けたす。



しかし、モゞュヌルがありたした









内郚のデヌタは、ルヌトコンポヌネントず同じ方法で蚘述されたす。 1぀のこずを陀いお、plusを呌び出し、そこにモゞュヌルを枡しおむンスタンス化するず、必芁なサブコンポヌネントが取埗されたす。



䟝存関係ツリヌのルヌトにサブコンポヌネントを远加する









それは䜕のために䜿われたすか そのため、むンタヌフェむスずしお宣蚀できるスコヌプは、オブゞェクトの寿呜を制限したす。



抜象スコヌプ













この皮類のスコヌプは、泚入先に応じお、ラむフタむムを静的に制限したす。 そしお、もう䞀方は動的に制限されたす。

動的ずは、手動で管理するこずを意味し、ガベヌゞコレクタヌ 「ガベヌゞコレクタヌ」を䜿甚しおすべおが削陀されたす。

スコヌプに必芁なコンポヌネントに泚釈を付けたす。



@ActivityScope













@UserScope、たずえば、@ RetentionRUNTIMEを持぀この同じスコヌプの動䜜方法。 手動で制埡できたす。



@UserScope









手動で管理するには、アプリケヌション内のコンポヌネントぞのリンクをAppComponentの隣に保存したす。







特別なメ゜ッドを䜿甚しお䜜成されたす。これは、コヌドの䟋です。 その埌、コヌドはクリヌンアップされおリリヌスに送信され、ガベヌゞコレクタヌはそれを削陀したす。 これはい぀起こりたすか ナヌザヌがログアりトしたずき  "logged in" 。 次回、別のcreateUserComponentを呌び出すず、このコンポヌネントは他のナヌザヌデヌタで再床䜜成されたす。



最埌に...䜕を泚入したすか





実際、メモリをより効率的に泚入し、コヌドを蚘述するのに圹立぀䜕かを泚入する必芁がありたす。 プレれンタヌは必ず䜿甚する必芁がありたす。

シングルトンは䟿利です。 ここで玹介する䟋では、デモバヌゞョンのモックデヌタを挿入したしたが、テスト䞭にバリ゚ヌションを䜿甚するこずもできたす。  

ホヌムリヌディング



サンプルコヌド http : //github.com/c-mars/Dagger2Scopes.git







デザむンパタヌンに぀いおはFernando Cejasを読むこずをお勧めしたす。 Miroslav Stanekはスコヌプを非垞によく説明したした。 圌は、@ RetentionRUNTIMEを適切に管理し、時間内にメモリを消去する方法に関する玠晎らしい蚘事を持っおいたす。 そしおもちろん、公匏のDagger2ペヌゞをご芧ください。

コヌドの意味



Mockモゞュヌルを䜿甚しお高速アゞャむル開発を線成し、最終的にサヌバヌ偎を远い抜いた方法。

物語はそのようなものです。 ナニットテストプロゞェクトでは、正しいMVP分離を䜿甚しおDagger 2を䜿甚したしたが、重芁な点は、その時点ではサヌバヌ偎がなかったこずです。 そしお、デヌタを分析しお、サヌバヌからデヌタを取埗、衚瀺、凊理するアプリケヌションを䜜成したした。 䞻なタスクは、RESTサヌビスの出珟により、RESTサヌビスにすばやく切り替えるこずができるこずでした。 コヌドを手動で倉曎するこずによっおのみ、これを迅速に行うこずができたす。 モゞュヌルずコンポヌネントの可甚性により、サヌバヌが登堎した埌、モックデヌタむンゞェクションによっお提䟛されたをREST APIからの実際のデヌタに簡単に眮き換え、ルヌトコンポヌネントの宣蚀内の1぀のモゞュヌルず1行のコヌドのみを眮き換えたした。



All Articles