当我们谈论自己的产品Wilddog时,其实大多数时间我们在谈同步机制。
工程的东西往往具有一个特点,后人不断站在前人的肩膀上,以前人的工作成果作为起点。
人类的进化也符合这个特征
人类的老祖宗进化成人类的一个最重要的里程碑是使用火--使用火,可以吃熟食。熟食更利于消化,吃的更少就可以提供足够的营养,食物负担减少,因此老祖宗门有了更多的时间去思考”猿生“的意义,有更多的时间制作效率更高的工具,也有了更多的营养发育大脑,因此才有了人类文明的起飞。要注意,这一切都源于火的使用。当然今天的主题并不是生物进化,关于老祖宗的话题就此结束,只留一个结论: 工具决定高度!
说到这里,有很多工程师不屑于这个结论:老子不需要先进的工具,只靠手速就可以战胜88%的工程师。我想说的是汽车在刚刚发明的时候一定没有人跑的快,但汽车性能的发展是线性的,而人类体能的发展是偶然性的!一旦汽车超过人,人类就被远远的抛在后面,永远没有机会。经过不断的训练,你可以把自己的百米成绩提高10%,然而只需要借助工具,不需要任何努力,这个数值可能是1000% 。
工具决定高度有两层原因:
就Web开发来说,一个工具帮你节约时间体现在帮你搞定兼容性,把原生的“能用的”API封装成“好用的”API,没错,我说的是JQuery。Jquery的优势体现在第一个层次,却没有体现在第二个层次,你还是思考DOM如何变化,监听哪些事件等一系列繁琐的事情。
我拿来与JQuery对比的工具是:AngularJS,React这类提供数据绑定的框架。当写一个逻辑复杂的页面,操作DOM变成了一件非常乏味而且恐怖的事情,这个时候你会问:TM为什么要操作DOM,为什么要监听事件?是的,其实你并不需要,或者说不需直接操作DOM。数据绑定帮我们做了数据(模型,状态)->DOM的事情,因此你只需要操作数据模型。操作数据比操作DOM要简单的多。
大脑并不是一个无限的容器,装下了DOM操作就装不下上层的业务逻辑。当你不必为DOM操作而烦恼的时候,就可以思考更多高层的东西。你并不关心DOM操作,网络传输,你只关心实现功能,也就是业务逻辑。在业务逻辑之外思考的越少越好,好的工具就是给你一个思维的框架,简化你的思维模型。
当然,作为开发者,你也许不会为减少这一点点脑力负担有多么了不起,就像原始人不会想到减少一点点食物负担对于世界有多少影响。
所以,我们需要更好的
工具。
数据绑定优于DOM操作。所以Angular,React 都提供数据绑定机制。
同样,在实时数据传输这件事情上对比两种方式:
直接传输是指将数据从一端直接发给另外一端。而数据同步发生在两个数据源之间,有一套算法机制保证其完全一致。传输仅仅是一个管道,而同步是管道加两端的数据池。
Socket.io 这类工具帮开发者解决了兼容性,甚至提供了服务端,的确简化了操作。但跟Jquery一样,没有简化思考。当你开发时,你需要考虑当前客户端是否在线,对端是否在线这样的问题。所以你的思维模型是 (服务端数据,目标客户端数据,本地数据,业务逻辑):
而如果提供同步机制,你的思维模型就只是(本地数据,业务逻辑):
由于本地有数据源,开发者只需要关心对本地数据源的修改,本地数据源到服务端,到后端的一系列事情都由同步机制来解决。
由此我们看出同步相对于数据传输的最大优势--简化开发模型。
Wilddog的同步机制通过以下方面简化开发模型:
这个很好理解,Wilddog的数据操作API是 set
update
remove
push
这些API的语义是 修改本地存储数据 (顺便同步到云端,如果当前不在线,就等在线后再说)。API是面向本地数据修改的,传输的过程完全封装。
而数据的查询 on
, once
在离线后也能够正常使用,本地数据操作能够正常触发 value
child_added
child_removed
child_moved
child_changed
事件。对于开发者来说,即使在离线情况下,所有的API都能够工作正常,所有的事件都能够正常触发。大多数情况下并不需要考虑在线与离线,而需要考虑的场景下,Wilddog也提供了查询当前在线状态的方法。
ref.on('child_changed',function(snapshot){ //即使在离线状态下也会触发 console.log(snapshot.val()) }) ref.set('hello',function(err){ //数据同步完成才会触发 console.log("sync complete") })
如果你不怎么关心这条数据是否真的被写到服务端,而只是关心这条数据这条数据在本地产生的影响 set
的回调可以不用。如果你关心数据真正被写到服务端,可以通过这个回调函数来处理。
同步的另外一个优势是统一事件模型。如果你需要维护一个数组,将数组中的所有数据打印出来,一般你需要这么做
//可能存在某些初始数据 var d = init() //监听新增的数据 d.forEach(function(data){ console.log(data) }) socket.on('message',function(data){ d.push(data); console.log(data) })
但是这段代码足以杀死处女座了,为什么对d的维护需要两段不同的逻辑:初始化和监听后续变化? 为什么打印要调用2次?这段代码可以优化的很优雅,问题是需要时间。这段代码是我凭第一感觉写出来的,相信大多数工程师也会有类似的表现。
那么看一下同步机制下的事件如何拯救处女座:
ref.on('child_added',function(snapshot){ cosole.log(snap.val()); })
没错,就这么简单,即使是已经存在的数据依然会触发这个回调,事件机制就这样统一了。
数据同步优于数据传输
工具决定你的思维模型,Wilddog的同步机制简化了思维模型,让你聚焦到业务逻辑。AND-处女座程序员的拯救者 :-)