Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Reactive Programming 介绍

Functional Reactive Programming 介绍

介绍了FRP由来 以及其中的一个关键概念 "derived state"

Jichao Wu

June 10, 2015
Tweet

Other Decks in Programming

Transcript

  1. Functional Reactive Programming 公司刚开始的时候 就我⼀一个⼈人做iOS这块 后来来了两个pm 以及两个开发⼩小伙伴 产品进⼊入快速迭代时期 随着需求越来越多越来越复杂 开发的⼩小伙伴

    越来越多 ⽔水平也不⼀一样 开发新功能和维护变得越来越困难 我意识到 由于我的经验不⾜足 没有给⼯工程做好⼀一个完整的架构设计 所以才遇到了这些问题
  2. Move Fast => App Growing 其实刚开始写的时候 代码全写在⼀一起 , ⼀一次写好所有的功能, 感觉还不错

    但是 我们在创业啊 我们要迭代 这时候问题就来了 我刚刚说 随着需求越来越多 开发新功能和维护变得越来越困难 为什么越来越困难啊 这个要从源头说起
  3. input Taps Keyboard events GPS events Web service responses 输⼊入:

    ⽤用户的点击 输⼊入啊 UI时间 web服务的相应 等等 输出: ⼀一般就是ui的变化
  4. State BOOL dataLoaded; BOOL refreshing; BOOL enabled; BOOL selected; 那我们⼀一般怎么处理这些input呢

    我们⼀一般⽤用⼀一些state去记录处理这些input visible enabled selected loaded refreshing
  5. New feature? New state. New complexity. New bugs. 这有⼀一个什么问题呢 有新的需求

    带来新的state 代码就越来越复杂为了什么越来越复杂了 {翻⻚页}
  6. 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的变化
  7. Functional Programming • pure function • 函数结果不依赖任何state • 函数不改变外部state •

    high-order function • 函数做参数, 函数返回函数 • tail recursion • composition • y = f(g(x)) 在我看来 函数式编程的作⽤用就是把⼀一个个函数函数串在⼀一起 因此消灭了状态 ⽐比如说gx直接做f的input 就可以避免⼀一个state出现
  8. 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
  9. Functional Reactive Programming ReactiveCocoa FRP 在 iOS 上的⼀一个实现, 由 Github

    开发 为了避免状态我们⽤用了函数式 为了view绑定view-model的值 我们⽤用了响应式编程 合起来就是frp ReactiveCocoa是⼀一个将函数响应式编程范例带⼊入Objective-C的开源库。由Josh Abernathy和Justin Spahr-Summers在对GitHub for Mac的开发过程中建⽴立
  10. INPUT (signal) • UI events • web service responses •

    timer triggers • GPS events } 让我们重新回到input和output上 看看他们是怎么结合的 ui 事件 (点击啊 输⼊入啊) web services 响应 这些都是input 他们都有个特点是 他们的值都会随着时间变化(time-varying value) 在reactive cocoa⾥里 他们都被包装成 signal
  11. 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上
  12. View-Model (UI events, web response) (UI) 在ui编程中 我们希望把(ui 事件, web

    相应 这些input 经过view model转化合并处理后 在view上展现
  13. 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
  14. 输⼊入时⾃自动搜索关键词 ⽤用户输⼊入关键词时 ⾃自动进⾏行搜索 且只有在关键词⻓长度⼤大于2 并且0.3s内的输⼊入请求⼀一起发出 最后显⽰示结果 ⾃自动搜索 特点是⽤用户输⼊入是不断变化的 特别适合使⽤用rac来处理 我们的要求是

    ⽤用户输⼊入关键词时 ⾃自动进⾏行搜索 且只有在关键词⻓长度⼤大于2 并且0.3s内的输⼊入请求⼀一起发出 加⼊入⽤用户输的太快的话 我们不能⼀一直请求吧 最后显⽰示结果 input 就是⽤用户的输⼊入 处理就是 过滤 忽略 搜索 我们甚⾄至可以借助 switchToLatest 把上次输⼊入的但还未完成的请求拍抛弃掉 取消⽆无⽤用请求
  15. 总结 - Design Information Flow - Define Clear Responsibilities (分层,

    分模块) - Simplify with Immutability (最⼩小化使⽤用的状态 最⼩小化函数的副作⽤用) 最后今天我想说的就是 不管哪⼀一种编程 哪⼀一种架构 借⽤用wwdc⼀一个演讲的总结 是⼀一个关于架构的总结 对应今天我讲的 第⼀一个就是 我们需要理清 data flow 2 适当分层 分模块 3 最⼩小化使⽤用的状态 最⼩小化函数的副作⽤用