Posted in December 2009

我对CPS的理解

最近学习Haskell,我看的是Yet Another Haskell Tutorial,看到CPS,发现这本书写的很难懂,不知所云。后来看了wikibooks上面的文章,明白了一些。这里是一个总结,也还不错。

CPS到底是个啥?拿例子看比较容易。比较如下代码:
add (square x) (square y)
和CAS style的:
pythagoras'cps x y k =
square'cps x $ \x'squared ->
square'cps y $ \y'squared ->
add'cps x'squared y'squared $ \sum'of'squares ->
k sum'of'squares

CPS有点像倒置过来的写法,而前者则是普通的堆栈的写法。那这样CPS有什么有优点呢?

在Java中类似的写法有stringBuffer.append(“A”).append(“B”).append(“C”),IO API中好像也有类似的方法。(在《The Productive Programmer》里面管这个叫做连贯接口 fluent interface…)

感觉有点类似管道(pipe),前面的square把结果(这里就是k)传到下一个function,这样一个个串联起来,而k起了连接的作 用。而像add( square(x), square(y))这种方式每个func相当独立(primitive),最后有一个组合(mash-up)的过程。

而这种方式才让“从某个点停止,然后继续执行”成为可能,因为这样没有堆栈。add( square(x), square(y))这种方式会生成临时变量,会有running context。而pipe某个节点的状态就是pipe的全部,是继续“流”下去所需的所有内容,这个function是可以“重入”的。这里“流”下去就是“延续”的意思。

这种状态保存其实很多地方都有,比如http session,比如进程上下文(进程也可以sleep后再重新载入,或者恢复),但是CPS则粒度更细,可以在代码级上的重新载入,“重入”精确到某行代码。而Spring web flow这种流程级的则是精确到了flow中的某个节点,比较代码级的天书一样的代码,流程级的引入进来还是比较好的一个折中。当然这样的话,跟CPS就关系不大了。

我很早前读过跨越边界: 延续、Web 开发和 Java 编程,当时不甚理解,现在拿Haskell做例子,才明白原来这里面实现起来还是很绕的。

Android Observer Pattern in Content Service

This article used NotePad project as example. It can be found sample dir at Android SDK.

1.Register process. There are 2 repository: a) content service, b) ArrayList in Observable.

a). in NotePadProvider, after we finished querying, there is:

c.setNotificationUri(getContext().getContentResolver(), uri);

which in turn invokes (c is type of AbstractCursor)

mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);

this type of observer is identified by Uri of resource and maintained by content service which is more like a event broker.

b). in init() method of CursorAdapter code, there is

c.registerContentObserver(mChangeObserver);

This type of observer is maintained by corresponding cursor.

2. notify process. These is a little more complex. Because content service will notify Observable first, then Observable will notify cursor adapter. I prepared a sequence to present this.

content-service

From the graph, it’s found the framework used a lot of inner class to implement call-back functionality. (This was full documented at Thinking in Java) This made the code a little hard to read.

So use this approach, we can register a observer on Contacts.People.CONTENT_URI, then when the contacts was changed, we will get a notification, as the example here. It is simple but remember to unregisterContentObservers your observer. You had better do it at a service. If we do it at an Activity and register at onCreate and un-register at onStop, when the activity went into background, it will not get notified.

So there are 2 level of observer. These 2 levels all can be found at OSGi. It make the framework more flexibility.

OSGi的白板模式(White board Pattern)

这个模式主要是来对付Listener Patter(或者Observer Pattern),具体来说,后者的缺点在:

  • 产生了很多的类,比如很多情况下,一个event source只对应一个listener,这种浪费在手机这种受限设备上是一个不得不考虑的问题。
  • event source和listener的管理复杂,比如注册和注销,因为这两者可能都很动态,不能保证自己需要对方时对方是工作的,或者说难以达到消息的可靠性。这两者之间的依赖太明显,太直接。

White Board引入了event broker,作为两者间的桥梁,保存消息和分发消息,走向了subscribe/publish模式。

whiteboard

图摘抄至OSGi in Practice。这并无神奇的地方,只是把复杂的代码挪到了broker。OSGi则在这个地方加上了比如异步,有顺序的分发和可靠的分发这些功能。还有Topic的功能,比如有一个topic: a/b/c/*,这样event source和listener直接就靠这个纽带来进行交互,在Android中把这个抽象成URI,感觉几乎是一样的。

倒不清楚Android是一个OSGi的实现?还是只是把OSGi作为一个templete拿来模仿?