《途客圈创业记:不疯魔,不成活》一一2.3 早期产品

本节书摘来自异步社区出版社《途客圈创业记:不疯魔,不成活》一书中的第2章,第2.3节,作者:陈天,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.3 早期产品

与申请助跑计划同步进行的是途我睿产品的开发。事实上,从1月我与老板沟通了辞职事宜后,每个周末我都投入20小时左右的时间在途我睿的构思和开发(包括学习)上。

概念
途我睿的目标是“让自助旅行变得轻松智能”,这是一个很大的目标。做互联网产品,想法宏大不是件好事,因为要么无法面面俱到,要么干脆做不出来。如果你想打造太阳系,你最好先把太阳做出来。

所以我把问题进一步缩小为“让旅行计划的制订更轻松,更智能”。对于这个范围缩小了的问题来说,解决方案也不是那么显而易见。我们无法从硅谷的创业网站中找到答案,因为对于大部分美欧旅行者来说,中国自由行旅行者面临的问题都不是他们的问题。

语言不通。担心自己低水平的英语在目的地成为绊脚石。

请长假旅行比较困难,所以一定要把有限的时间充分利用起来,优化路线到极致。

一次去好些城市。

手头紧,自然想少花钱多办事。

所以硅谷的面向在线旅行的创业公司几乎没有往旅行计划这个方向发展的。与我们想法最接近的tripit走的是旅行预定管理的路线,是旅行计划的一个子集(这从另一个侧面说明我们想解决的问题还是有些太大了)。

我最初的解决方案是将旅行计划这件事与购物做个类比。这样做的好处是用用户熟悉的东西去类比我们的不那么容易理解的服务,这样他们更容易理解一些,也容易建立对应关系。

那时大家已经很熟悉淘宝、京东这样的电商网站的购物流程,挑选商品,加入购物车,结账。在我眼里,旅行计划有类似的模式:挑选景点(城市),加入行囊[5],分配到每一天,生成在线和可打印的计划。

抛开我们解决的问题是否是一个有大众持续需求的问题[6],就这个问题本身,我觉得类比购物体验是一个很好的解决办法,别人容易听懂,做起来概念清晰,而且很多指标可以从电商那里借鉴。如SKU(stock keeping unit,保存库存控制的最小可用单位),每个景点、每个目的地服务都可以是一个SKU。可惜的是,正如途客圈的发展一直在质疑和改变中进行一样,类比购物体验的想法,在我们产品的第三个版本中被彻底抛弃。

技术选型
在当时,我没有任何互联网产品的背景,但学习和写代码一直是我的强项。在Juniper,我也做了好几个很小很小的Web工具——coredum分析工具、每周报告分析工具等。C语言和汇编对我要做的事情几乎没有任何帮助[7],好在那时我对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里几乎是个梦魇[8](好吧,我PHP功底很弱的)。这就是symfony无论如何也无法赶上Rails的最重要的原因:它被PHP语言的限制给束缚了。按照Paul Graham的说法,语言的表现力上:lisp >> Ruby ~ Python > PHP >>>> Java/C等静态编译语言。

我非常赞同这一观点。另外,PHP不太适合开发后台服务,如写一些守护进程(daemon),这样后台的服务还需要用别的语言,所以PHP出局了,我决定从Python和Ruby中选择一门语言来实现途我睿。

在花了不少时间分别学习Ruby/Rails2和Django[9]后,我决定使用Python。基于以下理由。

(1)Ruby的很多特性太灵活,如开放类的修改,太灵活可能不利于团队开发(这点现在看来是我当时的偏见)。

(2)使用Ruby做项目的工程师很难招。从招工程师的角度来看:PHP >>>> Python >> Ruby。Python工程师不好招,但合格的Ruby工程师几乎招不到。

(3)我对Python的驾驭能力比Ruby高至少两个等级[10]。

现在回过头来看,第三点是最关键的,第一点和第二点其实都不那么重要。具体原因如下。

(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[11]开始学习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)软件架构。系统有几大对象,它们之间是什么关系,模块怎么划分,关键路径的数据流怎么走。关于架构,一定要多问有经验的人士,因为,有时候你自己没有某方面的感觉,甚至不会想到问自己什么问题(答案是什么有时候并不重要,重要的是问对了问题)。

开发
确立了要做的产品、使用的架构后,我和Alex草草敲定了产品的功能和UI(用户界面)。我们缺乏互联网产品经验的问题在这一刻开始显现,从此我们做了很多不那么正确的决策,走了不少弯路。我们之前的行业追求的是性能、可扩展性和高可用性,UI很次要[12]。所以我们几乎都没有美感,也不知道怎样更能打动消费者这个群体。有一次我在国家图书馆结识了新浪的Liujia,她对途我睿很感兴趣,在产品上提出了不少自己的见解,可惜那时我对产品设计师这样一个职位没太多认同,觉得自己兼任足矣,于是错过了产品上的一次提升。

要构建旅行计划,首要的是构建结构化的景点数据库。景点库可以用用户产生内容(User Generated Content,UGC)的方式生成,但是你需要有基线数据让你的用户用得起来这个服务。所以途我睿一开始就面临两重冷启动的问题:数据的冷启动和用户的冷启动。用户冷启动可以先放在一边不管,可数据冷启动迫在眉睫——它是一切的基石。

我想到的方式就是爬数据。当时国内旅游类产品没有太好的提供结构化信息的网站,尤其没有介绍国外景点的。因此我把目光转向了TripAdvisor(猫途鹰)。我们当时盘算“爬”下TripAdvisor的景点的数据,然后将名称和描述翻译过来,就变成我们的数据。这么做有些游走于灰色地带,但我们对数据做了深度二次加工,几乎没有原始的痕迹。所以虽然这不太光彩,我们当时别无选择。

TripAdvisor的页面DOM结构不是特别好,用Scrapy爬有点儿费劲[13],正当我研究怎样更有效率时,Alex发现了Gogobot,它的结构很漂亮,数据基本来自TripAdvisor[14],所以我就开始抓Gogobot欧洲的数据。

一个晚上就有几万条景点被“爬”下来。我又做了一个内部系统toureet.me用于在线翻译。Alex在网上找翻译人员,约定每个景点的翻译价格,然后可以用这个系统给第三者开账户,供他们翻译及结算。就这样,他负责景点信息的整理,而我则负责产品的开发。我在AWS注册了3个账号,用3台免费的最小计算单元(tiny instance)来运行还在襁褓中的途我睿。每天我都会把最新的版本上线。

回过头来看,双重冷启动对像我们这样一个创业公司来说是很要命的,我们提供了一个工具来创建旅行计划,但这个工具需要有大量的POI才能让用户无障碍使用;然而大量的POI完全靠我们本身产生并不现实,所以我们期望以后有海量用户的时候,用户能自然帮我们完成这件事。其他依赖用户产生内容的网站,如论坛、帖子(主帖和回帖)就是用户唯一要创建的内容,内容和内容间没有依赖性。但在途我睿,用户要创建的旅行计划,严重依赖POI,如果没有用户要使用的POI,它需要自己创建。两种有依赖性的内容大大增加了用户创建的成本,为了降低这种成本,我们被迫维持一个“庞大”的编辑团队来为用户创建POI。这让我们的人员结构从一开始就往臃肿的方向发展。当然,如果说我们能跨过这个坎,让用户增长的红利启动网络效应,那我们的城堡外将建起一道宽阔的护城河。

我们后来得出的教训是:小团队一开始要避免做太复杂的、用户使用成本高的产品——尤其是要避免在数据和内容方面双重冷启动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值