技术选型
在当时,我没有任何互联网产品的背景,但学习和写代码一直是我的强项。在Juniper,我也做了好几个很小很小的Web工具——coredum分析工具、每周报告分析工具等。C语言和汇编对我要做的事情几乎没有任何帮助 ,好在那时我对PHP和Python已经是轻车熟路。于是我开始了艰难的技术选型之路。
语言和框架
我从以下几个方面去考察编程语言和框架。
(1)我自己要懂,且容易上手。
(2)开发成本不高,能够快速开发。
(3)有不错的测试框架(方便日后做持续集成)。
(4)社区支持好,文档丰富。
(5)招人成本不高。
我自己用了7年的C语言(全职),5~6年PHP和Python(个人的小项目),3~5年的C#(集中在我大学阶段和职业早期),几个月的Java、Ruby和F#(纯属兴趣爱好)。
C语言可以直接抛弃,做互联网的写代码还去考虑ELF、栈溢出、缓冲区泄漏太伤神;C#和F#也抛弃,除非我想绑在微软的架构下,支付高昂的总体拥有成本(TCO)(当然,想借力BizSpark的创业者可以考虑,毕竟3年内免费使用全套微软产品的诱惑很大)。
Java是一个巨大的诱惑,太多优秀的开源项目让你忍不住想使用Java。不过Java不适合快速开发,对团队能力和规模挑战太大,于是也被抛弃。但是开发一些关键的引擎会用考虑使用Java现成的工具,如Mahout(当时的想法简单,Mahout最终只出现在架构图中)。
入围的就剩下PHP、Python和Ruby。这三者都能很好地满足第2、3和4条。
虽然那时Symfony是我最熟悉的框架,但我并不喜欢PHP。骨子里的陈旧让它无法与Python/Ruby这样更“动态”的语言相媲美。symfony模仿Rails,但实现得很吃力,Ruby里method_missing这样美妙讨巧的甜点在PHP里几乎是个梦魇 (好吧,我PHP功底很弱的)。这就是symfony无论如何也无法赶上Rails的最重要的原因:它被PHP语言的限制给束缚了。按照Paul Graham的说法,语言的表现力上:lisp >> Ruby ~ Python > PHP >>>> Java/C等静态编译语言。
我非常赞同这一观点。另外,PHP不太适合开发后台服务,如写一些守护进程(daemon),这样后台的服务还需要用别的语言,所以PHP出局了,我决定从Python和Ruby中选择一门语言来实现途我睿。
在花了不少时间分别学习Ruby/Rails2和Django后,我决定使用Python。基于以下理由。
(1)Ruby的很多特性太灵活,如开放类的修改,太灵活可能不利于团队开发(这点现在看来是我当时的偏见)。
(2)使用Ruby做项目的工程师很难招。从招工程师的角度来看:PHP >>>>Python >> Ruby。Python工程师不好招,但合格的Ruby工程师几乎招不到。
(3)我对Python的驾驭能力比Ruby高至少两个等级 。
现在回过头来看,第三点是最关键的,第一点和第二点其实都不那么重要。具体原因如下。
(1)畏惧来源于无知,我不懂Ruby,所以害怕它的灵活。
(2)创业团队要小而精,两个很棒的Rails工程师抵得上一打PHP工程师(从开发效率上看),使用Rails的工程师在当时算得上是极客(geek),找出牛人(ace player)的概率很大。
最终我确定了使用Python/Django,然后就开始一门心思地学习,边学边做途我睿。Django有着可能是这个世上最好的在线文档,学起来毫不费力。
数据库选择
我主要考察的数据库有MySQL、PostgreSQL和MongoDB。对于这三种数据库,我都有一些经验,其中以MySQL的经验最为“丰富”,毕竟之前做的小项目都是用MySQL。
我对数据库的要求如下。
(1)支持地理位置查询。比如,两地间的距离,一个景点方圆几公里都有什么景点,离一个景点最近的景点是什么……
(2)适合快速开发,有成熟的ORM/ODM。
(3)容易部署,至少主从(master/slave)的部署不复杂。
(4)开发效率高。
其中第一条是决定性的,因为地理位置查询是我们很多操作的基础。MySQL因此出局(其实MySQL还是可以做类似的事情的,只是当时不懂),剩下PostgreSQL和MongoDB。PostgreSQL是GeoDjango的默认数据库,而GeoDjango提供了一套强大的可开发GIS的系统。此外,在地图上进行遮罩这种很高阶的功能GeoDjango也支持。因此,GeoDjango和PostgreSQL便成为我的首选。我从一个开源的项目——everyblock开始学习GeoDjango和PostgreSQL。
然而,两个月后,我发现GeoDjango/PostgreSQL的学习成本和曲线太高,要掌握它及其背后复杂的library非一日之功。复杂是创新的敌人,当你把全部精力用在应对复杂后,你已经无力去思考去创新。因此,我决定舍弃GeoDjango/Postgres和在此基础上完成的项目,转向MongoDB。
MongoDB仅仅支持范围查询(within)和附近查询(near),对于我们的项目来说,最核心的功能已经能够实现,目前基本够用了。相对于Postgres的复杂,MongoDB很简单、轻便,语法也很容易上手。此外,MongoDB很容易部署,因此第1、3和4条都符合得很好。然而,让我在MongoDB和PostgreSQL/GeoDjango纠结以至于一开始没有使用MongoDB的原因在于:Django对NoSQL没有支持!这意味着我不得不放弃近半数的Django功能,尤其是其引以为豪的后台生成器(admin generator)。这让人抓狂!
最终,支持地理位置查询和快速开发的优点使我选择了MongoDB。
心得
技术选型是一个项目开始最重要的事情,多看多问多写,而不要一拍脑门就做出决定。
在架构上,Han给了我很大帮助,我把我对架构的想法用Keynote演示给他,听取他的意见。很多东西我当时都不懂,如消息队列,他很好地帮我弥补了这些知识。
技术最终要为产品、团队和用户服务。懂一些技术的投资人有时候会不经意问起来你为何用Python,为何用MongoDB,他想听的不是仅仅因为Python速度快,MongoDB的效率比MySQL高你就选用它们,而是你在选型过程中的综合思考。
架构杂谈
互联网产品的架构很复杂,需要分成几个部分去考虑。
(1)服务器配置。网站的结构是什么样子的,几台服务器,它们之间什么关系,以后如何扩展。最好还能考虑上线时的拓扑以及3个月后可能的拓扑。
(2)服务端架构。打算用什么技术/框架/库/开源软件实现服务器端软件。例如,用什么搜索框架,用什么缓存框架,用什么消息队列,用什么协同过滤/推荐引擎。
(3)前端架构。打算用什么技术/框架/库实现客户端软件(包括Web客户端和App客户端)。例如,以Web客户端为例,用什么DOM框架,用什么MVC框架,用什么库来简化开发,用什么UI组件,用什么CSS框架。
(4)软件架构。系统有几大对象,它们之间是什么关系,模块怎么划分,关键路径的数据流怎么走。关于架构,一定要多问有经验的人士,因为,有时候你自己没有某方面的感觉,甚至不会想到问自己什么问题(答案是什么有时候并不重要,重要的是问对了问题)。