Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Immutable data holder
Search
haru067
February 28, 2019
Technology
1
1.1k
Immutable data holder
haru067
February 28, 2019
Tweet
Share
More Decks by haru067
See All by haru067
Jetpack Compose: 効果的なComposable関数のAPI設計
haru067
2
6k
いかにしてアプリの起動時間を改善するか
haru067
3
2k
REALITY Androidにおけるマルチモジュール移行
haru067
0
1.3k
ARTのメモリ管理
haru067
8
15k
Other Decks in Technology
See All in Technology
OCI 運用監視サービス 概要
oracle4engineer
PRO
0
4.8k
SSMRunbook作成の勘所_20241120
koichiotomo
2
120
リンクアンドモチベーション ソフトウェアエンジニア向け紹介資料 / Introduction to Link and Motivation for Software Engineers
lmi
4
300k
OCI Network Firewall 概要
oracle4engineer
PRO
0
4.1k
Amazon CloudWatch Network Monitor のススメ
yuki_ink
1
200
DMARC 対応の話 - MIXI CTO オフィスアワー #04
bbqallstars
1
160
強いチームと開発生産性
onk
PRO
33
11k
The Role of Developer Relations in AI Product Success.
giftojabu1
0
120
マルチプロダクトな開発組織で 「開発生産性」に向き合うために試みたこと / Improving Multi-Product Dev Productivity
sugamasao
1
300
信頼性に挑む中で拡張できる・得られる1人のスキルセットとは?
ken5scal
2
530
BLADE: An Attempt to Automate Penetration Testing Using Autonomous AI Agents
bbrbbq
0
290
スクラム成熟度セルフチェックツールを作って得た学びとその活用法
coincheck_recruit
1
140
Featured
See All Featured
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
44
2.2k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.5k
Code Reviewing Like a Champion
maltzj
520
39k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
860
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
Visualization
eitanlees
145
15k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Building an army of robots
kneath
302
43k
Transcript
Immutable data holder 2019/02/28 potatotips #59
よくある話 タップしてユーザのプロフィールを表示 λοϓ
MVVMによる実装 • ユーザIDを引数としてViewModelがRepository からfetch • pro leはDataBindingを通じてViewに表示 fun load(userId: String)
= profileRepository.fetchProfile(userId) { profile.value = it } ProfileViewModel.kt
MVVMによる実装 • ユーザIDを引数としてViewModelがRepository からfetch • pro leはDataBindingを通じてViewに表示 fun load(userId: String)
= profileRepository.fetchProfile(userId) { profile.value = it } ProfileViewModel.kt
MVVMによる実装 • ユーザIDを引数としてViewModelがRepository からfetch • pro leはDataBindingを通じてViewに表示 fun load(userId: String)
= profileRepository.fetchProfile(userId) { profile.value = it } ProfileViewModel.kt var profile = MutableLiveData<Profile>()
MVVMによる実装 • ユーザIDを引数としてViewModelがRepository からfetch • pro leはDataBindingを通じてViewに表示 fun load(userId: String)
= profileRepository.fetchProfile(userId) { profile.value = it } ProfileViewModel.kt var profile = MutableLiveData<Profile>()
MVVMによる実装 • ユーザIDを引数としてViewModelがRepository からfetch • pro leはDataBindingを通じてViewに表示 fun load(userId: String)
= profileRepository.fetchProfile(userId) { profile.value = it } ProfileViewModel.kt var profile = MutableLiveData<Profile>() ͳΜͱ͔͠ͳ͍ͱɾɾɾɾ
Lv1: mutableな変数宣言をやめる 知らないうちにobserveできなくなってしまう val に書き換えでimmutableに var data = MutableLiveData<String>() data.observe(this,
Observer { print(it) }) data.value = "hello" data = MutableLiveData() data.value = "world" // ͜͜observe͞Εͳ͍ var profile = MutableLiveData<Profile>() val profile = MutableLiveData<Profile>()
Lv2: mutableなデータを公開しない 変数をvalにしてもオブジェクト自体はまだmutable ViewがViewModelのデータを変更できてしまう 外からはread onlyなデータだけが見える形にする val data =
MutableLiveData<String>() data.value = "hello" data.value = "world" // いくらでも更新できる private val _profile: MutableLiveData<Profile>() val profile: LiveData<Profile> get() = _profile val profile = MutableLiveData<Profile>()
良さそう? まあよさそう。だが、、 privateとはいえViewModel内なら書き換え可能 • ViewModelが肥大化したら多分事故る •
そもそも2つも変数を宣言するのはくどい private val _profile: MutableLiveData<Profile>() val profile: LiveData<Profile> get() = _profile ProfileViewModel.kt
Lv3: そもそもmutableにしない switchMapを使いimmutableな定義に private val _userId = MutableLiveData<String>() … val
profile: LiveData<Profile> = Transformations.switchMap(_userId){ profileRepository.getProfile(it) }
Lv3: そもそもmutableにしない switchMapを使いimmutableな定義に private val _userId = MutableLiveData<String>() … val
profile: LiveData<Profile> = Transformations.switchMap(_userId){ profileRepository.getProfile(it) } userIdの変更を監視
Lv3: そもそもmutableにしない switchMapを使いimmutableな定義に private val _userId = MutableLiveData<String>() … val
profile: LiveData<Profile> = Transformations.switchMap(_userId){ profileRepository.getProfile(it) } IDに変更があればfetch
Lv3: そもそもmutableにしない switchMapを使いimmutableな定義に private val _userId = MutableLiveData<String>() … val
profile: LiveData<Profile> = Transformations.switchMap(_userId){ profileRepository.getProfile(it) }
Lv3: そもそもmutableにしない switchMapを使いimmutableな定義に • 「pro leはIDの更新以外を理由に変更できない」 という制約をコード上で表現することができる • 「pro
leはIDをトリガーとしてfetchした値」 というデータのフローが明確になる private val _userId = MutableLiveData<String>() … val profile: LiveData<Profile> = Transformations.switchMap(_userId){ profileRepository.getProfile(it) }
まとめ mutable、やめよう • 変数宣言 • オブジェクトが抱えるデータ LiveDataならswitchMap(Transformations) を使うといい感じに
Bonus: より簡潔に 拡張関数を活用すると良さそう(ktxにある?) Transformations.switchMap(_userId) { profileRepository.getProfile(it) } _userId.switchMap
{ profileRepository.getProfile(it) } fun <X, Y> LiveData<X>.switchMap(body: (X) -> LiveData<Y>): LiveData<Y> { return Transformations.switchMap(this, body) } 長い シンプル https://github.com/google/iosched ͷ Extensions.kt ΑΓ