JavaからKotlinに書き換えてハマる話
by
Koji Wakamiya
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
JavaからKotlinに 書き換えてハマる話 Kotlin Fest Reject Conference 2019 [非公式]@DeNA
Slide 2
Slide 2 text
自己紹介 Name : Koji Wakamiya Work : Studyplus, inc. Github : @koji-1009 Twitter : @D_R_1009 Blog : https://blog.dr1009.com/ Kotlin歴は2年ちょっと 2
Slide 3
Slide 3 text
MISSION 「学ぶ喜びをすべての人へ」 多くの人がStudyplusを通じて学習のきっかけを見つけ、 学習を楽しく継続できることを実現する。 3
Slide 4
Slide 4 text
StudyplusアプリのKotlin化 ● コミット履歴によると2017年12月ごろにKotlinを追加 ○ 当時のminSDKは15 ○ 2019年9月現在は21 ● 話者がスタディプラスに参加したのは2018年9月 ○ 本日の話は2018年9月から2019年9月に体験した物事がベースになってます 4
Slide 5
Slide 5 text
JavaからKotlinへの書き換え状況 ● 2018年7月末 ○ Java : 75,000行 ○ Kotlin : 20,000行 5
Slide 6
Slide 6 text
JavaからKotlinへの書き換え状況 ● 2019年8月末 ○ Java : 19,000行 ○ Kotlin : 72,000行 6
Slide 7
Slide 7 text
JavaからKotlinへの書き換え状況 ● 2019年9月9日(本日) ○ Java : 15,000行 ○ Kotlin : 74,000行 7
Slide 8
Slide 8 text
JavaからKotlinへの書き換え状況 8 2018年7月 2019年8月末 2019年9月9日
Slide 9
Slide 9 text
お品書き ● 2つのインスタンス化メソッドと NonNull ● 共通データクラス(神データクラス) ● 使い回されるデータクラス ● onActivityResult ● R8 9
Slide 10
Slide 10 text
2つのインスタンス化メソッドとNonNull 状況: AFragment.newInstance(Hoge hoge); AFragment.newInstance(Hoge hoge, Fuga fuga); 問題: 1. hogeがNonNull/Nullableのケースが存在する 2. fugaをNonNullとして扱わなければならないが、 レアケースでしか利用されない 10
Slide 11
Slide 11 text
2つのインスタンス化メソッドとNonNull 防ぐためには?: 1. インスタンス化メソッドの引数は必ずクラス内の利用箇所全てを確認する 2. lateinit varによる対応は市場クラッシュを引き起こすので、 valの利用を必ず検討する 11
Slide 12
Slide 12 text
共通データクラス(神データクラス) 状況: 1. 複数のSNS連携完了を伝えるデータクラスが 1つにまとめられている 2. 複数の型要素があるJsonをパースするため、 全要素を持つ1つのデータクラスが作成されている 問題: 1. 防御的にNullableで宣言して、動作を見ながら確認する必要が生じる 2. GsonからMoshiへ移行した際に、JsonDataExceptionの恐れがある 12
Slide 13
Slide 13 text
共通データクラス(神データクラス) 防ぐためには?: 1. @NonNull/@Nullableアノテーションをデータクラスにつける 2. 抽象クラスを利用するなど、全部入りクラス作成を避ける 13
Slide 14
Slide 14 text
使い回されるデータクラス 状況: 複数のビジネスロジックがデータクラスを使いまわした結果、 複数のコンストラクタがあるデータクラスが作成されていた 問題: 1. 複数のクラスに応じたプロパティ追加の結果、 NonNullの保証がない 2. 複数のコンストラクタが存在する 14
Slide 15
Slide 15 text
使い回されるデータクラス どう対応するか: 基本的にKotlin Data Classの利用を行うが、いくつかアプローチがある 1. secondary constructorを利用する 2. 利用クラスをKotlin化し、名前付き引数を利用する 3. Java + @JvmOverloadsの利用も可能だが、 引数のパターンによっては単に複雑性をますため注意 15
Slide 16
Slide 16 text
onActivityResult 状況: onActivityResult処理が含まれているActivityをKotlin化したところ、 dataがnullのケースでクラッシュが発生 問題: 1. onActivityResultは古いAPIのためアノテーションが付与されていない 2. Nullableな値をNonNullとしてメソッドをoverrideしても、 エラーは発生しない 16
Slide 17
Slide 17 text
onActivityResult どう対応するか: 1. あらかじめJavaのonActivityResultメソッドを アノテーション付きのメソッドに書き換えてから Kotlin化する 2. Kotlin化されたコードのonActivityResultメソッドを 置換機能で全て修正する ※ support lib 27.1.1のDiffUtil.ItemCallbackを、support libのpathがおかしい状態で追加した時にも同じような 問題が発生することがある (28.0.0以降ではNonNull扱いとなっているため問題なし ) 17
Slide 18
Slide 18 text
R8 状況: R8対応が必要になるケースが増えた (AGP3.4以上でデフォルト有効化、 Kotlin Coroutines 1.3系やOkHttp4系などのビルドクラッシュ) 問題: 1. Gson使っていると(そのままでは)ダメ a. https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md b. ビルド時ではなく実行時に問題が見つかるため、発見が難しい 18
Slide 19
Slide 19 text
R8 どう対応するか: 0. 対応しない(各種ライブラリ対応を待つ) 1. .proファイルの指定を頑張る 2. データクラスのKotlin化 + Moshi-Codegenへ移行する ※なおKotlin Coroutinesを利用している場合には、 Dispatchers.Main初期化遅延問題のためR8移行が望ましい 19