为什么学计算机的学生应该向开源项目做贡献?
编程是所有计算机科学、信息学、软件工程和计算机工程专业的必修课。几十年来,这项技能成为了区分计算机专业的毕业生与其他学科的同龄人的关键。我认为21世纪,编程的熟练程度本身既不能代表市场对计算机毕业生的技术水平要求,也不能成为有分量的资格证书。因此,我建议应该鼓励计算机专业的学生通过课程活动为开源软件项目贡献代码。
我在软件工程课程中实践这种方法已经有15年了,向开源项目贡献代码是必做的作业。本文中将根据个人的经验,说明为什么向开源项目贡献代码能够体现出学生对编程技巧的掌握情况,学生可以从这些活动中学到什么,如何将向开源项目贡献代码嵌入到课程中,以及如何帮助学生完成这份作业。
向开源项目贡献代码是编程的新概念
如今,编程只是软件开发人员必须掌握技能之一。出现这种情况的原因有两个:
首先,编程实践的发展远远超出了Fred Brooks于20世纪70年代推广的首席程序员模型,系统的规模扩大了几个数量级、工具更加先进、流程的自动化也得到了普及,还有团队合作、工作流程以及管理的日益复杂化。
其次,行业最佳实践与大型成功的开源软件项目所遵循的实践已经趋同。各个企业都吸收并贡献了许多开源开发实践。因此,相应的知识和技术力在志愿者项目与企业项目之间是通用的。
因此,我们的教学必须从课程的教育实验室走向实际的组织环境。学生可以通过为开源项目做贡献,在实践中获得了广泛的技能、知识和经验,使他们成长为全面发展的现代开发人员,而不是好莱坞影片中的独狼程序员。传统的编程作业最难获得的技能是以下社交与组织能力:
熟悉背景:了解项目范围、使命、合作开发团队以及新的领导形式下实际的开发工作状况;
与项目的全球及多元化社区互动;
协商功能的请求、要求以及实现方法;
处理沟通问题,例如无人响应,这在志愿者运营的项目中很常见;
通过问题分类和发布计划等实践,认识作为产品的软件;
接收、讨论和处理代码审查意见。
与技术相关的学习成果包括分析、评估、应用和创建等,具体内容如下:
浏览项目的资产,例如软件代码、议题、文档和拉取请求;
快速评估软件系统或组件的产品和流程质量,这在现代软件的重用中经常需要;
配置、构建、运行和调试第三方代码;
设置和运行包含不同软件和硬件要求的软件密集型系统。我开设的课程中包含手机、汽车电子、应用服务器、数据库、容器、物联网设备和嵌入式设备;
选择实际的贡献目标。(学生往往会在初期阶段高估他们为项目做贡献的能力。)这是敏捷开发冲刺中的一项关键活动;
阅读第三方代码,找出需要添加的功能或修复的问题;
通过添加新功能或修复错误来修改大型第三方系统;
编写测试来证明自己贡献的代码无论在当下还是将来都能够按预期工作;
学习使用多种编程语言和工具开发的软件系统。学生经常惊讶地发现,掌握集成开发环境 (IDE) 的知识远远不足以为项目做贡献;
记录自己的工作,一般都会使用声明式标记语言,例如 Markdown 或文档生成器代码注释;
遵循复杂的配置管理(版本控制)工作流程,例如处理问题分支和重新提交代码;
通过预提交和持续集成的检查和测试。
从这些实践中获得的社交经验和技术经验都是现代办公环境所必须的,这些超出了ACM/IEEE 提出的软件工程课程大纲。同时,课程的实践也与ACM/IEEE课程大纲中的许多内容息息相关。这主要包括:锻炼个人技能,例如批判性判断、有效沟通和认识到自己的局限;培养自主学习的技能;了解解决软件工程问题的多个维度;使用适当的最新工具;建立现实世界的基础;并通过各种教学和学习方法推进教育。
在软件工程课程中嵌入开源开发
这门把“向开源软件做贡献”作为必做作业的课程名为“实践中的软件工程”,是大三课程的一部分。(该课程在 2019 年获得了管理学院的卓越教学奖。)每年我们都会向20~50名雅典经济与商业大学管理科学与技术系软件和数据分析技术专业的学生教授这门课程。这门课程也是该大学信息学系的推荐选修课。
该课程在某种程度上颠覆了传统的课堂教学方法,最后的成绩完全由课程作业决定。向开源软件的贡献度占总分的50%。学生可以单独或结对完成作业。结对的目的是帮助没有安全感的学生,但要求结对完成的工作量必须多于个人,而且贡献必须来自个人的GitHub账号。
我们根据学生提供的在线开源项目工作(代码提交和交互)、他们的最终书面报告以及课堂演示来评估学生的表现。一共需要三场演讲,分别在第 4 周(描述所选项目)、第 8 周(概述提议的贡献)和第 14 周(总结贡献的实现)。贡献的代码是否被接受并不会作为作业的评判标准,但会得到积极的评估。其他评估要素包括,学生对自己选择的项目的理解和文档、贡献的广度、实现的质量、代码与项目的集成、测试实施、与项目开发团队的合作、口头陈述、书面报告的质量,以及他们在版本控制、代码审查、议题管理和文档等活动中使用的工具。
理论上,他们可以作弊(通过复制项目分支的贡献等),这可能会成为一个问题,但我们要求学生在课堂上展示他们的成果,而且我们会让学生们明白,他们贡献的代码会成为个人的一项战绩,而且将来还会被潜在雇主的询问,这些措施可以杜绝作弊。
成功地向开源项目做贡献
刚开始接触这门课程的时候,学生们都怀着惶恐的心情,但在完成后都会非常高兴。为了确保学生能够为开源项目做出有意义的贡献,我们需要考虑到他们的经验不足与现代开源软件开发的快节奏与复杂性。
这些年来,通过我分配的作业可以看出,为开源项目做贡献的难度越来越低。各个项目变得更具包容性。许多项目简化了新手入门指导,团队更加多样化(包括女性领导),公开联系方式很常见,回复通常都很有礼貌,而且支持Windows 构建(尽管一些学生采用 Linux 以避免出现故障)。由于拉取请求工作流程中的手动控制、持续集成的广泛采用、多样化的代码检查机器人、友好的代码审查流程以及拉取请求草案的使用,做贡献的难度已降低。
尽管如此,学生们接触的开源项目环境与传统学术作业环境的体验仍然相去甚远。因此,小规模的贡献才是比较现实的目标。为了让这门课程的作业发挥作用,关键在于降低对学生所做贡献度的期望。对于一个本科生来说,为开源做贡献的门槛非常高,即便是向一个大型项目贡献20行代码也是值得庆贺的成就。我们给学生选择项目的建议可以总结如下:
选择一个有多位活跃贡献者的项目,这样就有一个社区来指导并回答你的问题。
选择一个相对流行的项目(获得了一些GitHub给星),证明这个项目提供了有用的功能,并且以相对合理的方式开发。你应该避免上传到GitHub已久的废弃论文项目。
避免过于受欢迎的项目,因为你的贡献会被其他竞争者、噪音和官僚主义淹没。(尽管如此,我们的一些学生还是参与了轰动一时的项目,例如 Tensorflow 和 Visual Studio Code。)
确认可以在自己的计算机上构建和运行项目。
确保项目定期接受来自外部的拉取请求,保证自己也有机会。
尝试提供一个简单的bug修复,作为热身练习,测试一下自己是否有能力严格遵守项目的工作流程。
查找带有“Good first issue”标记的议题,这表明该项目对新贡献者很友好。
至于选择贡献怎样的代码,则完全由学生自己决定。他们可以从项目的议题列表中选择一个开放的任务,或者提出自己的增强或修复意见。学生在与项目的核心团队互动后也会经常改变策略。尽管让他们自由选择自己的贡献似乎让这个作业变得很容易,但我发现大约一半学生贡献的代码都被采纳了。
学生在作业中面临的最常见问题包括无法构建项目(通常是由于缺乏经验和平台不兼容),以及项目团队缺乏沟通(学生会过分焦虑,认为他们贡献的代码必须被采纳)。另一方面,学生们最大的快乐在于,发现自己的代码被某个全世界都在使用的生产软件所采纳。在课程评估中,学生都很开心,他们表示自己在向开源软件做贡献的过程中获得了许多实践技能,同时也更自信了。