各位好久不见,有些小伙伴可能知道大概1年多以前我开始维护log-record[1]项目(Java业务操作日志记录框架)。这期间项目陆陆续续更新迭代、发布新版本,一路走来也踩了不少坑。这篇文章主要是想给希望开始写开源项目的同学们一些开源项目维护的实操建议,也算是给自己梳理一下做一个开源项目需要注意的事项。
此外,本文讨论的个人开源项目仅限于代码为主的项目。像一些新闻、教程、电子书、工具集锦类开源仓库,不在本文的讨论范围内。
当然了,如果你已经是一个经验丰富的开源项目maintainer,那么请赶紧关掉这篇文章,并且联系我,让我好好抱大腿 :)
首先,我们要重点探讨如何准备个人开源项目。一个最基础的思考是,你的项目灵感从哪里来?当你觉得有了好的想法后,又应该做哪些事前调研工作?
积累灵感是开始一个开源项目的第一步。
很多时候灵感源自于我们日常的学习和技术工作上的积累。例如,在工作中遇到的问题,想解决的BUG,或者对某项技术的深入研究,它们都可能给你灵感。
此外,每天多多阅读技术文章、关注技术新闻以及浏览Github Trending都是获取灵感的好办法,多元化地获取信息对于积累灵感很重要。
之前硕士期间写论文经验的告诉我,当你对一个研究方向没有了解全面的时候,你的大多数想法是很幼稚的,有很大可能已经有前人替你踩过了坑,或者有了现成的框架和产品。
所以在确定你的项目主题之前,一定要充分的进行调研和搜索,保证你的项目在某个方面具有独特性。在调研过程中,你最好要罗列出现有和你相似的产品为何不能满足你的诉求,而你的项目又和他们有哪些差异化的特色。
当然,凡事都不要走两个极端,当你发现你的想法真的非常独特,没有人做的时候,你要考虑下是否是因为成本过大,或者受众过小的原因,才导致没有现成的产品,那么你来做第一个吃螃蟹的人,会面临的工作量和难度,你自己是否心中有数。
如果在经过认真的调研后,你发现你的想法确实在网络上没有很好的产品,那么它可以作为一个好的发力点。
OK,当你有了灵感,并且对于自己的这个想法十分有信心之后,让我们来讨论一下,当你准备正式开始一个项目时,你应该遵循的一些方法和我个人的经验。
对于一个开源项目,华丽的外表并非贬义。你可能需要花大量的工作去做编码以外的工作。此外,你还需要一些推广你开源项目的手段,毕竟,如果一个项目一直不被人看见,你也会很快失去动力。但是,不要害怕,有一个好的、有效的灵感其实已经成功了一半,让我们从拙劣的模仿开始,慢慢成为大师。
能者摹形,大师窃意。
很多时候我们点开开源项目主页,首先就会大致浏览下项目的README,所以无论如何也要把第一印象做好。
网上有很多关于如何写开源项目README的文章,这里就不展开讲了,推荐一篇写的还不错的外网翻译:如何写出优雅且有意义的 README[2]
对于我来说,有个很喜欢做的事就是贴上很多小徽章,用户会先入为主的觉得你的项目,有点“专业”。下面用几个仓库的截图举例子。
我的log-record也像上面的知名仓库一样,依葫芦画瓢,贴上了几个我认为重要的徽章(Badge)
对于不同类型,不同语言的开源项目,README的写法也千变万化,我也没法给大家推导出一个万能公式,但是我可以给大家介绍几类典型的README:
请多多参考优秀项目的README,将应有的模块尽量补全,之后慢慢迭代。
除了README,清晰的目录结构也很能吸引用户,以hutool和我的log-record为例,由于是Maven项目,可以尽量让用户能够看出module区分。此外,会有一些额外的文件夹,例如:
比如hutool项目:
log-record项目则是按照Maven模块进行了简单划分:
一个良好的commit记录能够让使用者对项目更有信心,也更有说服力,证明其contributor都是(至少表面上是)对代码质量有追求的开发者。
我的Log-record,做的不好的是我中英文混杂。如果你的仓库明确面向中文互联网,你可以全部以中文来写,但是如果想面对全球用户,还是尽量采用全英文为上策。
相反,一个差的commit log让人第一感觉就是不专业。这一点要吐槽下hutool
如果你做的是Java项目,那么最好项目能够索引到公共Maven仓库中,才能吸引更多用户,毕竟用户最需要的是方便地拉取你的包,而不是手动下载上传到用户的私有仓库里。其实大部分个人的Maven项目都可以提交到公共Maven仓库中,可以参考之前我的文章:如何提交自己的项目到Maven公共仓库
以我的log-record项目为例,我会按照下面的顺序,进行版本迭代:
发行RELEASE版后,你的仓库主页上会有最新的版本信息,方便用户查看和使用。
https://central.sonatype.com/artifact/cn.monitor4all/log-record-starter
这一点希望大家尤其重视,开源项目,也要尽量对用户负责,对项目的质量有追求,所以做好项目的单元测试和其他集成测试等工作,并且最好能够将你的测试覆盖率展示出来,也能够增强使用者的信心。
这里推荐一个网站codecov,它能够通过多种方式帮你的仓库维护一个测试覆盖率数据,并且通过API读取覆盖率数据展示在各种地方,比如展示在README中。
https://app.codecov.io/gh/qqxx6661/log-record/commits
大部分项目都需要有明确的Release Log/Update Log,用来向用户展示仓库的特性更新和问题修复,也能够记录一路以来项目的迭代更新历程。
恰巧最近正在学习reactor,发现其子项目的一个非常标准的Release Log
https://github.com/reactor/BlockHound/releases
在Github上,还有一些包装项目的好办法,Github支持organizations,个人可以注册一个虚拟的组织,用组织的名义建立开源项目,往往更有说服力。
https://github.com/settings/organizations
使用其免费版本即可,对于一个开源项目来说基本够用。
Github的更新还是比较频繁的,及时跟上Github新的功能和特性,也许会对你的项目有更多的帮助。
当你的项目有了一个最基础的雏形时,你可以慢慢开始你的宣传工作。还是那句话,不要觉得宣传有什么可耻的,如果一个项目一直不被人看见,你也会很快失去动力。那么你会更容易半途而废。
对于个人小项目,有一些常规的推广方式:
最后一个章节,我们聊聊,做一个开源项目,我们到底为了什么?出名?纯粹好玩?实现个人价值?体现开源精神?赚钱?还是...老实说,开源真的是个苦力活。
如果你的开源项目已经在稳定维护,并且有一定的用户正在使用,那么恭喜你,项目走上了正轨。但是需要泼冷水的是,大部分就算是有名的开源项目,很多时候是没法给你带来等价的商业回报的,你很可能在很长一段时间里都在用爱发电。
它能给你的主要是成就感和一点小小的知名度,以及这些知名度背后可能带来的一些附加价值(这就很难去描述了)。
如果你真的想要通过它得到一些金钱回报,那在你的项目小有名气后,以下几种方式可能会有效果:
这些事情的背后都要大量的时间和精力去推动,如果你和我一样是一个上班族,那么大概率你没法同时兼顾工作和维护一个持续保持活跃的大型项目。所以很大可能是,你的项目在很长时间内一直是一个小而美的项目。
当你的项目有了流量,被很多开发同学搜索到了,你会获得很多流量附带的东西。
伸手党就是其中一个,具体来说就是有很多网友,会要求你添加很多他们能想到的功能或者他们觉得你项目应该提供的功能。
遇到这种情况,你需要用心判断,他们所要求你添加的功能是否背离你本身项目的初衷,如果是,那么请忽视这些建议。如果是合理的功能,那么请考虑加入,但是可以和用户说明,会在下一个里程碑中加入,不要让用户过于期待你能很快完成。(如果用户真的很希望能立马用到此功能,你可以建议他自己开分支提交PR)。
除了伸手党之外,还会有很多用户在ISSUE区问很多问题,例如我的log-record仓库下这些例子。很多时候,用户对你的项目不熟悉,自然会有一些提问,当遇到重复的提问时,要有耐心,你可以尽量关联到重复问题的老ISSUE上,让他们自己跳过去看。
此外,善用Github提供的各种标签,归类功能,把ISSUE分类,也是间接给用户参与感,让他们知道你正在跟进处理这些问题。
ISSUE虽然比较多并且你很可能觉得有些毫无意义,但是毕竟他们只是用户的提问或者给出建议,我们可以选择是否接受。
但是PR其实是比较尴尬的问题,很多用户的PR很可能是对你的代码进行了很大的改动,有时候这些改动你其实并不愿意接受。但是有的PR,用户花了精力和心思对你的代码进行了大面积的改造(至少在他们心里,这些改造是非常好的)。
这种情况下,大家都会感觉到进退两难,如果接受PR,可能代码有些地方就和你预想的越来越偏,如果不接受,就显得不近人情。这种情况,我也没有想好非常好的对策,目前我的策略,是尝试做一个冷血无情的。如果与这个提PR的用户还有很多交流,那就尽量用你对项目的看法和他进行交流,让他按照你的要求更改,或者是让她自己fork你的项目,自成一派。
像一些大型的项目,它们也有很多PR没有被接受,且长时间搁置在那边,例如SpringBoot
https://github.com/spring-projects/spring-boot/pulls
[1]
log-record: https://github.com/qqxx6661/log-record
[2]
如何写出优雅且有意义的 README: https://juejin.cn/post/6844904057191170055
[3]
spring-boot: https://github.com/spring-projects/spring-boot
[4]
langchain: https://github.com/langchain-ai/langchain
[5]
hutool: https://github.com/dromara/hutool
[6]
transmittable-thread-local: https://github.com/alibaba/transmittable-thread-local
[7]
log-record: https://github.com/qqxx6661/log-record
[8]
uptime-kuma: https://github.com/louislam/uptime-kuma
[9]
ChatGLM-6B: https://github.com/THUDM/ChatGLM-6B
[10]
llama3: https://github.com/meta-llama/llama3
- END -