本文转载自公众号“读芯术”(ID:AI_Discovery)
如今,擅长编写代码与精通英语一样重要。想要变成优秀的程序员需要长期的磨炼,最好方法是加入一家有高编码标准的公司。而笔者想要给你的,是如何通过简单调整开发过程,以使代码看起来更好。
本文汇集了笔者长期查看可补充学术论文的代码,发布数据集或分析Kaggle竞赛的解决方案总结而成的经验。
本文的目标读者是研究人员、数据科学家和初级软件开发人员。每个步骤只需不到5分钟,而且这些调整会迫使您做得更好。
使用版本控制来跟踪代码中更改的地方
版本化代码看起来很明显是必须做的事情,但事实并非如此。笔者的硕导是一个非常聪明的人,他开发了一种算法来执行Hubbard模型的Quantum Monte Carlo。该代码被全世界许多研究人员使用,以推进理论的“凝聚态物理”。
当开始使用这种算法时,笔者惊讶地发现没有集中式的存储库。代码的交换是通过电子邮件进行的。一位科学家开发的漏洞修正和新功能并未交换给其他用户。此外,我也看到同事如何使用不同的文件夹控制代码版本。
在GitHub或其他服务上进行代码版本控制和使用集中式存储库很有必要,许多研究人员正在这样做。但是如果不使用计算机科学,那么大多数教授和研究生正处于使用文件夹进行版本控制和通过电子邮件发送代码的阶段。
问题:什么时候需要开始在项目中使用git?
回答:从代码的第一行开始使用。
问题:何时需要在GitHub上创建存储库并将代码推送到库里?
回答:从代码的第一行开始。如果认为由于法律或其他原因不能公开共享自己的代码,那可以创建一个私人存储库。在其他所有情况下,请访问公共存储库。
等到代码看起来不错再公开,这是一个错误。如果GitHub存储库中有不完美的代码,我的许多同事都会感到非常不安全。他们担心别人会认为自己是差劲的程序员。实际上,根本没有人会去评判你。此外,现在编写的每个代码在六个月后看起来都会很糟糕。
私人存储库总比没有存储库要好。公共存储库又比私有存储库更便利。
Kaggle竞赛的参赛者在比赛结束后发布自己的pipeline是一个好习惯,对参赛者和社区都有帮助。
此外,还有一个名为Sourcegraph的工具,可以在所有公共Github存储库中的代码中执行搜索。非常方便,能够提高工作效率。
不要推送到主分支
在团队中工作时,不要直接推送到主分支。创建一个单独的分支,并在其中工作,创建一个拉取请求(PR),将拉取请求合并到主分支。这比直接的push to master 错误要复杂得多,原因是要合并拉取请求,更改须通过各种检查。手动检查是协作者进行的代码审查。自动检查包括语法、样式、测试等。
当独自工作时,没有机会代码审查,但是自动检查的功能仍然可以使用。
在GitHub上调整设置非常有必要,即使有意愿,也不会出现push to master。如上所述,这可以防止犯错误并节省意志力。
图源:unsplash
使用持续集成/持续交付(CI / CD)系统
完成创建分支和合并的过程是一项日常开销,主要原因是允许对代码更改执行检查。设置持续集成系统后,创建的每个拉取请求需要进行检查,并且仅在所有检查通过后,才能合并拉取请求。
有许多提供CI /CD功能服务的软件,如GitHub Actions、CircleCi、Travis、Buildkite等
推荐使用GitHubActions。完全免费,可在私有和公共存储库上使用,且易于设置。
这些听起来非常复杂,但是实际上,只需要向存储库添加配置文件即可。
- 简单示例:笔者的库具有辅助功能。笔者检查代码样式、格式并运行测试。
- 复杂示例:在Albumentations库中,检查语法和代码样式,运行测试,检查自动文档构建,并针对不同的python版本和操作系统(Linux,Windows,Mac OS)执行操作。
注意:需要在GitHub存储库中更改设置,这样在所有检查都在绿色区域中的情况下将无法合并请求。
Linters
这些工具不会更改代码,而会对代码进行检查并查找可能存在的问题,这称为linter。最常用的是flake8。
它可以寻找:
- Pep8错误和警告。
- 一致的命名公约。
- 功能的圈复杂度。
- 以及带有一组插件的其他内容。
这是一个功能强大的工具,建议将其添加到CI /CD配置以及预提交钩中。
Pre-commit hook
在上一步中,提到了提交之前在本地运行格式化程序的重要性。
假设使用black 和 isort,需要运行:
- black .isort
这很麻烦,更好的解决方案是使用这些命令(例如“code_formatter.sh”),创建一个bash脚本并运行脚本。
创建脚本这样的方法非常流行,但问题是,除非强行使用,否则人们不会这样做。
有一个更好的解决方案即预提交钩(pre-commit hook)。这个想法类似于bash脚本,但是想要在每次提交之前运行的内容将在执行时运行:
- git commit -m“ <commitmessage>”
这看起来差别很小,但事实并非如此。有了预提交,行为就会被强制执行,如上所述,它的效果会更好。
图源:unsplash
问题:PyCharm执行格式化很不错。为什么需要一个预提交的钩?
答案:因为可能会忘记使用PyCharm格式化代码。此外,当有两个人以上时,要确保他们的格式相同。预先提交钩,所有人将拥有与存储库相同的配置。笔者建议同时使用这两个方法,即预先提交钩并使用PyCharm格式化代码。
问题:如果跳过控制台,直接从PyCharm执行提交会怎么样的?
答案:可以将PyCharm配置为在每次提交时运行预提交钩。
Mypy:静态类型检查器
从Python3开始,可以在代码中的函数添加类型注释。这不是必选项,但强烈推荐。其中一个原因在于,读取带有类型注释的代码非常容易。
当在代码中看到:
- x:pd.DataFrame
这比仅仅输入X能提供更多信息。当然,不应刚开始就将变量命名为“ x”。尽管如此,本文谈论的是简单且自动的方法来改进代码,而好的命名要比简单的输入更难一些。
类型注释是可选可不选的。没有它们,代码也能运行良好。有一个名为Mypy的工具可以进行检查:
- 功能和输入参数的类型注释
- 变量类型与操作之间的一致性
这是一个非常有用的工具。所有大型的科技公司都使用它来检查python代码的每个拉取请求。
这个工具会强制编写易于阅读的代码,重写过于复杂、写得不好的功能,并能识别错误。
Mypy检查可以添加到CI /CD并预提交钩。
代码格式化程序
格式化同一段代码的方法有很多。
- 函数之间要有多少空格?
- 代码中的行要多长?
- 输入的顺序是什么?
- 应该使用哪种引号来定义字符串?
- 等等
有一些称为代码格式化程序的工具。如果要在代码上运行代码格式化程序,这些工具会修改代码以符合格式化程序的要求。
通用的格式化程序类型:
- YAPF:非常灵活,可以进行配置以适合所需的样式。
- Black:不够灵活只可以配置行的长度。
选择其中一个工具并将其添加到CI /CD配置。本人喜欢使用Black。这让笔者所有的项目都看起来和Black的项目一样。
代码格式化程序减少了上下文切换,这让读取代码变得更加容易。
还有更多特定的格式化程序,如isort。Isort只对输入进行排序。
需要在两个地方运行格式化程序:
- 在CI / CD中。以检查模式运行:格式化程序将会告知要格式化的文件,但是代码将保持不变。
- 提交更改之前需要在本地进行,并重新格式化代码。
更多检查以预提交钩
可以使用许多不同的内容扩展预提交钩。
- 删除尾随空格。
- 文件的末尾是新行。
- 文件格式要求txt。
- 检查yaml文件,更正格式
- 等等
可以为代码格式化创建自己的钩子,并检查自动产生的钩子。
外部工具
像Deepsource.io和Deepcode.ai这样的工具,可以用作对拉取请求自动代码审查的附加检查。
这是完全免费的公开存储库,很难找出不为公共代码启用它们的理由。
只要使用了其中的至少一种技巧,代码会更加易于阅读。但这只是第一步,还有其他标准的技巧,比如:单元测试、Hypothesis的单元测试、Python环境、创建安装包、Dockerization、自动文件等等,这些会更难一点。
给自己不得不尝试的理由,让更好地工作成为自然而然的选择。从第一步的改变开始吧!