Download free for 30 days
Sign in
Upload
Language (EN)
Support
Business
Mobile
Social Media
Marketing
Technology
Art & Photos
Career
Design
Education
Presentations & Public Speaking
Government & Nonprofit
Healthcare
Internet
Law
Leadership & Management
Automotive
Engineering
Software
Recruiting & HR
Retail
Sales
Services
Science
Small Business & Entrepreneurship
Food
Environment
Economy & Finance
Data & Analytics
Investor Relations
Sports
Spiritual
News & Politics
Travel
Self Improvement
Real Estate
Entertainment & Humor
Health & Medicine
Devices & Hardware
Lifestyle
Change Language
Language
English
Español
Português
Français
Deutsche
Cancel
Save
Submit search
EN
Uploaded by
Hiroshi Kikuchi
2,751 views
画面状態を抽象化してテスタブル設計ライフを送ろう
Shibuya.apk #17で発表した(する)内容です。
Technology
◦
Read more
3
Save
Share
Embed
Embed presentation
Download
Download to read offline
1
/ 32
2
/ 32
3
/ 32
4
/ 32
Most read
5
/ 32
6
/ 32
7
/ 32
8
/ 32
9
/ 32
10
/ 32
11
/ 32
12
/ 32
13
/ 32
14
/ 32
15
/ 32
16
/ 32
17
/ 32
18
/ 32
19
/ 32
20
/ 32
21
/ 32
22
/ 32
23
/ 32
24
/ 32
25
/ 32
26
/ 32
27
/ 32
28
/ 32
29
/ 32
30
/ 32
31
/ 32
32
/ 32
More Related Content
PPTX
SPAセキュリティ入門~PHP Conference Japan 2021
by
Hiroshi Tokumaru
PDF
ゲームの仕様書を書こう4 仕様書作成で楽をするconfluenceの活用
by
Sugimoto Chizuru
PDF
Spring Boot × Vue.jsでSPAを作る
by
Go Miyasaka
PDF
Tackling Complexity
by
Yoshitaka Kawashima
PDF
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
by
NTT DATA Technology & Innovation
PDF
例外設計における大罪
by
Takuto Wada
PDF
マイクロにしすぎた結果がこれだよ!
by
mosa siru
PDF
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
by
Preferred Networks
SPAセキュリティ入門~PHP Conference Japan 2021
by
Hiroshi Tokumaru
ゲームの仕様書を書こう4 仕様書作成で楽をするconfluenceの活用
by
Sugimoto Chizuru
Spring Boot × Vue.jsでSPAを作る
by
Go Miyasaka
Tackling Complexity
by
Yoshitaka Kawashima
Apache Airflow 概要(Airflowの基礎を学ぶハンズオンワークショップ 発表資料)
by
NTT DATA Technology & Innovation
例外設計における大罪
by
Takuto Wada
マイクロにしすぎた結果がこれだよ!
by
mosa siru
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
by
Preferred Networks
What's hot
PDF
「のどが渇いた」というユーザーに何を出す? ユーザーの「欲しい」に惑わされない、本当のインサイトを見つけるUXデザイン・UXリサーチ
by
Yoshiki Hayama
PDF
3週連続DDDその1 ドメイン駆動設計の基本を理解する
by
増田 亨
PDF
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
by
Takuto Wada
PDF
フロー効率性とリソース効率性、再入門 #devlove #devkan
by
Itsuki Kuroda
PPTX
ユーザ要望に応えるView customize活用事例
by
Hidehisa Matsutani
PDF
Webブラウザ上で動作する帳票エンジンを作る話
by
terurou
PDF
Vertex AI Pipelinesで BigQuery MLのワークフローを管理 (ETL ~ デプロイまで)
by
幸太朗 岩澤
PPTX
IoTと業務システムをつなぐgRPC/RESTサービスの開発と運用
by
DeNA
PPTX
負荷分散だけじゃないELBのメリット
by
Takashi Toyosaki
PPTX
CEDEC2019 大規模モバイルゲーム運用におけるマスタデータ管理事例
by
sairoutine
PDF
スクラムはもうだめぽよ!新しい開発手法『パワープレイ』をお姉さんが教えてあげちゃう!
by
Moto Arima
PPTX
イベント駆動プログラミングとI/O多重化
by
Gosuke Miyashita
PDF
イミュータブルデータモデル(世代編)
by
Yoshitaka Kawashima
PPTX
로그 기깔나게 잘 디자인하는 법
by
Jeongsang Baek
PDF
Python 3.9からの新定番zoneinfoを使いこなそう
by
Ryuji Tsutsui
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
by
Y Watanabe
PDF
Confluenceショートカットキー表 v1
by
Naho Inuyama
PDF
Redmineを快適に使うためのおすすめ初期設定
by
Go Maeda
PPTX
NDC 11 자이언트 서버의 비밀
by
승명 양
PDF
서버학개론(백엔드 서버 개발자를 위한)
by
SU BO KIM
「のどが渇いた」というユーザーに何を出す? ユーザーの「欲しい」に惑わされない、本当のインサイトを見つけるUXデザイン・UXリサーチ
by
Yoshiki Hayama
3週連続DDDその1 ドメイン駆動設計の基本を理解する
by
増田 亨
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
by
Takuto Wada
フロー効率性とリソース効率性、再入門 #devlove #devkan
by
Itsuki Kuroda
ユーザ要望に応えるView customize活用事例
by
Hidehisa Matsutani
Webブラウザ上で動作する帳票エンジンを作る話
by
terurou
Vertex AI Pipelinesで BigQuery MLのワークフローを管理 (ETL ~ デプロイまで)
by
幸太朗 岩澤
IoTと業務システムをつなぐgRPC/RESTサービスの開発と運用
by
DeNA
負荷分散だけじゃないELBのメリット
by
Takashi Toyosaki
CEDEC2019 大規模モバイルゲーム運用におけるマスタデータ管理事例
by
sairoutine
スクラムはもうだめぽよ!新しい開発手法『パワープレイ』をお姉さんが教えてあげちゃう!
by
Moto Arima
イベント駆動プログラミングとI/O多重化
by
Gosuke Miyashita
イミュータブルデータモデル(世代編)
by
Yoshitaka Kawashima
로그 기깔나게 잘 디자인하는 법
by
Jeongsang Baek
Python 3.9からの新定番zoneinfoを使いこなそう
by
Ryuji Tsutsui
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
by
Y Watanabe
Confluenceショートカットキー表 v1
by
Naho Inuyama
Redmineを快適に使うためのおすすめ初期設定
by
Go Maeda
NDC 11 자이언트 서버의 비밀
by
승명 양
서버학개론(백엔드 서버 개발자를 위한)
by
SU BO KIM
More from Hiroshi Kikuchi
PDF
JUnit5とAndroidのテスト
by
Hiroshi Kikuchi
PDF
今更聞けない? Androidのテストのいろは
by
Hiroshi Kikuchi
PDF
なるべくコードを書かないAndroid開発
by
Hiroshi Kikuchi
PDF
KotlinJSって正直どうなん
by
Hiroshi Kikuchi
PDF
テストコードをアプリケーションコードと同じ階層に置きたい
by
Hiroshi Kikuchi
PDF
Android Developer Toolsのバグを見つけて直してもらった話
by
Hiroshi Kikuchi
PDF
Androidの世界を離れて異文化留学してみた
by
Hiroshi Kikuchi
PDF
Android thingsやってみた
by
Hiroshi Kikuchi
PDF
3分で作る Kotlin Friendly な API
by
Hiroshi Kikuchi
PDF
どうしてコードはレガシーになるのか
by
Hiroshi Kikuchi
PDF
Designing Auto Generated Codes
by
Hiroshi Kikuchi
PPTX
C#でiPhone & Androidアプリ!
by
Hiroshi Kikuchi
PDF
モバイルアプリ開発をグッと楽にするKotlinの便利なところ3選
by
Hiroshi Kikuchi
PDF
新規Androidアプリ開発において何より大切なこと
by
Hiroshi Kikuchi
PPTX
開発チームにKotlinを導入した話
by
Hiroshi Kikuchi
PPTX
Ideatter : Tech-on2011決勝でのプレゼン資料
by
Hiroshi Kikuchi
JUnit5とAndroidのテスト
by
Hiroshi Kikuchi
今更聞けない? Androidのテストのいろは
by
Hiroshi Kikuchi
なるべくコードを書かないAndroid開発
by
Hiroshi Kikuchi
KotlinJSって正直どうなん
by
Hiroshi Kikuchi
テストコードをアプリケーションコードと同じ階層に置きたい
by
Hiroshi Kikuchi
Android Developer Toolsのバグを見つけて直してもらった話
by
Hiroshi Kikuchi
Androidの世界を離れて異文化留学してみた
by
Hiroshi Kikuchi
Android thingsやってみた
by
Hiroshi Kikuchi
3分で作る Kotlin Friendly な API
by
Hiroshi Kikuchi
どうしてコードはレガシーになるのか
by
Hiroshi Kikuchi
Designing Auto Generated Codes
by
Hiroshi Kikuchi
C#でiPhone & Androidアプリ!
by
Hiroshi Kikuchi
モバイルアプリ開発をグッと楽にするKotlinの便利なところ3選
by
Hiroshi Kikuchi
新規Androidアプリ開発において何より大切なこと
by
Hiroshi Kikuchi
開発チームにKotlinを導入した話
by
Hiroshi Kikuchi
Ideatter : Tech-on2011決勝でのプレゼン資料
by
Hiroshi Kikuchi
画面状態を抽象化してテスタブル設計ライフを送ろう
1.
画面状態を抽象化してテスタブル設計ライフ を送ろう kikuchy
2.
Who? @kikuchy 菊池紘 株式会社Diverse (ミクシィグループ) テストの大切さは知っているけれど腰が重い
3.
突然ですが こんなコードに出くわしたことはないですか
4.
var page =
1 var isLoading = false var hasBeenReachedPageEnd = false var isInitialLoading = true fun showData(data: Data) { page++ hasBeenReachedPageEnd = checkPageEnd(data) adapter.setDataAndNotifyChanged(data) } if (!isLoading && !hasBeenReachedPageEnd) { repository .getData() .subscribe(object: Observer { override fun onNext(data: Data) { showData(data) } override fun onStart() { isLoading = true; showProggress(isInitialLoading) } override fun onComplete() { isLoading = false; hideProgress(isInitialLoading); isIlitialLoading = false } }) }
5.
複数フラグで状態管理= 終わりの始まり
6.
booleanのフラグが3つあるとして、とり得る状態は本当に8通りな のか? 実際は5通りくらいだったりする あり得ない状態を考慮できてしまうのは混乱の元 いつ/どこでフラグいじる?問題 どこで変更するの? どこで参照するの? いま変更して大丈夫なの? Activity / Fragmentに生えたメンバ変数は実質グローバル変数
8.
こんな地獄を防ぐには 状態を列挙 状態の操作をできる場所を制限 状態が正しく切り替わっているか確認 状態をオブジェクトで管理して 挙動のテストを書く!
9.
ちゃんと考えよう
10.
前提 APIからとってきた情報を表示するアプリ ‑> 通信状況≒ 画面の状態 暗黙的に期待されている機能は洗い出せているとする 読み込み中の表示 再読込 ページング 失敗時の表示
11.
作例 DroidKaigi 2017のStargazersを表示する https://github.com/kikuchy/ScreenStateIsModelSample
12.
いきなりページングする画面のことを考えるのはしんどいので 簡単な状態のものからステップアップして考えていきます
13.
状態 ページングなし、再取得なし、読んだ情報を表示するだけの画面 読み込みしていない[初期状態] 読み込み中 読み込み成功(with 読み込めたデータ) 読み込み失敗(with エラー内容)
14.
sealed class State
{ // 読み込みしていない object NeverFetched : State() // 読み込み中 object Fetching : State() // 読み込み成功 data class Success(val data: Data) : State() // 読み込み失敗 data class Failure(val error: Throwable) : State() }
15.
状態遷移 遷移を考える どの状態からどの状態へ遷移可能なのか どんな操作によって遷移が起こるのか 操作を受け付けられない状態であったら無視することにす る
16.
図 +--------------+ | NeverFetched | +--------------+ | |
fetch v +----------+ | Fetching | +----------+ | | (読み込みが終わったら自動で遷移) +--------------------- | | v v +---------------+ +----------------+ | Success(data) | | Failure(Error) | +---------------+ +----------------+
17.
状態の管理場所を作る 状態遷移モデルなので、 モデルと呼ぶ ステートマシンと呼んだ方がしっくり来る人もいる 状態の変更はモデル外部で受け取ってもらう必要がある 今回はRxJavaを使用 自前でObserverパターンを実現できればそれでも良い モデル内部では現在の状態を保持している必要がある 通知も同時にできるBehaviorSubjectが適任
18.
class Model(private val
repository: Repository) { // 状態を保持するメンバ代わり。通知役も兼ねる。 private val stateHolder = BehaviorSubject .createDefault<State>(State.NeverFetched) // 外にはObservableとして公開 val stateObservable: Observable<State> get() = stateHolder
19.
private fun fetchRepo()
{ // 読み込みが始まるときに、読み込み中状態にする。 stateHolder.onNext(State.Fetching) repository.getData().subscribe({ data -> // 読み込み成功 stateHolder.onNext(State.Success(data)) }, { error -> // 読み込み失敗 stateHolder.onNext(State.Failure(error)) }) } fun fetch() { // NeverFetched状態でなければ要求を無視する when (stateHolder.value) { is State.NeverFetched -> fetchRepo() else -> return } } }
20.
図のとおりになっているはず +--------------+ | NeverFetched | +--------------+ | |
fetch v +----------+ | Fetching | +----------+ | | (読み込みが終わったら自動で遷移) +--------------------- | | v v +---------------+ +----------------+ | Success(data) | | Failure(Error) | +---------------+ +----------------+
21.
ステップアップ
22.
再読込もページングもする画面の状態 読み込みしていない[初期状態] 読み込み中 (with ページ番号、今までに読み込んだアイテム) 読み込み成功(with
ページ番号、アイテム+ 新しいアイテム) 読み込み失敗(with ページ番号、エラー、アイテム) ページ終端(with アイテム+ 新しいアイテム) 読み込みに失敗してページ終端に到達することはない 操作 次のページを読み込む 読み込みに成功したらアイテムを増やし、ページ番号を増やす 再読込 抱えてるアイテムを破棄して、ページ番号を1に戻す
24.
感覚はわかったと思うのでコードは省略
25.
テスト ちゃんと遷移できているかをテスト 画面にどう反映するかはモデルの関心事ではない テストすることはそこまで多くないから気が重くならない ※もちろん、モデルの複雑さによります
26.
画面とつなぐ 使ってみたかったのでLiveDataでイベントを流す RxLifrcycleを使えればそれでもよい LiveDataのObserverが表示を制御するようにする RecyclerViewのAdapter君 エラー用のSnackBar表示する君 読み込み中インジケーター表示する君 など 個別なので管理がすごく楽
27.
よかったこと 基本的なところは楽にテスト書ける 画面を作る前に動作確認できた テストするうちに抜けていた状態に気づくこともある どこに新しい機能を置けば良いのか悩まなくていい 少なくとも、状態と表示、どちらのことなのかは悩まないはず 1ファイルあたりのコード少なくて感動する モデルがライフサイクルを超えて生き残ってくれれば、Activity / Fragmentが表示された瞬間に以前の状態が復元される 各種アーキテクチャパターンに発展可能
28.
大変だったこと クラスは多い べた書きに比べれば初期開発の時間はかかる 慣れないと大変 暗黙的に期待されている状態を洗い出すのが一番大変 githubのREST API辛くないすか ヘッダのパース面倒とか rate limit引っかかって死ぬとか
29.
Activity / Fragmentが重くてお困りの方 まずは画面の状態を別クラスで 管理するところから始めてみては?
30.
ちなみに このアーキテクチャは弊社サービスYYCのiOS版(開発中)から ヒントを得て作りました Special thanks iOSチームのみなさま
31.
https://github.com/kikuchy/ScreenStateIsModelSample
Download