聊聊初创公司的后端语言选型(小众语言)

jopen 8年前

在创业公司初创伊始,如何选择合适的技术类型决定了如何进行合理的业务支撑方向。如果你在读这篇文章之前,更倾向于选择Java/C#/PHP技术栈,我觉得对于你而言,这篇文章其实对你帮助不大。因为对你而言,这些技术栈意味着更加方便招人,更方便的故障处理资料等等。但是对于一个初创公司选择合理的小众语言技术栈而言,我想这篇文章对你也许有一些帮助。

在文章开始之前,我觉得有必要描述一下所谓的小众语言,这里我在最初进行技术选型时,考察了包括:

  • Python: 你可能在接触爬虫、大数据分析等等方面听过Python的大名,大家都知道Pythonist都习惯说的一句话就是:人生苦短,我用Python。
  • Ruby: 你如果做过Web框架,你遇到最多的是很多人都会提到RoR框架。用过之后只有一个惊叹了。
  • JavaScript(Nodejs): 有没有听过JavaScript全栈工程师?有没有听过JavaScript全栈工程师?有没有听过JavaScript全栈工程师?
  • Golang: 简单粗暴的语言,也许你见过很多人跟你吹嘘,Golang是下一代的云计算开发语言。

其他语言太过于小众,考虑到更多的社区支持等等功能,目前不在考虑的范畴内。

小众语言的劣势

正所谓知己知彼百战不殆,在了解一个技术选型之前,最好是研究这些语言的缺点,因为事实上,你最后感觉这个技术选型不适合你的时候,根本的原因是这些劣势影响了你。

在上面提到的几个语言中,Python、Ruby、JavaScript是动态语言。关于动态语言的争议最大的地方是:动态语言到底是否合适进行大型项目。事实上,在某些阶段,多人合作,并且大家水平语言不同时,这个时非常大的问题:团队更多的时间要确保动态语言的准确性上。对于保证一个项目的高可用、低错误率时,由于语言的动态特性,对程序开发时的单元测试和后期集成测试的要求更高。由于变量在运行时才会赋予类型含义,因此也很难在静态检测过程中发现问题。这样对测试人员的压力也会更大,当然如果你没有合适的测试人员时,这个时候通常会变成,你只测试了理想情况下的成功失败情况,而对特别异常情况缺少预估。

Python、Ruby语法对程序员而言最大的成本在于需要重新学习一门新的语言。这个学习成本、时间成本通常对初创公司而言通常是支付不起的,哪怕像这些比较容易学习的动态语言而言。另外一个值得一提的是,无论是Python还是Ruby,从长远看,如果你后续有较大的用户增长又需要保证用户体验时,Python、Ruby的执行效率和吞吐量会有较大的影响。

Python最大的问题是可能和程序员入门的语言差距较大:用4个空格表述程序缩进。这意味着,程序员直接从网上寻找解决方案(拷贝代码)时成本更高,因为很有可能他需要手工进行代码格式化,这样有可能造成程序逻辑的改变。另外一个不得不提的是一些Python库看似好用,实际上或多或少有有一些坑,这对新手而言,往往是致命的。对应的,Ruby语言本身时不存在这些问题的。然而Ruby最大的问题是,如果选择RoR框架作为初始的Web框架时,如果没有一个熟悉RoR框架的人,那么学习RoR框架的成本是特别高的:因为对于一个通用型框架而言,你可能需要更多的特殊场景定制,这可能需要做大量的猴子补丁,这需要对框架有一个比较全面的认识。

JavaScript(后面统一用Nodejs代称)则借住Nodejs实现了高性能和较大吞吐量。而且从语言层面上,JavaScript对很多程序员并不陌生。然而,在过去的很长时间,真正熟练掌握JavaScript的都是前端工程师,这是一个尴尬的问题。对后端工程师而言,Nodejs需要不同的技术栈,而且大概没有公司希望一个完全没有任何后端经验的前端工程师去接手后端项目的开发的。Nodejs是一个年轻的语言,年轻必然会伴随一些问题,比如,库比较少。一些必要的库需要慢慢寻找。事实上,我也不得不吐槽,可能是开发者水平问题,导致很多npm提供的包,往往或多或少存在一些比较恼人的BUG,这些BUG可能会在你开发过程中,正常运行中出现,而你却不得不干掉它。对于这种东西,很多时候更快的处理方式是快速的进行修复,然而当你的程序员不具备这种能力的时候,提一个issue到开发者,由开发者进行修复,并且需要等待版本更新到npm源中。很多时候这个过程都是比较尴尬的,尤其是你选择了一个开发者并不是特别活跃的包。

Golang是一个编译型语言,语法简单,似乎一切看起来都是那么的美好。事实上Golang本身还是处于在Google开发维护的阶段,本质上虽然语言完全开源了,但是却不是一个完全社区维护的语言。换句话说,是Google会决定Golang未来的走向。不过好在第三方包都是由社区来驱动的,这样还是提供了更多的可定制性。另外一个比较烦恼的是Golang本身的包管理机制,事实上,这是完全不存在的。别告诉我你觉得go get完全足够了,那只是因为你还没有遇到依赖导致break的问题而已。不过从现在看起码Google意思到自己的问题,也正在努力改变吧。从前面一个问题也能看出,Golang目前是一个年轻的语言,年轻必然会伴随一些问题,比如,库比较少。虽然你可以利用cgo去桥接一些现有的C/C++库到Golang程序中,但是这部分的代码维护,涉及到GC的优化处理等各个方面,对开发者的要求其实本身不低。另外一个大家都会抓住讲的就是GC问题,在高并发环境下GC的影响从1.5开始下降了很多,但是GC并不像Java一样更加可控,很多时候还是需要进行代码层面控制。

上面所有的小众语言面临共同的问题,招人。没错,找到一个合适的小众语言工程师是一个痛苦的事情。虽然你可以通过语言的高开发效率去节省人力,但是当你出现人手紧缺的时候,去找一个合适的人替补就变成了一件昂贵的事情。通常你需要从现有的人员中培养则更加靠谱。(庆幸的是,我可以骄傲的说,经过培养后,哪怕我们的移动开发工程师也可以hold住我们现在的后端部分需求。)

如何选择合适的技术栈

这是一个复杂的问题。选择合适的技术栈,你需要覆盖上面我提到的所有的劣势问题。比如说,你选择了Nodejs,你就要考虑,你可以hold住所有的难点,你可以修正开源包的问题,甚至你可以解决现在没有包的难题,OK,那么你选择这个语言本身是没有任何问题的。

我在综合考虑之后,选择的技术栈比较简单:Python和Golang。其实选择的原因很简单, 这两种语言我更熟悉 。没错,只是这个是第一个理由。为什么会有2个技术栈,这个其实与我们现有的业务状态和未来发展的思考有关,这个会在后面进行一下介绍。

还有一个问题,我在上上段中提到的问题,厚脸皮的说一下, Python和Golang语言中的绝大部分问题目前都可以自己解决 ,这也是另外一个理由。

接下来,人员培养方面,上面提到的小众语言大多培训容易,以现在产品发展节奏和产品演进速度, 我们的人员培养成本目前是可以承受的

使用Python的原因,是 开发更快,从而快速试错 。利用现有的Web框架,搭配合适的数据库,我们可以在1-2周内实现一个完整产品的上线,快速试错。我们针对Python制订了一系列的标准,用于规范代码的格式,保证代码的强壮度。这个可以参考下我之前关于代码风格要求的文章。

使用Golang的原因, 在于大型长期稳定运行项目的考量 。事实上,我在前面也提到了,在目前的开发过程中,Python在多人协作过程中个人编码风格、工程性上要更弱、无法控制的内存泄漏等等问题,如果需要长期稳定运行,我更倾向于选择可以进行编译的编译型语言, 通过静待检查+动态测试方式,更好的保证程序的强壮型

结语

上面啰里八嗦说了那么多,只是想告诫大家,对小众语言而言,选择的机会成本是特别高的。如果你只是验证试错,或者你只是想卷一笔钱就跑,小众语言的高开发效率是绝对可以满足你的。但是从一个大型工程的角度,你需要通盘考虑小众语言的劣势,选择一个合适的语言作为你的技术栈。

来自: http://ipfans.github.io/2016/01/startup-architecture-language/