|
复制粘贴是程序程序员最基础的生产力工具,但粘过来的员代代码能不能跑,是复制另一回事。我在GitHub上见过一个项目,程序README里写着“复制以下代码即可运行”,员代结果下面三十多条issue全是复制“ModuleNotFoundError”。作者把本地路径写进了import语句,程序别人复制过去当然找不到。员代 这事不稀奇。复制Stack Overflow上高赞答案里,程序代码片段经常缺上下文——变量没定义、员代依赖没声明、复制环境假设没交代。程序提问的员代人拿到答案,兴冲冲贴进编辑器,复制红色波浪线立刻铺满屏幕。有个统计说,开发者平均每天花1.5小时在调试从网上复制的代码。我没验证过这个数字,但体感上只多不少。 真正可复制的代码,得满足几个条件,缺一个就容易翻车。 依赖必须显式声明。Python里import requests之前,你得先pip install requests。但很多示例代码默认你环境里已经装好了。我见过一个Flask教程,代码写得干净利落,但没提pip install flask。评论区第一条就是“为什么报No module named flask”。作者回复:“我以为你知道要装。”——这种“我以为”是复制代码最大的敌人。 环境假设要写清楚。Node版本、Python版本、操作系统差异,这些不说明白,代码复制过去就是薛定谔的bug。有个同事从博客复制了一段用pathlib的代码,本地跑得好好的,扔到服务器上就挂——服务器Python 3.5,pathlib的某些方法在3.6才加进去。博客没写版本要求,他也没问,两边都默认对方知道。 还有硬编码。示例代码里写db_password = "123456",复制的人直接拿去连生产库,这种事真发生过。可复制的代码应该把配置项抽出来,用环境变量或配置文件占位。哪怕写个YOUR_API_KEY_HERE,也比写死一个假key强——至少提醒了复制的人这里要改。 错误处理不能省。网上很多代码片段只写happy path,try/except全没有。复制过去一旦网络抖动或文件不存在,直接崩。我自己的习惯是,哪怕写个三行的示例,也加一层try...except,至少打印个有意义的错误信息。别人复制的时候,知道哪里可能出问题。 注释要解释“为什么”,而不是“是什么”。i += 1 # i加1这种注释毫无价值。i += 1 # 跳过表头行才有用。复制代码的人需要知道这行代码的意图,才能判断在自己场景下要不要保留。 说到具体案例,有个开源库叫requests,它的文档是我见过最接近“可复制”标准的。每个示例都有完整的import,都假设你装了库,都告诉你返回对象怎么用。但即便如此,还是有人复制了requests.get('https://api.example.com')然后问“为什么返回403”。——因为那个示例域名是占位符,不是真能访问的。文档里其实写了“替换为你的API地址”,但很多人不看。 所以“可复制”不仅是代码本身的事,还涉及文档怎么写、读者怎么读。写代码的人要把自己当成第一次接触这个项目的人,把所有隐含前提都摆到台面上。读代码的人也得养成习惯:粘之前先看import、看版本要求、看配置项、看错误处理。 我现在的做法是,任何要分享的代码,先在一个干净环境里跑一遍。用Docker起个最小容器,把代码贴进去,看能不能直接运行。不能的话,缺什么补什么。这个习惯帮我省了很多“在我机器上能跑”的尴尬。 代码大全可复制,重点不在“大全”,在“可复制”。一段能直接跑起来的十行代码,比一百行跑不起来的漂亮代码有用得多。 |