Monthly Archives: 十二月 2013

2013之“马上”总结

这篇文章写的

对一件事物,一个人,从不熟悉到熟悉,中间必定诸多波折坎坷,内心早已有千万只小马驹奔腾而过。禅宗希望我们保持一个“初心”,对事物的看法永远不要有定势思维。对事物的“初心”的印象,虽然某种角度上来说,过于极端与片面。但极端反应着形势的演化及事件的趋势。

知道自己的位置很重要

今天要讲的主要是我今年工作上的体会与总结。希望从中识得蛛丝马迹的朋友们看到了不要误会,我只是希望抛砖引玉,用这粗糙的思想换取看官们宝贵的意见。

先简单介绍相关的业务:我们主要实现视频的聚合,包括各大视频网站的节目更新,并为线上客户端提供数据支持。这要求我们必须做到与各大视频网站同步更新。业务逻辑描述起来总是比较简洁,所以我想深入讨论下数据。

可以认为,存储在NOSQL中的每一条节目都是一个完整数据,而数据中都包含了很多信息。根据信息属性主要可以分为三类:

  • 不更新的元信息,如演员/导演,可用于相似度计算(实现聚合);
  • 更新中的信息,如剧集,提供视频更新支持;
  • 实时计算的信息,如节目的热度/评分/排行等,为推荐系统服务。

我们对于三类数据的处理也可以分为三个主要方面:

  • 元信息管理,负责完善基本不更新的元信息,提高相似度计算的准度,如演员/导演/年份等;
  • 正反向爬虫,负责节目剧集的更新;
  • 运营需求相关的管理,负责对节目的热度/排行等进行自动计算和人工干预。

当然,还包括一个为客户端服务的线上数据库,用HTTP协议与客户端通信。

目前的数据处理流程 🙁 比较简单:数据库管理/所有爬虫/后台管理,单独访问/修改数据库。看起来好像三个项目不需要互相通信,可但是,但可是,我们使用MongoDB,一个轻量型的非关系型数据库。所有信息都放入一个对象中,并且所有项目都直接操作这个对象。并不是说MongoDB不对,它是一个很出色、易上手的数据库。但这是一种耦合的设计,操作数据远没有这么简单。所有的模块在访问数据对象都需要谨慎考虑是否会把其它模块写入的信息覆盖/丢失,鉴于我们都是程序员而不是计算机,出错在所难免(请不要嘲笑我们,我们都在努力地分离业务逻辑),导致经常在提交代码补后发现这份代码有副作用:它把其它信息给“不小心”覆盖了。说来说去还是耦合的问题。这就引出一个我最近一直在思考的问题:分离数据库,线下将数据库分成三个表,三个独立的模块只负责自己的一部分数据信息,线下数据库对外并不可见;而线上则统一数据库入口,近实时的将关系型数据关联起来,导入线上的MongoDB。所谓统一入口指数据在入库前经过公用的标准化模块格式化,以适应客户端的需求。而能够这样采取这个方案的原因也在于线上的业务只是对数据库进行读取,并不会修改线上数据库。我想这样能很大程度地解决目前三个本应独立的项目互相干扰的现状。

讲完实际业务,再谈谈我在编程过程中遇到的问题。NodeJS/Python/Java,这是我们三个小项目使用的语言。天呐,在操作同一个数据库对象时,三个人要写三份代码,并且还要保证三个人交流足够充分,这算是杀死程序员的第二种好方法,NOT DRY。我们总是在重复代码,但却不能共用。我个人倾向于使用Python,Java就算了吧,我至今没弄明白Java中IOStream的各种类型的区别。Python就简单多了,没有复杂的类型,不需要复杂的设计模式解决复杂的类型问题。而NodeJS,它的热度还是很高的,但你有没有写过异步遍历序列并在回调操作序列中数据的代码?关于异步,倒可以扯一点,Golang支持一种语法糖,使用”go”关键字直接实现异步调用,这个代码风格就简单多了。程序员写的代码都是给程序员看的。但根据业务选择合适语言并提供可靠的公共模块确是我们需要考虑的。

讲到代码,我想我们又有问题了。我们确实用了代码审查工具,但可是,可但是,我们的审查力度还远远不够。这就像是公务员系统,大家总觉得差不多就行了,不要太较真,破坏团队和谐。我总是天真地提醒我自己,一定要在问题上较真。代码上,该不对的就不对,该重构的就重构。如果撤销一个补丁影响太大,那就必须追加一个补丁来“清理”;对代码追求简洁到灵活运用复杂的运算符优先级而不加一个“免费的小括号”的代码坚决抵制;发现程序有漏洞,如果自己没有把握,那就找作者交流并共同修改,共同进步。我该庆幸这份代码不用自己维护吗?我们已经有了工具,但我们却没有正确的使用。代码的审查制度要绝不留情。这听起来像不像资本主义的口号?

总结起来,我觉得有四个方面可以考虑:

  1. 生产数据库统一入口,避免过多程序直接操作对外数据库,保证数据的一致性;
  2. 抽象公共模块,提供可复用代码,由指定几人对模块进行维护,并严格审查;
  3. 严格的代码审查制度,避免“坏味道”代码流入代码仓库;
  4. 线下数据可以使用关联型的数据库设计,避免项目耦合于无形之中。

最后,给自己提个醒。我们总是有各种理由来说服自己学习新的语言/框架/技术,但对于许多程序员而言,“活到老学到老”变成了负担。多学习能拓宽思维,借鉴其设计的巧妙之处,就像最近接触了MapReduce之后,总觉得应该抽个时间看看函数式编程。可是没时间啊。 🙂

我正朝着“懒惰的程序员”的方向努力着,以上只是我在漫漫程序员路的旅途中得到的一些粗浅见识。按照程序员的记忆曲线,在三个月以后,这些想法可能会非常的陌生抑或我终于意识到并承认这些想法听起来就是个笑话,但我不希望我在很久以后才发觉。

看官们任何直面主题的评论、建议或探讨都是对我的帮助与支持。


后续:

2013-12-28:

对于“统一入口”的需求是因为目前的数据操作单元是整个对象,对象中的某个字段中嵌套的数组结构又包含着复杂的字典结构,深层嵌套之下,逻辑分离的同时保证数据统一就变得复杂了。

“统一入口”要求很严格的入口控制,目前我们并不能保证。而从另一个角度出发,根据数据属性而不是业务逻辑,清晰地数据结构定义是能保证数据的一致性的。