DroidKaigi2021

# Index
1.プロダクトレベルで必要になるJetpackComposeテクニック
2.Master Of Lifecycle
3.長く生きるコードベースの「品質」問題に向き合う

## 1.プロダクトレベルで必要になるJetpackComposeテクニック

#### Android Jetpackとは
Android Jetpackとは、Android公式開発者ページにある通り、
ベストプラクティスを集めたライブラリである。ボイラープレートコード（ほぼ固定化されたよく出てくるコード）を減らし
Androidバージョンやデバイスが変わっても一貫して機能するコードの作成を助け、
コーディングの負担を軽減する。

Android Jetpackは、4つのカテゴリに分類される。
![スクリーンショット 2021-12-05 14.56.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/2c081f92-e46b-f5ef-4dc9-10b151e04ee2.png)

#### JetpackComposeとは
Jetpackに含まれる、ネイティブUIをビルドするためのAndroid最新ツールキット。
AndroidのUI開発を簡素化し、加速する。
少ないコード、パワフルなツール、直感的なKotlinAPIを使用して
アプリをすぐに動かすことができる。

#### JetpackComposeのサンプルを用いて、画面遷移の実装を行う
|JetpackComposeサンプル|Activity生成数|画面遷移|
|---|---|---|
|Crane|複数Activity|Activity遷移、Fragment差し替え|
|Jetchat、Jetsurvey|1Activity|Fragment差し替え|
|JetNews、JetCaster、Rally、Owl|1Activity|Compose|

補足）
Activity・・・一つの枠を表示するのに向いている
Fragment・・・タブやマルチメイン画面など、複数の枠を表示するのに向いている　　　
　　　　　　　　Activity上で動く
Compose・・・状態ごとに画面を持つという形式

#### JetpackComposeにおける、必要な機能の検索手順
##### ①リファレンスをみる
・androidx.compose.*の Top-level functions summary
・androids.compose.materialのComponents

必要な機能の検索は、リファレンスをみて探すのが一番早い
必要なパッケージは大体、androidx.compose.foundationか、androidx.compose.materialにある

URL）
・androidx.compose.foundation
https://developer.android.com/reference/kotlin/androidx/compose/foundation/package-summary?hl=ja

・androidx.compose.material
https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary?hl=ja

##### ②accompanistにないか調べる
URL）
https://github.com/google/accompanist

・JetPack Composeの便利ライブラリ集
　・Swipe to Refresh
　・Pager
　・…

もともとはGoogle開発社個人のリポジトリにあったものだが、Jetpackの方に移動されてきた
本体にない時はここをチェックする
時々みると新しいものが増えていたりする

##### ③Kotlin Slackのcomposeチャンネルで検索する
URL）
https://kotlinlang.slack.com/
※https://kotlinlang.org/community/ から招待をリクエストできる

どうもそれらしいものがない、または、ありそうだけどどれか良くわからない場合に調べる

##### ④JetpackComposeのサンプルコードを読む
URL）
・Android Coad Search
https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/

JetpackComposeの機能はサンプルが用意されていることが多い

Kotlin slackやstack overflowで見つけた機能のサンプルがないか
Android Code Searchで調べる

それでも見つからない場合はsampleでありそうな名前（materialdesignなど）で調べる
accompanistで見つけた名前などで検索すると引っかかることもある

##### ⑤JetpackCompose Roadmapをチェックする
URL）
https://developer.android.com/jetpack/androidx/compose-roadmap

今後の実装予定が公開されている
・自分で実装するか、用意されるまで待つかの判断材料になる

それでも見つからない場合は、リリース予定のロードマップをみる

それでも見つからない場合は自分で実装するか、3rdParty製ライブラリを利用する
UIパーツはライブラリを探すよりかは自分で実装した方が速い
それ以外は大体は本体かaccompanistかcoilで対応している

##### まとめ
JetpackやJetpackに含まれるJetpackComposeを使うことで開発スピードを上げられる。

### 2.Master Of Lifecycle

#### ライフサイクルとは
例えばActivityにはライフサイクルというものがあり
Activityの生成から破棄までの周期（状態遷移）を表したものである。

##### Activityのライフサイクル
![activity_lifecycle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/8d5bcb99-9862-f132-a7cb-6015967e2c93.png)

##### ライフサイクルを理解した方が良い理由
ライフサイクルを理解しなくても、「動く」アプリを作ることができる
しかし、「より良いアプリ」を作るためには理解しておいた方が良い

・不要に端末リソースを消費しない
・無駄なネットワーク通信をしない
・クラッシュしない

##### 不要な端末リソース消費として、メモリリークがある
メモリリークとは確保メモリの解放漏れのことであり、例えば以下により起こる
・生存期間が長いインスタンスAが、生存期間が短いインスタンスBを強参照する
・非同期処理のキャンセル忘れ

メモリリークを起こさないために
・不必要になったタイミングでインスタンスの解放、処理を終了する必要がある
・Androidでは、ライフサイクルを利用することで、適切なタイミングで解放することができる

##### Activityのライフサイクルを適用する
・Activityにはライフサイクル実装を行うために、コールバックメソッドが定義されている
ライフサイクルの表にもある、以下メソッド
onCreate()、onStart()、onRestart()、onResume()、onPause()、onStop()、onDestroy()

・アクティブ・非アクティブの状態変化を受け取ることができ、適切に処理を実行することができる

##### 例）ライフサイクルに従った、UIの更新
UIの更新でやりたいこと
・UIの構成に必要なデータを、非同期に取得し、取得したデータをUIに反映したい
・常に最新のデータを保つ
・画面が非アクティブの時はUIを更新しない
・画面回転など、Activity再生成時にデータを保持する

ViewModel
・UIの構成に必要なデータを保持するクラス
・Activityが再生成されても、データを保持することができる

・ViewModelを使うことで、Activityの再生成、プロセスデスを乗り越えてデータを保持できる
・次に、そのデータのUIへの通知方法について考える

LiveData
・値が変更されたら、ライフサイクルの状態に応じてUIに通知する
　・アクティブ時に通知する
　・非アクティブ時には通知されない

LiveDataビルダー
・必要なデータをコルーチン（非同期処理）を使い、取得することができる
・指定した時間非アクティブになったら、処理を終了する

LiveDataのまとめ
・LiveDataを使うことで、ライフサイクルに合わせたデータ更新が可能になる
・ViewModelと組み合わせると、Activity再生成時に、効率良く画面復帰ができる
・LiveDataビルダーも使うと、処理のキャンセルもできる

まとめ
・ライフサイクルは「良いアプリを作る」ために必要
・アプリをライフサイクルと協調して動かすことで、端末のリソースを効率良く使うことができる
・ViewModel、LiveData、LiveDataビルダーを使うことで、UIの更新を効率良くできる

### 3.長く生きるコードベースの「品質」問題に向き合う

#### はじめに

現場において大規模開発チームで何チームもある場合、こういうことがある

・他のチームが書いているコードの内容がよく分からない

ここでは、LineのAndroidクライアントチームが行っていることを紹介する

話の前提
・スクラム開発
・バージョン管理にGitを利用

↓TEAM Aの中でやっていることはわかるがTEAM Bの人にはわからない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/e6c90649-174f-3a5f-42ea-9035d0185dbb.png)

↓新しいルールやライブラリを作っても特定のチームは反映できていない状況が起こる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/beaadf8c-13d0-86f3-af00-f8ed52904fc6.png)

これらを解消するために、コンテキスト（歴史や背景）を記録していく。
これは、世間一般で行っていることだが

LineAndroidクライアントチームでは、加えて
・ソースコードについてコンテキストなしで読めるようにする
　取り組みを行っている
・チームの垣根を壊して、チーム間での知識共有、技術共有、
　開発文化の共有を行っている

##### 具体的に落とし込んだのが次の５つになる
・2フェーズレビュー

・構造ドキュメント

・コード作成のベストプラクティス作成

・技術コンサルタント

・レビュー委員会

##### チーム内のレビューでは、以下のような問題がある
・依頼者とレビュー者が固定化されてしまう
・チームをまたがったレビューが行いにくくなる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/8e7133ea-518e-71fc-7a9d-c4609a27b777.png)



##### これを解決するためにレビューを2段階に分ける
①まずチーム内で知識のある人が1stレビューを行う

②次に、プルリクエストを検知するbotを通してランダムで
　slack通知して選出された他チームの何も知らない人に
　2ndレビューをしてもらう
　→背景なしにコードが読めるかどうかをチェックすることができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/ab469123-2b27-b854-2124-d272c5964a32.png)

##### 2フェーズレビューの利点として、
①レビュアー同士でフィードバックができる
　→1stレビュアーで何か見落としがあった場合に、
　　2ndレビュアーが1stレビュアーにフィードバックすることができる

②チームの垣根を超えたレビューをすることになるので
　チームの垣根を超えた知識共有ができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/5dd4f04c-7a83-d939-801e-ff019baf4d9e.png)

##### ・2フェーズレビューを使うことによって、プルリクエストの範囲で
コンテキストなしにコードが読めるかチェックできる

だが、プルリクエストを複数合わせた「構造」で見たときに分からない
→個々ではわかるけど、まとまると理解できない

　それを解決するのが、次の構造ドキュメント

##### 構造ドキュメント
構造ドキュメントは実装を始める前にドキュメントを書く
これにより技術的な問題点を明確にできる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/c1131526-f03e-6f75-a37c-6b9097b5f4b3.png)

##### ウォーターフォールの詳細設計との大きな違い
→フォーマットがないこと、好きなものを好きなだけ書く

　もう一つの大きな違いとして、実装して問題がある場合、
　構造ドキュメントに立ち戻って修正する

##### 構造ドキュメントに書くこと
・やることとゴール

・背景

・クラス図（抽象図、具象図）やモジュール図

・Modelクラスの定義
　→開発の規模に応じて省略

・タスクで、セキュリティ・プライバシー・パフォーマンスについて懸念点がある場合は、
　その旨をドキュメントに残す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/e8fed65c-73fa-e1a8-6140-61b8a74c404f.png)

##### LINE Androidクライアントチームが構造ドキュメントを実際に導入して得られた知見
①構造ドキュメントを必須とするべきはない
　１、２日で終わるようなタスクでは必須にしてしまうと
　かえって生産性が落ちてしまう
　→例えば2週間以上とか中・大規模のタスクで構造ドキュメントを書くようにするといい

②よく話し合ってから書く
　話し合ってから書くようにするとより手戻りが少なくなる

③構造ドキュメント自体が背景などを示すコンテキストになる
　プルリクエストのdiscriptionなどにリンクとして残しておくと、あとあと役に立つ

##### 2フェーズレビューや構造ドキュメントは開発プロセスを改善するのに役立つ
だが、実際のコード改善はこれではできない
→LineのAndroidクライアント開発においては、発表が8hにも
　及ぶコード作成のベストプラクティスが作成されている

　ベストプラクティスを用いて実装することにより、
　後々のリファクタリングの効率が上がる

##### 例）以下、Account TypeによってUIで表示するBackgroundとAccount Iconを切り分けたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/765a5d85-4d33-5f96-f30a-36e8af090fb4.png)

##### 関数を作成する方法として、Account typeで分ける方法とUIで分ける方法がある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/0fd1038a-60b7-48ac-3626-23ce4c06ffdb.png)

##### 結論を先に言うと、UIによって分けるべきであり、Account typeで分けてはならない

なぜそうした方がいいのか
→読みやすさ、外的要因に左右されない、
　将来のリファクタリングのしやすさ

##### 以下のCase1はAccount Typeで関数分けした
→関数名を見ても何がしたいか分からない
##### 以下のCase2はUIで関数分けした
→関数名を見ると何をするかが分かる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/673372cd-d578-f3b1-2f03-ce487861c731.png)

##### 2フェーズレビュー、構造ドキュメント、ベストプラクティス作成

これらは全てのチームに採用してほしいが
全てのチームが全てのルールを更新するのは難しい
→これを解決するのが技術コンサルタント

##### 技術コンサルタント
シニアエンジニアがチーム内でコードレビューを行うが
その際、コードだけではなく、知識共有やプロセスの改善点も
フィードバックする

レビューを受けた人は、構造ドキュメントやソース構造を修正する
→コードだけでなくプロセスや構造を覚えスキルアップする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/5c7af8b9-816b-e29b-77e1-f3da6335d8d4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/3308cf2b-03d9-aeed-9151-b8fc5b84daeb.png)

##### レビュー時の観点
①プロジェクトルール
関係者の集まり方が正しいか、プラットフォームの使い方が正しいか

②タスクのマネジメント方法
話し合いの仕方、構造ドキュメントの書き方、スケジュールの改善の仕方

③アーキテクチャデザイン
レイヤーの切り方が正しいか、依存関係の貼り方が正しいか

④コード詳細
名前の付け方、ロジックのフロー

##### 技術コンサルタントで影響するのは特定のチームでしかない
より効率的にチーム間で知識を共有するためにレビュー委員会を行う

##### レビュー委員会
やること
・チームに属さないシニアエンジニア数名を配置し
　すでにマージ済みのプルリクエストを各チームから送る
　それをレビューしてフィードバックする

・シニアエンジニアは１週間に１回これをレポートとしてまとめ
　全チームに共有する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/4c98b16c-c463-7cf0-d3d9-05513dc0f888.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355942/c0906cb5-0113-70a3-96e5-ab4dd01e3088.png)

##### まとめ
・2フェーズレビュー
チームの垣根を越えて知識を共有できる
コンテキストなしでもコードが読めるようになる

・構造ドキュメント
コンテキスト（歴史や背景）を残す

・コード作成のベストプラクティス作成
のちのちのリファクタリングがしやすくなる

・技術コンサルタント
チーム内でシニアエンジニアの知識を共有することにより、
エンジニアのスキルアップ

・レビュー委員会
全チームにシニアエンジニアの知識が行き渡る


結果として、大規模開発でのコード品質が長い間に渡って保たれていく