编者按:开源很简单,只要你想干就干对吧。也许,但如果你想在开源上取得成功,就得听听过来人的经验教训。做开源项目绝不仅仅只是写代码那么简单,甚至最困难的都不是写代码的部分,而在于你如何宣传和推销,如何做好维护,以及如何跟一帮喷子打交道。Formidable的开源总监用一篇苦涩的开源指南告诉你:如果你不是真心喜欢开源的话,最好不要去做开源项目了。
嗨,我是Ken。
我是Formidable的开源总监。
如果你听说过我,可能是因为以下两点中的一点或者全部:
我在Twitter上面是个话唠
因为Slick Carousel、Webpack Dashboard、Spectacle、Cash……这些开源库
今天我们主要关注第二点。最近(以及过去)有很多人问我开源方面的指导,今天是我觉得想写一写的日子。
不过在此之前,我会先谈谈为什么你想做开源的问题,以及我的个人经历。
为什么你应该写OSS(开源软件)
说到为什么,开源对你和你的职业生涯的好处可以列举很多:
它可以为你的个人品牌创造奇迹。如果你有一个很火的项目,大家就会熟悉你和你的工作
它可以为你的公司品牌创造奇迹。提供和维护开源项目能提高品牌的知名度。让员工有时间去做这个然后看看他们的想法变成现实,这可以让人知道在这里工作很棒
作为开发者你可以得到成长!你不再只是写写孤芳自赏的业余项目脚本了。有人盯住你,所以你会有积极性去把东西做好。
你会得到回报。因为John-David Dalton写了lodash而节省了你这个项目的开发时间一样,你也许也会用你的代码帮别人节省时间。你成为一个人人为我我为人人的社区的一部分。
感觉会很棒。虽然这个是个人体验,但每次有人感谢你对其项目的贡献或者告诉你有关你节省了他们时间的故事的时候那种感觉都非常奇妙。
这未必能帮你找到一份工作,因为大多数公司并不严格地根据GitHub的星星数量去招人,但是如果说这不会帮你得到一次面试机会我就是在撒谎。
我的OSS经历
我还是承认吧。我是有史以来最糟糕的开源维护者。OK,也许不是最糟糕的,但我每次并没有做到最好。
我曾经有过几次未能正确地管理好开源项目,不过嘿如果不是因为我成功创建了数量可观的项目的的话就没那些事了。
但是,我从每一个项目的失败那里都学到了一些东西,并且利用从中得到的洞察来帮助我下一次做得更好,这些我后面会谈。我当然越来越擅长这个了,但我希望一些读者也能从我的错误中吸取教训而不是再走弯路。
我决定简要介绍一下我的经历,因为相对于典型的OSS经历我的有点不太符合常规。不管你信不信,我认为我的整个职业生涯大概给不到20个不是我自己的项目做出过贡献。
我的第一个OSS项目大概是我最成功的项目。我记得那时候我还在一家广告公司工作,在为纽约的一个大型时装品牌创建电子商务网站。我是团队的资深开发者,通常繁重的JS开发都是我干的。跟我一起回到jQuery那时候的日子吧……
时尚电子商务比较有趣的一点是到处都是旋转木马。而且往往会有非常复杂非常有野心的设计。以至于现有的旋转木马/幻灯片库都不够灵活来支持他们提供给我的设计,所以我开始从头写旋转木马,用CoffeeScript来写。这玩意儿行得通,但是当然并没有让我让在同事当中更受欢迎。
所以我看到一个很明确的需求。得有一个足够灵活的旋转木马插件来支持设计师扔给我们做的任何事情,而且还有易用易于修改。于是我就写了。为我们大家。然后我觉得它很有用,既然如此为什么不帮别人节省大量时间呢,于是我就把它开源了……
结果表明它的确帮别人省了大量时间,而且大家似乎都挺喜欢。在发布后的头几个月里,其热度突破了天际。我对OSS还很陌生,对大家使用我的东西感到非常兴奋,所以热情高涨,甚至愿意彻夜加班去修补问题,推出新版,确保没人能与之竞争。
这些就不说这么多了,因为这篇文章是想提供一些提示的,不是讲我的故事:最后发生的事情是我停止了项目的维护。我宣布了几件事。我换工作了,所以我再也不需要旋转木马了。我已经脱离了那个问题空间。React也出来了,我早早就开始研究,所以我对jQuery之类的东西再也没兴趣了。
但是最大的原因之一还是因为我筋疲力尽了。我做得太辛苦了。评论里面个个都自以为是,说我们如何不应该使用旋转木马(即便我为了赚钱做得每一个项目都会有一个,而且都是手工设计),我变胖了,我妻子发火了。
从此之后,我在不同领域又做了几个流行的库,每一个都解决了一个不同的问题。我的最大恐惧之一是我再也不能写出热门的库了,担心点击数不如人意。目前为止我仍能避免这件事情发生,虽然我还会时不时做一些蠢事出来,但是至今仍令我无法释怀的还是对旋转木马项目的管理,那感觉就好像让半个互联网都失望了。
所以下面我要给大家介绍一些经验,希望你能够利用好它们做出成功的项目,而不是留下遗憾。
入门
开源跟演讲很像。许多人并不认为自己推销的东西足够有价值。这纯属胡扯。如果你看过冒名顶替综合征的东西的话,这完全是对的。每个人都有自己的独特知识构成,没有一个人什么东西都懂完。你兜售的东西总会有人需要的。
我有两个独特优势1)看得开 2)自信心爆棚,所以我只管写出来,但是我注意到这两点对很多人都比较困难。
我的建议:
尽管去做吧!
可能会发生的最糟糕的局面是什么?别人会指手画脚?我来告诉你吧孩子,哪怕你把最完美、最有用、最令人印象深刻的代码放到GitHub上,你猜怎么着?照样有些混蛋会进来吐槽发牢骚。这是不可避免的。最糟糕的情况下你也能学到一些东西。有人可能会说,“嘿这搞得性能很糟糕”你要么“呃我不会编程,算了我退出”,要么“哦哇哦,多谢你的提示,刚刚改好,现在好点了。”要成为把它做得更好的那个人。
那么你应该开发什么呢?好吧,这个问题而可是价值百万美元的啊。
我是这么看的:
你有一个问题
对于这个问题你有一个解决方案
你提供的这个解决方案包装得非常好,大家都想用你的解决方案去解决自己的问题
那么我们就来谈谈如何包装的问题……
API设计
假设你有了自己的想法。你有一个问题,现在你已经解决了这个问题。但是你还希望别人也用它对吧?以下就是一些提示告诉你如何让别人也想用你的东西。
首先,要看看之前的技术和你的竞争对手。如果别人的库做的东西跟你的一样,你就得有与众不同的东西才行。假设说你想开发下一个lodash。好吧助你好运。但除此以外,为了能争取到lodash的市场份额,你得有吸引人之处。你的东西必须要有更小或者更快或者更好的API。知道为什么我会这么做了吧?
说到API设计,需要有一些平衡。你可以做一个开箱即用不用做任何事情的库,可是这样的话大家就会抱怨想要修改的东西。你可以做出最灵活、可配置型最强的库,可这样一来你就会成为Tobias Koppers/ Sean T. Larkin,而大家就会抱怨自己要做配置的工作。(对不起Sean,我是被迫的。V4版做的很不错。)
你希望找到其中完美的平衡,既要尽可能方便使用,又能进行必要的配置。在此之上,你希望保持简洁、明确以及可用。不要聪明过头,否则的话你会惹毛所有人的。
我喜欢做的一件事是用非常明了但不聪明的方式写源码。因为这样可以让别人更容易做贡献。东西是什么就按照什么命名,不要做自嗨式的编程,如果你要搞东西的话,要注释一下为什么。
这段时间以来我没写过一行代码,直到我完成了一个心目中想要的模拟API。如果你要把它做成真正的API的话是要花些时间的,但这是一个值得努力的好目标。你会知道什么时候API做对了的,因为那时候你会感觉喜欢上它。
准备好发布
现在你已经解决了你的问题,并且包装得很好了。现在是是时候发布它了。但在你做之前,如果你希望别人使用的话还需要有些事情发生才行。
写点该死的文档。
这不是开玩笑。你的文档得是有史以来写出来的最好的文档。避免用居高临下的口吻去写东西。你需要在开头有类似标题链接索引这类的东西。你的有个开头章节解释那些如何让这玩意儿第一次跑起来的折磨人的细节。你需要把API的所有边边角角以详细到荒谬的地步全都写出来。
如果你有一个方法,你应该把预期的参数、类型以及返回类型都写进文档里面。你应该说明它做什么。你应该给出例子来解释如何去使用它。让别人很容易就能使用你的库。
你应该说明如何做贡献。你应该说明如何运行所有这些编译步骤。如果你引用了另一个项目,或者概念,要提供链接。如果你引用了任何可链接的东西,链接过去。
要彻底详细,结果会大不一样。
写一些该死的测试。
给我仔细听清楚。你应该把测试覆盖到合理的占比。原因是:
这会激发你对你的库健康情况的信心
这会让你充满自信地合并PR(Pull Request)
这会让你在暂停项目一段时间之后自信地继续工作下去
有一次我发布了一个库,但没有经过测试,Paul Irish就说了,“如果做过一些测试的话就酷了。”自然,我的反应是,“哦天哪,是Paul啊”然后开始写测试。写了那些测试后我一共找到了15个BUG!谢谢你Paul!
如果你写了任何东西,那就继续写点测试。求你了。这是锦上添花的事情。这可以省掉我很多时间和痛苦。
写完测试后,把它在Travis或任何持续集成平台上设置好,你就能高枕无忧了。
使用类型
测试没有抓到的bug,type都能抓到。现在如果你不对你的JS划分类型,这种举动就像开车不系安全带一样。此外,随着越来越多的人使用TS(TypeScript)或者Flow,他们都假设type已经就位。用类型来写库,导出和提供类型,你会感谢我的。要么让别人到后面再给它标注类型,这将是第三方风格的,过时的可能还是错误的。你看着办吧。
Repo(代码仓库)的先决条件
README.md
CONTRIBUTING.md
LICENSE.txt
一个有效的、填好的package.json
呃,README。你永远应该把LICENSE.txt放进去,否则的话一些人就用不了你的代码库。授权用MIT就可以了。不要自作聪明自己写一些授权声明。只用MIT。写吧。
CONTRIBUTING.md不仅是指出如何做这个项目的好地方,也是链接到/添加到你的行为准则的好地方。不管你同不同意这个概念,一定要增加行为准则,相信我。这会让某些人对贡献感到舒服并且参与进来,今后你要是有问题的话,这里也是把讨厌的人踢走时告诉对方原因的一个很好的指示牌。
锦上添花
假设你已经写出了很棒的文档。API设计的很好,所有的先决条件都就位了,并且你已经准备好让你的代码库看起来比较像样了。但我还有些意见。
勋章。没有东西能像勋章那样让你的代码库看起来更加像样了。勋章太多当然不好,但如果你纳入一些有用的勋章的话,这就是正统的印记。这说明你很上心。
像npm版本,测试状态,覆盖率数据等这样的东西也是很好的。
此外,Markdown支持裸HTML,所以你可以让你的repo标题更好看点。把东西居中排列,添加引言,美化一下。
如果你真的想拿金牌的话,学着这里(https://github.com/kentcdodds/all-contributors)一样增加贡献者条目。
认识给项目做贡献的人真的是非常好。
发布 & 营销
好了现在一切就绪了,是时候闪亮登场了。怎么才能让别人过来看看并且使用你的新库呢?
我的建议非常具体。周一美东时间12凌晨发布。这是欧洲一天的结束,是纽约午休时间,而旧金山还在任何事情还没做完的早上。这时候有大量的受众正在滑动手指,在互联网上闲逛呢。
至于怎么发布,我想Twitter是第一站。做出大胆的声明。
“厌倦了用键盘写CSS?猜猜看,现在你可以用Xbox控制器来写了!”
“Stack Traces让你很沮丧?如果是在VR里面跟踪这些会怎么样?”
开干吧。但要有吸引力。使用图片。或者视频。要直截了当让人明白它是做什么的以及为什么他们要使用它,附上链接。这个流程应该这样:
浏览Twitter
噢看看这条推特
噢MD,这个东西居然能做这个?!
点击链接
进入到代码库,噢它看起来挺像那么回事的
去到入门
拷贝/粘贴到终端,爽一把
[点击星星按钮]
你的代码库受欢迎程度可能要取决于粉丝数以及你向他们推销的技术方向,但这些一般都是有用的招数。除了Twitter用户以外,在HN(HackerNews)和Reddit上面发布也效果不错。
此外,需要的话还可以跟着发布一起发表一篇博客文章,尤其是如果你是在公司的旗帜下做这件事的话。你可以用更长一点的形式展示出来。
要大胆。要有信心。准备好给你的东西留够版面。
维护
我很害怕说到这一部分,因为这是通常是我经历最糟糕的地方。不过我还是很乐意给你们谈谈我从各种失败中吸取到的教训,希望你们看了能够知道会发生哪些事情。
现在你已经发布了你的库。接下来可能会有两种情况发生:
1、它失败了。
谁会在意呢。我就经常发生这种事情。重头再来过呗。有时候一些东西火不起来。这未必就意味着你很糟糕或者你的想法不行,只是时机不对罢了。重要的是你做出来了,你做对了。下一次你再开发的时候,你为成功所做的准备就更加充分了。给自己鼓鼓劲,下次加油吧!
2、它火了。
这时候才是你真正麻烦的时候。大家喜欢你的东西。他们在推特上面转发你的东西。你得不断改bug回答问题并且为你的想法辩护。对此我有一些看法。
首先,如果任何人对折腾你的库感兴趣的话,让对方成为维护者。再重复一遍:
如果任何人对折腾你的库感兴趣的话,让对方成为维护者。
原因是:时间会流逝,新的技术会出现,问题也会改变。你也会变。但你的repo还在那里。如果你你委派别人的话,你就会碰上糟糕的时刻。你会因为维护而筋疲力尽,你会对这个项目心怀怨恨,这东西最后会变成你的负担。相信我,这件事情授权给别人干。
接下来,我想谈谈跟人相处的事情。
这是开源最大部分之一,在很多时候甚至比写代码还要重要。等着吧,大家会吐槽你。他们各个都觉得自己有这个资格。他们会公开蔑视你的项目。
让那帮家伙见鬼去吧。
我已经花费了那么时间在做东西上面,现在我希望能把精力放在别的地方。相信我,让那些喷子见鬼去吧。
不过,要带着警惕的眼光去辨别那些喷子。你知道,有时候有些人可能看起来像是个喷子,但其实不是。要考虑到这个,要知道你是把代码发布给全世界。要记住并不是所有人都讲你的母语。
想象一下你想给一个用俄语写的repo做贡献。但是你不懂俄语。于是你Google Translate“嘿这里有个什么时候实现这个的时间表)”。然后比方说Translate返回的俄语意思变成“这个什么时候能完成。”乍一眼看过去你可能会觉得“嘿这个家伙有什么问题啊”,后来你才意识到在互联网上意思的传达做得不是那么好,经过翻译后就更加了。
要小心这个,有时候他们不是情绪失控,只是不讲你的语言。
除此以外,我的最好建议是对你的PR(pull request)要有牢靠的CI(持续集成),要回答问题,要有PR模板。在代码库上你会遇到一堆的问题和PR,如果你想管理好这些的话,有一些基本规则是必要的。我的建议:
要求重现案例或者失败的测试用例
要求提供bug发生的情况
某些一次性的bug意思哈没有时间找出来的。让用户向你证明这个bug是存在的,并且让你能够方便地识别出来,这样你就有时间去解决问题了。
此外,在CONTRIBUTING.md的某个地方指出大家应该在处理PR前在issue里面跟你先讨论一下想法是值得的。全世界最悲哀的事情莫过于有人非常努力地处理一个永远也不会得到接受的PR。
说到接受PR,本节中我想告诫你的最后一件事是你不必去做别人要求你的东西。因为屈服于用户我就浪费了很多力气去做个API出来。
大多数时候,一些人要求一样东西只是为了解决他们自己的一个孤立的问题,但是那个问题对于广大的社区是没有价值的。要警惕对你的API的任何修改,因为那些有着极端需求的人会把你的API搞砸的。要做对核心库是对的东西,而不是帮一些搞滑翔机遥控系统的家伙去解决问题。
哦我撒谎了,还有一件事。要恰当地使用语义版本控制。
求求你了。否则的话每个人都会失去理智的。还有推送标签。还要写版本说明。详细的版本说明。随着你的库的不断演进,让投入到里面的人知道发生了什么是非常重要的。
要透明、清晰、有信息量。否决事情要有宽限期。如果别人投资了你的库而你的修改让他们的应用出问题的话,他们是不会高兴的。用富有同情心的方式更新你的库。
结论
到了现在,你大概已经意识到我不仅做OSS很糟糕,而且写东西也是。但是有人要我写,于是我就写了。我希望这篇流水账能够帮助一些希望发布自己的开源项目的人,让他们能节省一些时间,以及避免破坏到他们的心情。
这里面有很多的坑,但是如果你每一样都能照顾到的话,你的日子就会比我更加好过,成功的机会也会更大。
最后,我还有一个建议。除非你真的想做这个,否则的话不要做。不要觉得这是你必须做的。不做这个你也能找到工作。不做这个你也能成为一名好的开发者。我从中获益良多,也非常享受做这个,但是我永远也没法把免费花在那些库上面的时间给要回来了,我本来可以用来跟家人待在一起或者追求我的爱好或者做任何可以给我带来收入的事情。做这个因为你想做。如果你对自己开发的东西没有激情的话,你可能是不会成功的。
原文链接:https://medium.com/codezillas/a-bitter-guide-to-open-source-a8e3b6a3c1c4
编译组出品。编辑:郝鹏程。