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
Functional Reactive Programming 介绍
Search
Jichao Wu
June 10, 2015
Programming
1
110
Functional Reactive Programming 介绍
介绍了FRP由来 以及其中的一个关键概念 "derived state"
Jichao Wu
June 10, 2015
Tweet
Share
Other Decks in Programming
See All in Programming
광고 소재 심사 과정에 AI를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
1
310
Realtime API 入門
riofujimon
0
140
Pinia Colada が実現するスマートな非同期処理
naokihaba
4
220
【Kaigi on Rails 2024】YOUTRUST スポンサーLT
krpk1900
1
320
アジャイルを支えるテストアーキテクチャ設計/Test Architecting for Agile
goyoki
9
3.2k
Identifying User Idenity
moro
6
9.7k
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
5
1.5k
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
210
Jakarta EE meets AI
ivargrimstad
0
280
Click-free releases & the making of a CLI app
oheyadam
2
110
JavaでLチカしたい! / JJUG CCC 2024 Fall LT
nhayato
0
120
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
329
21k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
159
15k
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
Rails Girls Zürich Keynote
gr2m
94
13k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
700
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
250
21k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.3k
The Language of Interfaces
destraynor
154
24k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
109
49k
Transcript
Functional Reactive Programming 公司刚开始的时候 就我⼀一个⼈人做iOS这块 后来来了两个pm 以及两个开发⼩小伙伴 产品进⼊入快速迭代时期 随着需求越来越多越来越复杂 开发的⼩小伙伴
越来越多 ⽔水平也不⼀一样 开发新功能和维护变得越来越困难 我意识到 由于我的经验不⾜足 没有给⼯工程做好⼀一个完整的架构设计 所以才遇到了这些问题
Model View Controller 这是apple期待我们的mvc架构 层次分明 责任明确
Massive View Controller 这是我的代码的架构 数据 和业务 全在vc ⾥里⾯面
Move Fast => App Growing 其实刚开始写的时候 代码全写在⼀一起 , ⼀一次写好所有的功能, 感觉还不错
但是 我们在创业啊 我们要迭代 这时候问题就来了 我刚刚说 随着需求越来越多 开发新功能和维护变得越来越困难 为什么越来越困难啊 这个要从源头说起
Input & Output 我们的app从根本上就是接受输⼊入 经过处理整合然后输出⼀一些东⻄西 那什么是输⼊入 什么是输出
input Taps Keyboard events GPS events Web service responses 输⼊入:
⽤用户的点击 输⼊入啊 UI时间 web服务的相应 等等 输出: ⼀一般就是ui的变化
State BOOL dataLoaded; BOOL refreshing; BOOL enabled; BOOL selected; 那我们⼀一般怎么处理这些input呢
我们⼀一般⽤用⼀一些state去记录处理这些input visible enabled selected loaded refreshing
New feature? New state. New complexity. New bugs. 这有⼀一个什么问题呢 有新的需求
带来新的state 代码就越来越复杂为了什么越来越复杂了 {翻⻚页}
State BOOL dataLoaded; BOOL refreshing; BOOL enabled; BOOL selected; BOOL
visible; 2 states 4 states 8 states 16 states 32 states 我们有四个状态 看起来只有四个 其实有16种可能 我们再加⼀一个 就是32种可能了 ⽤用到state两种情况 ⽐比如我们有bug了 往往要跟踪⼀一个state变量 我经常会⽤用状态名字全局搜索 这些状态往往散落在各个⽅方法⾥里 因为我不知道那个⽅方法有副作⽤用改了这个state state 散落在各处 对调试简直是噩梦 所以说 新的需求 带来新的state state越多代码越复杂 复杂就容易出bug 我们怎么去避免使⽤用state 或者我们有没有⼀一种⽅方法能预测state的变化
Functional Programming 有⼀一个 input 经过 函数作⽤用 输出⼀一个 f(x) 这为啥能避免引⼊入state呢
Functional Programming • pure function • 函数结果不依赖任何state • 函数不改变外部state •
high-order function • 函数做参数, 函数返回函数 • tail recursion • composition • y = f(g(x)) 在我看来 函数式编程的作⽤用就是把⼀一个个函数函数串在⼀一起 因此消灭了状态 ⽐比如说gx直接做f的input 就可以避免⼀一个state出现
Model View View-Model 状态消除了 我刚刚还说的⼀一个问题就是vc干了太多事情, 这个好办 就是分层 在MVC的基础上,把C拆出⼀一个ViewModel专⻔门负责数据处理的事情
View-Model (UI events, web response) (UI) 更重要的是 viewmodel作为input 和output之间的桥梁 它还负责数据的合并和转化
这时候 我们的data flow就很清晰了
Data Flow Ownership view 持有 view model, view model 持有
model ⼀一个view可以持有多个view model view model 可以组合起来⽤用 对 view-model, view是不可⻅见的, 两者不耦合 这样view-model 就可以重⽤用 还可以⽅方便测试 那我们怎么把view-model和view连起来呢 view怎么拿到input经过view model 合并转化处理过的值? input往往都是⼀一些接连不断的进来的东⻄西 像⽤用户的点击 输⼊入啊, socket的不断接收数据啊 我们可以在每次有新的output的时候 通知view更新 但是我们上⼀一张图 viewmodel是看不到view的 (为什么? 分层啊? 便于脱离ui层测试 ) 那么view怎么知道什么时候更新? ⽐比如view-model发全局通知 或者view observer view-model, kvo 这时候 我们就可以引⼊入reactive programming
Reactive Programming “programming around data flows and the propagation of
change”
把b改成3 在reactive programming⾥里 c就会相应的变成5 这⾥里看起来没什么⼤大⽤用 但是把前⾯面functional programming 和 reactive programming
结合起来 就成了⽕火了好⼀一阵的 functional reactive programming
Functional Reactive Programming ReactiveCocoa FRP 在 iOS 上的⼀一个实现, 由 Github
开发 为了避免状态我们⽤用了函数式 为了view绑定view-model的值 我们⽤用了响应式编程 合起来就是frp ReactiveCocoa是⼀一个将函数响应式编程范例带⼊入Objective-C的开源库。由Josh Abernathy和Justin Spahr-Summers在对GitHub for Mac的开发过程中建⽴立
INPUT (signal) • UI events • web service responses •
timer triggers • GPS events } 让我们重新回到input和output上 看看他们是怎么结合的 ui 事件 (点击啊 输⼊入啊) web services 响应 这些都是input 他们都有个特点是 他们的值都会随着时间变化(time-varying value) 在reactive cocoa⾥里 他们都被包装成 signal
derived state derived state 是绑定到signal上的state derived state 意味着你不能去直接设置它的值 它的值依赖于signal把input的值转化合并⽽而成 说完了输⼊入
说说处理 什么是derived(衍⽣生) state 刚刚不是说state不好吗? state在函数式编程中可以避免, 但是在cocoa编程中⽆无法避免 在reactive cocoa⾥里 只要derived state绑定在⼀一个signal上(若干个input的组合) 它就是可以接受的 它意味着你不能去直接改变他的值, 它的值根据 input的值转化合并⽽而⾃自动⽣生成 ======================================== 实际上 derived state 就是 view-model 和 view之间的桥梁 我们再回到input和output上
在理论上 函数式编程 给它⼀一个x 经过f() 输出⼀一个f(x) 不带任何副作⽤用 不引⼊入什么state
View-Model (UI events, web response) (UI) 在ui编程中 我们希望把(ui 事件, web
相应 这些input 经过view model转化合并处理后 在view上展现
signals derived states views derived states <= view-models(signals) views <=
derived states view = view-models(signals) 在iOS的frp的⼀一种实现 reactive cocoa 把 input 统⼀一成了signal (随着时间变化的value), 然后在view-model上转化合并这些inputs成derived states, 之后view绑定到这些 derived states上 在刚看看rac时 我经常会好奇 为神⻢马model的属性 要在viewmodel上重新写⼀一遍 然后再绑定到view上, 多⿇麻烦啊 后来看资料看到了dervied state 英语不好死活理解不了 看了好多资料才知道 dervied state 就是view model上的那些属性, 在最简单的情形下就是model的属性, ⽐比如⼀一个整数年龄转化成⼀一个年龄字符串 xx岁, 来⽅方便view显⽰示 但是复杂情形下 derived state 就是对 好多input做⼀一些复杂的转化和合并 最终合成了derived state 供view绑定 说了这么多虚的 我们来个demo
derived states <= view-models(signals) views <= derived states view <=
view-models(signals)
Demo
输⼊入时⾃自动搜索关键词 ⽤用户输⼊入关键词时 ⾃自动进⾏行搜索 且只有在关键词⻓长度⼤大于2 并且0.3s内的输⼊入请求⼀一起发出 最后显⽰示结果 ⾃自动搜索 特点是⽤用户输⼊入是不断变化的 特别适合使⽤用rac来处理 我们的要求是
⽤用户输⼊入关键词时 ⾃自动进⾏行搜索 且只有在关键词⻓长度⼤大于2 并且0.3s内的输⼊入请求⼀一起发出 加⼊入⽤用户输的太快的话 我们不能⼀一直请求吧 最后显⽰示结果 input 就是⽤用户的输⼊入 处理就是 过滤 忽略 搜索 我们甚⾄至可以借助 switchToLatest 把上次输⼊入的但还未完成的请求拍抛弃掉 取消⽆无⽤用请求
总结 - Design Information Flow - Define Clear Responsibilities (分层,
分模块) - Simplify with Immutability (最⼩小化使⽤用的状态 最⼩小化函数的副作⽤用) 最后今天我想说的就是 不管哪⼀一种编程 哪⼀一种架构 借⽤用wwdc⼀一个演讲的总结 是⼀一个关于架构的总结 对应今天我讲的 第⼀一个就是 我们需要理清 data flow 2 适当分层 分模块 3 最⼩小化使⽤用的状态 最⼩小化函数的副作⽤用
[subscriber sendNext:@"Thank you ~"]; [subscriber sendCompleted]; // Any Question?