Lever's Castle

「译」使用Haskell创业4年的感受

January 15, 2017

我想说的: 最近在学习Haskell语言,这是一门函数式编程语言。很多人都在问我为什么学它,问我学会这门语言能做什么,问我这门语言的市场占有率怎么样。 其实,站在一个初学者的角度,我没有办法很好的回答这些问题。我一开始去学习这门语言,只是想去了解函数式编程这种与之前所学的、所用的编程方式完全不同的编程思维。你问我学会了能做什么,呵呵,多学点东西又不会死。 当别人问我这些问题的时候,我也在问我自己。面对难度如此高的语言,我也会想去逃避。我在不停的怀疑,自己这样去学习是否真的有意义。 这个时候,就需要来点鸡汤啦 ---- 有效行动的逻辑 在有效行动者的世界里面,他永远相信两件事: 第一,先干了再说,因为只要干了,我就会遇到更多的意外,就有机会把握这些意外。 第二,只要我行动,就有机会洞察优势背后的代价,有机会把那些坏事变成好事。 总结一下就是,如果有件事可干可不干,时间允许的情况下,那就去干。 翻译这篇文章,也只是想让更多的人了解Haskell这门语言,同时也坚定自己的信念,继续学习下去。

原文链接:http://baatz.io/posts/haskell-in-a-startup/#fn7

下面是正文:

2012年,我和我的合伙人共同创办了一家公司----Better,一家新型的面向企业的线上学习平台。 我们的目标是让大公司更快、更便宜地开发,提供适应性,跨平台,多语言的在线课程。

从第一天起,我们就决定使用Haskell作为我们的主要开发语言,直到我们的团队已经扩展到了10个开发人员,它仍然是我们在后端使用的唯一语言。

经过一段时间的试验和开发,Better在几个月的时间里,经常性收入从0美元增长到了500K+,客户包括了美国运通和Swissport等大型企业。然而,分布式的模式被证明是更有效的解决方案,我们最终出售给GRC Solutions,一家澳大利亚的合规公司。

尽管大家对Haskell的兴趣似乎在不停的增长,但它在生产环境中的使用仍然少之又少。有些人甚至错误的认为这只是一门学术语言,别的什么都做不了。在这篇文章中,我想告诉大家我对项目中使用Haskell的一些看法。你能用它完成项目么?它能在实践中保持稳定么?你能招到相应的开发人员么?是否更多的公司应该使用它?

我对上面问题的回答是YES。这可能不会适用于所有的问题或者所有的团队,但这样做绝对值得考虑。对于构建服务端,Haskell可能是你现在所能找到的最接近秘密武器的东西。

为什么我们选择Haskell?

在创建Better几年前,我为一家财务顾问公司开发了一个预测模型。第一款原型是使用Python开发的,结果这个模型很脆弱而且总是会出错。我该如何确保变量的类型不会改变?我该如何避免函数中某个值发生突变?我需要花很多时间去写大量的测试用例,才能保证程序不出错。

我回想起了大学时学过的Haskell。用Haskell做了几天的实验之后,我惊讶的发现,Haskell似乎更适合这个任务。工作了一周之后,我得到了一个粗糙版本的预测模型。后来,当我们开始创办Batter时,我相信Haskell会比其他常用的语言更有效率。

Haskell拥有纯净、惰性、静态强类型和类型推断等特性,这些特性让它跟别的语言区分开来。纯净而没有副作用,让开发者更容易查找程序中存在的问题。惰性让我们更好进行函数组合和性能优化(以更难以理解的存储开销为代价)。静态强类型和类型推断机制,保证了程序的一致性,让重构更快乐,顺手消除了一大波bug,还不用编写和维护测试用例。把这些特性叠加在一起,绝对是一种愉快而且高效的开发体验。

使用Haskell能把事情办好么?

如果你从头开始构建项目,Haskell完全能够让你用相当有限的知识完成工作。用Haskell写的代码可能不会特别整洁和高效。但是最终你会发现,仅仅使用5行代码,就可以建立一个标准的可以被不断重用的抽象。

对有经验的开发者来说,提高Haskell的运行效率是一个不小的挑战。这对新手来说实在是太不友好了,为了提高效率,你往往需要学习很多东西。Haskell十分重视概念和抽象,很多Haskell中的概念只是名字看上去比较吓人,其实很好理解。学习Haskell时,可以参考一些教科书,但是很多博客和论文也具有很重要的学习价值。Haskell不可能符合所有人的胃口,但其中思想的价值远超语言本身。如果通过学习Haskell,能够影响你在编写程序时的思维方式,那么目的就达到了。

在实际的使用中,我们对Haskell最大的抱怨之一是基本的工具支持。使用cabal-install构建项目太不顺利了。之后出现的Stack倒是减少了这方面的槽点。Stack对初学者来说是十分友好的,它让大型Haskell项目的管理更加方便。你可以做许多其他工具链方面的标准,像github上面的fork库,依赖fork库就不必再发布包了。

Haskell的工具支持完全没有达到它应该有的样子,特别是在IDE和编辑器的支持上。可能存在各种不同的集成开发环境,而且目前来看还是十分混乱的,没有一个通用的标准。对Haskell如此丰富而且有用的类型信息来说,这简直是个耻辱。

如果谈到各种各样的库,它们的覆盖面虽然不是很大,但还是足够使用的。我们也用Haskell写了一些比较粗糙的内部库(比如通过Mandrill的API发送邮件)。Haskell同样也有些很出名的库,但是去确定使用哪个更好并不容易,而且质量差异也很大。如果不算内存出现的问题的话,我们只遇到过一个严重的库错误,这个bug导致无法进行https连接。

至于语言本身,Haskell的惰性要求使用者考虑更多的空间复杂度。其实是有很好的工具和技术能够帮助开发者做到这一点的。你当然可以编写节省空间的代码,但这需要你有意识的去做这些事情。至于语言本身,Haskell的惰性计算需要你考虑更多的空间复杂性。有很好的工具和技术来帮助解决这个问题,你当然可以编写节省空间的代码,但它需要比使用严格的语言更有意识的努力。 也许你会通过使用更好和更强大的抽象来回收这种心理负荷。 还有一些其他小麻烦,如字符串类型之间的转换,标准风格的缺乏,没有良好的记录语法。Lenses确实解决了记录的问题,但是这东西不好调试,而且需要花很多时间学习。

在日常使用中,Haskell其实是特别务实的。最关键的一点,我认为很难找到一个Haskell代码库有值得重构的点。类型推断系统和纯度能够在你阅读代码寻找bug时给你更多的信心。

Better在经历了几次推到重写之后,还是放弃了创建一个伟大软件的雄心壮志。尽管我们对市场的判断总是出错,工程团队却从未失败过。

软件稳定么?

Batter平台每周大约会产生50万次的用户学习行为,它已经运行了一年多,没有停机,也没有维护。我们至今还没有找到任何bug。到最后,在停止平台的开发之前,我们做了一次重大的重构。

我只是举些例子来当证据,软件运行的那么稳定让我也感到很惊讶。 我们有一个伟大的工程师团队,他们值得信任,我也同样信任Haskell。 我们没有使用测试驱动开发,我们仅仅针对关键部分进行了测试。 这似乎是正确的成本/质量权衡方式。如果你现在问我,我仍然会这么做。

Haskell的类型推断系统使开发者不必像在弱类型语言中那样,需要写一堆的测试用例来捕获不一致。 具有类型推断系统,可以减少编写和维护测试用例带来的成本。我认为,测试驱动开发的论点不仅仅是编写测试来捕捉bug, 它同样有助于开发人员更清楚地思考问题。 然而,Haskell的纯净和类型比测试驱动开发这种方式强有力多了。“一旦编译通过,它就能工作”,这句话可不是个玩笑哦。

我可不是说测试不重要,相反,测试其实是相当重要的。 类型系统能够保证类型的一致性,但是一致的程序也可以做错事。测试是迭代速度和质量之间的折衷, 不同的业务需要不同的权衡。

Haskell也有方便你做测试的优秀工具。 例如,QuickCheck可以基于工程师所指定的程序应该保持的属性,来自动生成大量的随机测试用例(利用Haskell的类型系统)。

因此,Haskell似乎特别适合用于对软件的正确性和质量要求较高的项目中。 你可能期望以减少迭代速度为代价保证它的安全性,但有趣的是,你将会发现自己的迭代速度远比比使用弱类型,非纯净语言更快。

你能雇到写Haskell的人么?

Better这个项目是在苏黎世进行的。我们刚开始进行时,不知道这里有谁会使用Haskell,但是招聘开发人员比我们预想的要容易的多,这很大程度上都要归功于Haskell。找到合适的开发者还是需要花一些力气的,但我们的经验是,很多来面试的开发人员得知能够用Haskell开发项目时都表现的很兴奋。我们终结了一个伟大的团队,其中几个人是从国外搬到苏黎世与我们合作的。很早的时候我们就决定公司不走远程开发的模式,但如果您的团队愿意接受远程开发,您应该会有更多的可供选择的机会。

我们根据我们自己的需求,将技术,兴趣和动机这些条件混合起来作为招人的标准,根据这些标准我们招到了几个技术很棒的Haskellers。我们当然雇佣过只有一些Haskell基础的人。我们的一位开发人员是直接从物理学学位过来的,在生产环境的指导下迅速成为了经验丰富的开发人员。

虽然我们的薪资水平不能与Google,IBM苏黎世研究院或本地的大型银行相提并论,但我们仍然能吸引到优秀的人才。使用Haskell是我们能做到这一点的原因之一 ---- 好的开发人员倾向于使用更好的技术。

它对公司的文化有什么影响么?

很难将编程语言对工程师文化,雇佣决策,管理风格和个人特性的影响分离开来,因此我们的工程师文化是深受Haskell影响的。

人们不会为了高薪而学习Haskell。市面上并没有足够的需要Haskell的工作。这种语言也比其他语言更难学习,这会过滤掉那些不愿意努力学习有趣的东西如functors,applicatives和monads的人。

这样做的好处是,如果你雇佣的人花了一点时间学习了Haskell,他们可能会比平常人更有内在动机来编写代码和学习新东西。缺点是他们很有可能厌恶工作,因为工作是在浪费和减少学习的机会。

因此,我认为选择Haskell有助于建立我们想要的工程师文化,但它不是魔法 ---- 我们也花了很大的力气去招聘,我们试图做的更加公平,我们寻找那些能够驾驭各种语言的开发者。

那么,你应该使用Haskell吗?

Haskell并不适合所有人。它不同于大多数开发人员的习惯。它需要学习各种很抽象的概念。它的生态系统不像现在流行的那些语言那么成熟。它不是最快的语言,黑客一起快速开发原型也需要2天。它有垃圾收集,因此它不适合实时系统。它的空间复杂度总是变幻莫测的。拥有Haskell生产经验的人少之又少。

但如果缺点不会破坏你的面试,你可能会得到一个很棒的待遇。 Haskell适合在小型的,技术熟练的和不断成长的团队中使用。随着你的代码库的扩展和发展,Haskell处理复杂性,澄清思维和确保一致性的能力是一个福音。 你不用担心服务器会崩溃这种问题,放心去睡大觉就好啦。你不需要花很多时间在旧代码中寻找bug。你能够相当自信、敏捷地重构。在招聘时,你也会从Java,Node和Ruby等等市场中脱颖而出。你会开始在全新的抽象方式中考虑如何构建程序。谁知道呢,你甚至会十分享受你的工作呢。

如果回头重新去过在Better的那几年,很多事情我也许会做不同的选择,但是选择Haskell作为主要的开发语言这一点,我始终不会改变。


Lever

痕迹
没有过去,就没法认定现在的自己