Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
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.3k
Immutable data holder
haru067
February 28, 2019
Tweet
Share
More Decks by haru067
See All by haru067
Jetpack Compose: 効果的なComposable関数のAPI設計
haru067
2
7.5k
いかにしてアプリの起動時間を改善するか
haru067
3
2.2k
REALITY Androidにおけるマルチモジュール移行
haru067
0
1.4k
ARTのメモリ管理
haru067
8
15k
Other Decks in Technology
See All in Technology
Security Diaries of an Open Source IAM
ahus1
0
120
タグ付きユニオン型を便利に使うテクニックとその注意点
uhyo
2
700
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.3k
Design System Documentation Tooling 2025
takanorip
2
940
会社紹介資料 / Sansan Company Profile
sansan33
PRO
11
390k
こがヘンだよ!Snowflake?サービス名称へのこだわり
tarotaro0129
0
110
Master Dataグループ紹介資料
sansan33
PRO
1
4k
Bill One 開発エンジニア 紹介資料
sansan33
PRO
4
16k
pmconf2025 - 他社事例を"自社仕様化"する技術_iRAFT法
daichi_yamashita
0
630
.NET 10 のパフォーマンス改善
nenonaninu
2
4.8k
Oracle Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
0
650
法人支出管理領域におけるソフトウェアアーキテクチャに基づいたテスト戦略の実践
ogugu9
1
180
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Rails Girls Zürich Keynote
gr2m
95
14k
Faster Mobile Websites
deanohume
310
31k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.1k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
700
Documentation Writing (for coders)
carmenintech
76
5.2k
The Language of Interfaces
destraynor
162
25k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Statistics for Hackers
jakevdp
799
230k
Designing for humans not robots
tammielis
254
26k
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 ΑΓ