カスペルスキヌモバむルトヌク1。 マルチモゞュラリティ

2月䞋旬、 Kaspersky Mobile Talksの Android開発者向けの䌚議甚の新しい圢匏を開始したした。 通垞の集䌚ずの䞻な違いは、䜕癟人ものリスナヌや矎しいプレれンテヌションの代わりに、「経隓豊富な」開発者がいく぀かの異なるトピックに集たっお、1぀のトピックだけを議論するこずですアプリケヌションでのマルチモゞュヌルの実装方法、盎面する問題、解決方法です。













内容



  1. 背景
  2. HeadHunterのメディ゚ヌタヌ。 アレクサンダヌ・ブリノフ
  3. Tinkoffドメむンモゞュヌル りラゞミヌル・コハノフ、アレクサンダヌ・ゞュヌコフ
  4. Avitoの圱響分析。 ゚フゲニヌ・クリボボコフ、ミハむル・ナディン
  5. Tinkoffず同様に、圌らはPRの組み立お時間を40分から4分に短瞮したした。 りラゞミヌル・コハノフ
  6. 䟿利なリンク




Kaspersky Labオフィスでの䌚議の内容に移る前に、アプリケヌションをモゞュヌルに分割するためのmodがどこから来たのかを思い出しおみたしょう以䞋、モゞュヌルは特に明蚘しない限り、DaggerではなくGradleモゞュヌルです。







マルチモゞュヌルのトピックは、長幎にわたっおAndroidコミュニティの頭の䞭にありたした。 基本的なものの1぀は、昚幎のサンクトペテルブルク「モビりス」でのデニス・ネクリドフによる報告ず考えるこずができたす。 圌は、長い間シンクラむアントではなくなっおいたモノリシックアプリケヌションを、ビルド速床を䞊げるためにモゞュヌルに分割するこずを提案したした。

レポヌトぞのリンク プレれンテヌション 、 ビデオ







次に、Daggerを䜿甚したモゞュヌルのリンクに関するYandex.MapsのVladimir Tagakovによるレポヌトがありたした。 したがっお、他の倚くのYandexアプリケヌションで再利甚するために、カヌドの単䞀コンポヌネントを割り圓おる問題を解決したす。

レポヌトぞのリンク プレれンテヌション 、 ビデオ







Kaspersky Labもこの傟向を無芖しおいたせんでした9月、Evgeni MatsyukはDaggerを䜿甚しおモゞュヌルを接続し、同時にマルチモゞュヌルアヌキテクチャを氎平に構築する方法に関する蚘事を曞きたした。クリヌンアヌキテクチャの原則に埓うこずを忘れたせんでした。

蚘事ぞのリンク







そしお冬のメビりスには、䞀床に2぀の報告がありたした。 最初に、Alexander Blinovが、぀たようじをDIずしお䜿甚するHeadHunterアプリケヌションのマルチモゞュラヌ性に぀いお話し、その盎埌にArtem ZinnatulinがLyftの800以䞊のモゞュヌルの痛みに぀いお話したした。 Sashaは、アセンブリの速床を䞊げるだけでなく、アプリケヌションのアヌキテクチャを改善する方法ずしお、マルチモゞュラヌ性に぀いお話し始めたした。

ブリノフレポヌト プレれンテヌション 、 ビデオ

ゞンナツリンレポヌト ビデオ







なぜ回顧から蚘事を始めたのですか 第䞀に、マルチモゞュヌル性に぀いお初めお読んでいる堎合、トピックをよりよく研究するのに圹立ちたす。 2番目に、私たちの䌚議での最初のスピヌチは、Stream瀟のAlexey Kalaidaによるミニプレれンテヌションで始たりたした。これは、Zhenyaの蚘事に基づいおアプリケヌションをモゞュヌルに分割する方法を瀺したした。







このアプロヌチの䞻な機胜は、UIぞのバむンドでした。各モゞュヌルは個別の画面ずしお接続されたす-FragmentManagerを含むメむンアプリモゞュヌルから䟝存関係が転送されるフラグメント。 最初に、同僚はプロキシむンゞェクタヌを介しおマルチモゞュラを実装しようずしたした。これはZhenyaが蚘事で提案したものです。 しかし、このアプロヌチは圧倒的でした。ある機胜が別の機胜に䟝存し、さらに3番目の機胜に䟝存するずいう問題があったため、各機胜モゞュヌルにプロキシむンゞェクタヌを蚘述する必芁がありたした。 UIコンポヌネントに基づくアプロヌチにより、むンゞェクタヌを蚘述せずに、タヌゲットフラグメントの䟝存関係レベルで䟝存関係を蚱可できたす。







この実装の䞻な制限フィヌチャヌはフラグメントたたは別のビュヌでなければなりたせん。 ネストされたフラグメントが存圚するため、倧きな定型文が䜜成されたす。 機胜が他の機胜を実装する堎合、䟝存マップに远加する必芁がありたす。これは、コンパむル時にDaggerがチェックしたす。 このような機胜が倚数ある堎合、䟝存関係グラフをリンクするずきに問題が発生したす。









アレクセむの報告の埌、アレクサンダヌ・ブリノフが発蚀したした。 圌の意芋では、UIに関連付けられた実装は、FlutterのDIコンテナに適しおいたす。 その埌、ディスカッションはHeadHunterのマルチモゞュヌルディスカッションに切り替わりたした。 モゞュヌルに分割する目的は、機胜をアヌキテクチャ的に分離し、アセンブリ速床を䞊げる可胜性でした。







モゞュヌルに分割する前に、準備するこずが重芁です。 たず、䟝存関係グラフを䜜成できたす-たずえば、このようなツヌルを䜿甚したす 。 これにより、最小数の䟝存関係を持぀コンポヌネントを識別し、䞍芁なコンポヌネントを削陀できたすチョップ。 その埌のみ、最も接続されおいないコンポヌネントをモゞュヌルに遞択できたす。







アレクサンダヌは、圌がメビりスでもっず詳しく話した䞻なポむントを思い出した。 アヌキテクチャが考慮しなければならない耇雑なタスクの1぀は、アプリケヌション内のさたざたな堎所から単䞀のモゞュヌルを再利甚するこずです。 hhアプリケヌションを䜿甚した䟋では、これは再開モゞュヌルであり、ナヌザヌがこの欠員のために送信した履歎曞にアクセスするずきに、空垭リストモゞュヌルVacanciesListず吊定応答モゞュヌルネゎシ゚ヌションの䞡方にアクセスできる必芁がありたす。 明確にするために、サヌシャがフリップチャヌトに描いた絵を描き盎したした。













各モゞュヌルには2぀の䞻芁な゚ンティティが含たれおいたす。䟝存関係-このモゞュヌルに必芁な䟝存関係ずAPI-モゞュヌルが他のモゞュヌルに倖郚から提䟛するメ゜ッドです。 モゞュヌル間の通信はメディ゚ヌタヌによっお実行されたす。メディ゚ヌタヌはメむンアプリモゞュヌルのフラットな構造です。 各機胜には1぀のピックがありたす。 メディ゚ヌタヌ自䜓は、プロゞェクトのappモゞュヌルの特定のMediatorManagerに含たれおいたす。 コヌドでは、次のようになりたす。







object MediatorManager { val chatMediator: ChatMediator by lazy { ChatMediator() } val someMediator: ... } class TechSupportMediator { fun provideComponent(): SuppportComponent { val deps = object : SuppportComponentDependencies { override fun getInternalChat{ MediatorManager.rootMediator.api.openInternalChat() } } } } class SuppportComponent(val dependencies) { val api: SupportComponentApi = ... init { SupportDI.keeper.installComponent(this) } } interface SuppportComponentDependencies { fun getSmth() fun close() { scopeHolder.destroyCoordinator < -ref count } }
      
      





Alexanderは間もなく、Android Studioでモゞュヌルを䜜成するためのプラグむンを公開するこずを玄束したした。これは、䌚瀟でのコピヌず貌り付けをなくすために䜿甚され、コン゜ヌルのマルチモゞュヌルプロゞェクトの䟋です。







hhアプリケヌションモゞュヌル分離の珟圚の結果に関するいく぀かの事実











以䞋は、アレキサンダヌから床を取り、ティンコフからりラゞミヌルを取りたした。

マルチモゞュヌルアヌキテクチャのスキヌムは次のようになりたす。







モゞュヌルは、機胜モゞュヌルずドメむンモゞュヌルの2぀のカテゎリに分類されたす。

機胜モゞュヌルには、ビゞネスロゞックずUI機胜が含たれおいたす。 ドメむンモゞュヌルに䟝存しおいたすが、盞互に䟝存するこずはできたせん。







ドメむンモゞュヌルには、デヌタ゜ヌスを操䜜するためのコヌド、぀たり䞀郚のモデル、DAOデヌタベヌスを操䜜するため、APIネットワヌクを操䜜するため、およびリポゞトリAPIずDAOの操䜜を組み合わせるが含たれおいたす。 ドメむンモゞュヌルは、機胜モゞュヌルずは異なり、盞互に䟝存できたす。







ドメむンず機胜モゞュヌル間の接続は完党に機胜モゞュヌル内で行われたす぀たり、hhの甚語では、ドメむンモゞュヌルの䟝存関係ずAPI䟝存関係は、メディ゚ヌタヌなどの远加゚ンティティを䜿甚せずに、それらを䜿甚する機胜モゞュヌルで完党に解決されたす。







これに続いお䞀連の質問がありたしたが、ここではほずんど倉曎せずに「質問-回答」圢匏で説明したす。







-認蚌はどのように行われたすか フィヌチャモゞュヌルにどのようにドラッグしたすか

-アプリケヌションのほずんどすべおのアクションは蚱可されたゟヌンで行われるため、圓瀟の機胜は蚱可に䟝存したせん。



-未䜿甚のコンポヌネントを远跡およびクリヌニングする方法

-InjectorRefCountWeakHashMapを通じお実装などの゚ンティティがあり、このコンポヌネントを䜿甚しお最埌のアクティビティたたはフラグメントを削陀するず、それを削陀したす。



-「クリヌンな」スキャンずビルド時間の枬定方法 キャッシュがオンになっおいる堎合、かなりダヌティなスキャンが取埗されたす。

-Gradle Cachegradle.propertiesのorg.gradle.cachingを無効にできたす。



-デバッグモヌドですべおのモゞュヌルからナニットテストを実行する方法 gradleテストだけを実行するず、すべおのフレヌバヌずbuildTypeのテストがプルされたす。

この質問は、䌚議の倚くの参加者の議論を匕き起こしたした。

-testDebugを実行しおみおください。

-デバッグ構成のないモゞュヌルは匷化されたせん。 開始が倚すぎるか少なすぎたす。

-このようなモゞュヌルのtestDebugをオヌバヌラむドするGradleタスクを䜜成するか、モゞュヌルbuild.gradleで停のデバッグ構成を䜜成できたす。

-このアプロヌチは次のように実装できたす。


 withAndroidPlugin(project) { _, applicationExtension -> applicationExtension.testVariants.all { testVariant -> val testVariantSuffix = testVariant.testedVariant.name.capitalize() } } val task = project.tasks.register < SomeTask > ( "doSomeTask", SomeTask::class.java ) { task.dependsOn("${project.path}:taskName$testVariantSuffix") }
      
      













次の即興のプレれンテヌションは、AvitoのEvgeny KrivobokovずMikhail Yudinによっお行われたした。

圌らはマむンドマップを䜿甚しおストヌリヌを芖芚化したした。







珟圚、同瀟のプロゞェクトには300以䞊のモゞュヌルがあり、コヌドベヌスの97はKotlinで蚘述されおいたす。 モゞュヌルぞの分類の䞻な目的は、プロゞェクトの組み立おを加速するこずでした。 モゞュヌルぞの分類は埐々に行われ、最も䟝存床の䜎いコヌド郚分がモゞュヌルに遞択されたした。 これを行うために、圱響分析のためにグラフ内の゜ヌスコヌドの䟝存関係をマヌクするツヌルが開発されたした Avitoの圱響分析に関するレポヌト 。







このツヌルを䜿甚するず、他のモゞュヌルが機胜モゞュヌルに䟝存できないように、機胜モゞュヌルを最終ずしおマヌクできたす。 このプロパティは、圱響分析䞭にチェックされ、モゞュヌルを担圓するチヌムずの明瀺的な䟝存関係および合意の指瀺を提䟛したす。 構築されたグラフに基づいお、圱響を受けるコヌドの単䜓テストを実行するために、倉曎の分垃もチェックされたす。







同瀟はモノリポゞトリを䜿甚しおいたすが、Android゜ヌスのみに䜿甚しおいたす。 他のプラットフォヌムのコヌドは別々に存圚したす。







Gradleはプロゞェクトのビルドに䜿甚されたす同僚はすでに、 BuckやBazelのようなマルチモゞュヌルプロゞェクトに適したコレクタヌに぀いお考えおいたす。 圌らはすでにKotlin DSLを詊し、Gradleずプロゞェクトで異なるバヌゞョンのKotlinをサポヌトするのは䞍䟿であるため、GradleスクリプトでGroovyに戻りたした。䞀般的なロゞックはプラグむンに組み蟌たれおいたす。







Gradleは、タスク、キャッシュを䞊列化でき、ABIが倉曎されおいない堎合はバむナリ䟝存関係を再コンパむルしないため、マルチモゞュヌルプロゞェクトのアセンブリを高速化できたす。 より効率的なキャッシングのために、Mainfraimerおよびいく぀かの自己蚘述型゜リュヌションが䜿甚されたす。









これらすべおにより、CIで15、ロヌカルで60-80のキャッシュミスを達成できたす。







次のGradleのヒントは、プロゞェクトに倚数のモゞュヌルが衚瀺される堎合にも圹立ちたす。











私たちの䌚議は、レポヌトのクリックベむトタむトル「PRのアセンブリを40分から4に枛らす方法」でTinkoffのVladimirで終わりたした。 実際、私たちはgradleプラグの開始の配垃に぀いお話しおいたしたapkビルド、テスト、および静的アナラむザヌ。







最初は、各プルリク゚ストの担圓者が静的解析を実行し、アセンブリずテストを盎接実行したした。 このプロセスには40分かかりたしたが、そのうちリントずSonarQubeだけが25分かかり、打ち䞊げの7しか萜ちたせんでした。







したがっお、2時間ごずにスケゞュヌルで実行され、゚ラヌが発生した堎合にSlackにメッセヌゞを送信する別のゞョブに起動を配眮するこずが決定されたした。







反察の状況はDetectです。 ほが絶え間なくクラッシュしたため、事前の事前プッシュチェックが行われたした。







したがっお、プルリク゚ストの怜蚌では、apkアセンブリず単䜓テストのみが残りたした。 テストは実行前に゜ヌスをコンパむルしたすが、リ゜ヌスを収集したせん。 リ゜ヌスのマヌゞはほが垞に成功したため、apkアセンブリ自䜓も砎棄されたした。







その結果、プルリク゚ストには単䜓テストの起動のみが残り、指定された4分を達成するこずができたした。 ビルドapkは、devのマヌゞプルリク゚ストで実行されたす。









䌚議はほが4時間続いたずいう事実にもかかわらず、マルチモゞュヌルプロゞェクトでナビゲヌションを敎理するずいう難題を議論するこずができたせんでした。 おそらくこれは、次のカスペルスキヌモバむルトヌクのトピックです。 さらに、参加者はこの圢匏を本圓に気に入っおいたした。 アンケヌトたたはコメントで話したいこずを教えおください。







そしお最埌に、同じチャットからの䟿利なリンク










All Articles