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

Functional Reactive Programming 介绍

Functional Reactive Programming 介绍

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

Avatar for Jichao Wu

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 最⼩小化使⽤用的状态 最⼩小化函数的副作⽤用