我理解的函数响应编程

       原创,转载请注明出处。

       函数响应编程,这个概念在网上已经有很多解释了,我也读了很多,说说我的理解。有时候我想,我如何学习一个新的概念或技术,不是应该用我已有的脑袋去理解它么,关键是怎么理解,怎么才算理解,理解的对不对,我想这是抽象变形象的过程。那我就用自己的方法去理解和认识函数响应编程这个概念。

       函数响应式编程的本质是什么?是函数编程和响应编程的结合,函数是编排,响应是关联作用。用来编排的是什么呢?是逻辑,是处理逻辑,这些逻辑是用函数实现的,而函数和函数之间的粘合剂是响应式编程实现的函数接口(when,then,merge,map,flatmap,fork,join etc.),我们最熟悉的编程方式是什么?如何定义一个函数?对输入参数进行各种运算,赋值,if-elseif-else,函数调用,抛出ex,处理ex,最后return,这是我们的函数定义。函数响应编程怎么做?定义一个函数:对函数的参数输入,进行map(func1).filter(func2).merge(func3)...(funcN),好了,编排完了,这是函数定义。

        函数都定义好了,但它并没有真正执行,只是定义,最终需要调用,需要执行,怎么调用执行?怎么触发?基于事件流触发,事件流中是一个个事件单元,一个事件什么时候产生,什么时候触发。那到底是哪些事件呢?具体到实际中,我们界面上的操作或者动作,也可以是系统定时产生的动作,这些动作会被转化成事件而write到stream中。而在后台,一样是事件,可以是notify事件,可以是io事件,本质上io也是notify的一种。异步的线程之间相互作用触发了函数的执行,而函数的执行结果可能再次作用于异步的线程。函数响应编程定义的处理过程可能是同步的可能是异步的,由scheduler的调度方式决定。有的执行多次,有的执行一次,是由流的性质决定的。

        map filter merge...这不是和mapreduce很像吗?是的,mapReduce使用了函数式编程方式,像更贴近的spark的定义执行方式。spark的RDD是函数响应编程的事件流,而spark的mapreduce定义了响应行为,输入和输出的RDD形成了DAG(有向无环图),通过对数据的位置和依赖分析形成最终的执行计划。如果说spark的batch RDD是静态(冷)数据流,那spark streaming则更像是动态(热)数据流。

       涉及到并发编程,那并发编程的本质是什么?现在的并发和古老的并发到底有何区别?这些各种封装好框架,除了让你编程的代码结构发生了变化,提取了常用的处理模式,分离了并发处理逻辑和你实现的业务逻辑。本质仍然是wait/notify/资源共享(表现为内存区域共享,简单的就是变量,文件,数据库,介质无非就是内存或者磁盘,这就是资源)。

        和传统编程相比,到底哪里不同?同步单线程确实无差别,异步调用确实有差别,使用高阶函数,让传统的回调漩涡看起来扁平化,高阶函数是什么?输入参数为函数或输出结果为函数(curry化)或两者兼备的函数。这看上去更像是两种生长方式,传统回调漩涡是从地面一直下降到地心的漩涡,而高阶函数更像是通过函数指针或接口定义重新定义函数或接口的行为,依次进行输入输出的调用。

最后简单总结下我们的编程方式:

1、野蛮人风格?

exec(){

dosomethingA...;

dosomethingB...;

dosomethingC...;

}

2、看上去像漩涡?像链?

function a(r1){

dosomethingA...;

b(r1);

}

function b(r1){

dosomethingB...;

c(r1);

}

function c(r1){

dosomethingC...;

}

exec(){ a("r1");}

3、看上去像大饼

function a(r1){

dosomethingA...;

}

function b(r1){

dosomethingB...;

}

function c(r1){

dosomethingC...;

}

exec(){ a("r1");b("r1");c("r1");}

 

4、这是函数式编程?

function a(r1){

dosomethingA...;

return r1;

}

function b(r1){

dosomethingB...;

return r1;

}

function c(r1){

dosomethingC...;

}

exec(){ c(b(a("r1")));}

 

5、这是函数响应编程?

List acts = ...;

acts.add(function(r1){dosomethingA...})

.add(function(r1){dosomeghingB...})

.add(function(r1){dosomethingC...});

exec(){for(Action act : acts) act("r1");}

亦或是:

List acts = ...;

acts.add(&a)

.add(&b)

.add(&c);

exec(){for(Action act : acts) (*act)("r1");}

或是:

List acts = ...;

acts.add(new Action(){ call(r1){dosomethingA...;}})

.add(new Action(){ call(r1){dosomethingB...;}})

.add(new Action(){ call(r1){dosomethingC...;}};

 

exec(){for(Action act : acts) act.call("r1");}

 

编程很简单,就看你怎么折腾它。

我感觉很简单,但是好像也没说明白,也许还需要理解2.0。

猜你喜欢

转载自currentj.iteye.com/blog/2276008