又论函数式编程
前言 4月初在北京的时候,徐昊同学表示我们公司的同事们写的文章都太简单,太注重细节,然后捡起了芝麻丢了西瓜,于是我就不再更新博客(其实根本原因是项目太忙)。上周和其他几个同事一起参加“Martin Fowler深圳行”的活动,我和同事扎西贡献了一个《FullStack Language JavaScript》,一起的还有杨云(江湖人称大魔头)的话题是《掌握函数式编程,控制系统复杂度》,李新(江湖人称新爷)的话题是《并发:前生来世》。 和其他同事预演的时候,突然发现其实我们的主题或多或少都有些关联,我讲的部分也涉及到了基于事件的并发机制和函数式编程。仔细想想,应该与JavaScript本身的特性不无关系: 基于事件(Event-Based)的Node.js的正是并发中很典型的一个模型 函数式编程使其天然支持回调,从而非常适合异步/事件机制 函数式编程特性使其非常适合DSL的编写 会后的第二天,我在项目代码里忽然想要将一个聚合模型用函数式编程的方式重写一下,结果发现思路竟然与NoSQL依稀有些联系,进一步发现自己很多不足。 下面这个例子来自于实际项目中的场景,不过Domain做了切换,但是丝毫不影响阅读和理解背后的机制。 一个书签应用 设想有这样一个应用:用户可以看到一个订阅的RSS的列表。列表中的每一项(称为一个Feed),包含一个id,一个文章的标题title和一个文章的链接url。 数据模型看起来是这样的: var feeds = [ { 'id': 1, 'url': 'http://abruzzi.github.com/2015/03/list-comprehension-in-python/', 'title': 'Python中的 list comprehension 以及 generator' }, { 'id': 2, 'url': 'http://abruzzi.github.com/2015/03/build-monitor-script-based-on-inotify/', 'title': '使用inotify/fswatch构建自动监控脚本' }, { 'id': 3, 'url': 'http://abruzzi.github.com/2015/02/build-sample-application-by-using-underscore-and-jquery/', 'title': '使用underscore.js构建前端应用' } ]; 当这个简单应用没有任何用户相关的信息时,模型非常简单。但是很快,应用需要从单机版扩展到Web版,也就是说,我们引入了用户的概念。每个用户都能看到一个这样的列表。另外,用户还可以收藏Feed。当然,收藏之后,用户还可以查看收藏的Feed列表。 由于每个用户可以收藏多个Feed,而每个Feed也可以被多个用户收藏,因此它们之间的多对多关系如上图所示。可能你还会想到诸如: $ curl http://localhost:9999/user/1/feeds 来获取用户1的所有feed等,但是这些都不重要,真正的问题是,当你拿到了所有Feed之后,在UI上,需要为每个Feed填加一个属性makred。这个属性用来标示该feed是否已经被收藏了。对应到界面上,可能是一枚黄色的星星,或者一个红色的心。 服务器端聚合 由于关系型数据库的限制,你需要在服务器端做一次聚合,比如将feed对象包装一下,生成一个FeedWrapper之类的对象: public class FeedWrapper { private Feed feed; private boolean marked; public boolean isMarked() { return marked; } public void setMarked(boolean marked) { this....