"程序怎么运行不了,不应该啊?"
"程序怎么能运行了,不应该啊!"
这句话是不是让程序员朋友们的 DNA 动了呢?今天鱼皮分享一些新手程序员常犯的小 Bug,很多是我自己或者网友们的亲身经历,相信绝大多数程序员都写过这些 Bug~
程序员经典小 Bug
1、标点符号错误
刚学编程语言的很多同学应该都被这个错误折磨过,比如在代码中使用中文逗号(,
)或引号(""
),结果就导致了编译错误。
// 使用了中文逗号,编译会报错
Map<String, Integer> map = new HashMap<>();
map.put("key1", 1);
我之前就遇到过一位同学,把类似上面的代码拍了个照,然后问我哪里有错,我当时快把眼珠子瞪出来了,也没发现问题:
结果后面他自己发现问题了,我知道真相后直接红温了。
其实这类 Bug 很好自己解决,开发工具都会给出提示的,只不过由于新手不知道要去看错误信息罢了。
2、更新数据没指定范围
现在的数据库操作框架封装得太好了,以至于很多同学都不怎么自己写 SQL,查询语句可能还写过一点儿,但更新语句基本上没写过。这就导致了很多低级问题,比如在更新或删除数据时,忘记加上 WHERE 条件。像之前我分享过,我们团队一位同学更新某个用户权限的时候,不小心把所有用户的权限都刷成了 "管理员"。
UPDATE orders SET role = 'admin';
一般有经验的开发者看到数据更新或删除操作,就条件反射想到要加 WHERE 条件:
UPDATE orders SET role = 'admin'
WHERE id = xxx
企业中通常也会给数据库加上限制,防止范围更新和删除。
3、资源忘记释放
在开发中,文件、数据库连接、内存、网络连接都属于资源,如果打开了资源没有释放,就有可能因为资源泄露导致程序崩溃,很多线上 Bug 都是这么来的。
比如打开一个文件,却没有关闭:
public void readFile(String path) throws IOException {
FileReader reader = new FileReader(path);
char[] buffer = new char[1024];
reader.read(buffer);
// 忘记关闭文件
}
平时要养成好的习惯,只要打开了资源,都要看看有没有 close 方法。如果有的话,再确认该资源会不会自动关闭;如果不会自动关闭,就要手动释放资源。
在 Java 中,可以在 finally 块中、或者使用 try-with-resources
语法自动释放资源:
public void readFile(String path) throws IOException {
try (FileReader reader = new FileReader(path)) {
char[] buffer = new char[1024];
reader.read(buffer);
}
}
4、明文存储隐私数据
这也是一类低级错误,比如在数据库中明文存储用户的密码:
INSERT INTO users (username, password)
VALUES ('admin', '123456');
好好好,这下管理员爽翻了!
标准做法是,使用哈希算法 + 盐值加密存储密码:
String hashedPassword = BCrypt.hashpw("123456", BCrypt.gensalt());
虽然这个错误很低级,但可千万别小看它。某公司因为明文存储密码被处罚了 9100 万欧元!
类似的错误还有直接从前端明文发送密码给后端,虽然可以通过 HTTPS 协议增强安全性,但 HTTPS 只保证传输加密,服务端和客户端仍能看到密码明文,攻击者可能通过日志窃取密码。
5、前端存储秘钥
这也是一类低级错误,经常出现于调用第三方 API 的时候。
比如需要调用一个第三方天气服务 API,为了省事,前端直接将秘钥写到了 JS 代码中:
// 第三方 API 秘钥
const API_KEY = "yupi123456";
// 调用 API
async function getWeather(city) {
const url = `https://codefather.cn/weather?city=${city}&apikey=${API_KEY}`;
const response = await fetch(url);
const data = await response.json();
console.log(data);
}
这样一来,用户直接打开 F12 控制台,就能看到你的秘钥了,即使对 JS 代码加密混淆,也能轻而易举被找到。
所有前端的内容都是不安全的。 如果有调用第三方 API 的需求,最好还是通过后端进行转发。
6、忘记区分环境
刚在企业中接触多环境的同学,可能会不小心把测试环境的代码或配置部署到生产环境。
比如 Java 项目使用 application.yml
文件来管理配置,测试代码时,我先把数据库改为测试库:
spring:
datasource:
url: jdbc:mysql://localhost:3306/dev_db
结果上线前,忘了把配置改回来,导致线上环境找不到这个数据库或者因为网络隔离无法连接。
标准的做法是,通过配置文件后缀区分多环境,在启动项目时指定对应的环境值即可。比如 application-dev.yml
表示开发环境、application-prod.yml
表示生产环境。
7、强行合并或推送代码
我见过一些急性子的同学,在提交或推送代码的时候遇到了代码冲突,觉得麻烦就强行合并或推送了。
# 忽略代码冲突,强行合并
git merge branch-feature --strategy-option=theirs
# 强行推送,覆盖远程代码
git push --force
此举可谓图一时之快,但后患无穷矣。
很快你的同事就会找上门:我的码呢?
你的领导也会找上门:没通过审核的代码怎么就推到主分支了?
所以遇到代码冲突之后,一定要仔细处理冲突,不要强行合并或推送,除非你能接受这么做的最坏结果。
对于管理者,最好在代码管理平台中开启保护分支,禁止成员把未审核通过的代码直接推送到主分支。
8、提交敏感信息
很多朋友的数据保护意识是比较差的,尤其是刚接触 Git 代码提交的同学,可能一不小心,就把包含了数据库账号密码的配置文件提交到 GitHub 等开源平台了,开源精神令人感动。
不信的话,你可以在 GitHub 搜索和秘钥有关的关键词,一抓一大把。
我自己也经历过这事,曾经提供了一个免费的图床给编程导航的同学使用,结果有不止一个人把我的图床秘钥开源到了 GitHub 上。
好在有些大厂的云服务会自动检测你有没有将秘钥提交到开源平台,如果出现了,会给你发送邮件。
解决这个问题的方法也很简单,我们可以准备两套配置文件,一套开源,一套自用,在 Git 中忽略掉自用配置文件的提交即可。
OK 就分享到这里,大家还见过哪些常见的、或者 "有点儿东西" 的 Bug 呢?欢迎评论区分享~