小姐姐: 你上班一般做些什么?
程序员: 我上班一般写 bug...
虽然程序员自嘲自己是写 bug 的,大家都是希望自己程序无bug 的。
首先来看看 Bug 的由来,
"Bug" 一词最早可以追溯到计算机科学的早期。1947 年,美国计算机科学家格蕾丝·霍普(Grace Hopper)在哈佛大学的 Mark II 计算机中发现了一只飞蛾卡在继电器中,导致计算机无法正常工作。她将这只飞蛾贴在日志本上,并写道:“First actual case of bug being found”(首次发现实际的 Bug)。从此,"Bug" 一词被广泛用于描述计算机系统中的错误。
"Bug" 通常指软件、硬件或系统中的错误、缺陷或故障。它的来源一般有复杂性问题、编程错误、设计缺陷、需求误解、环境问题、时间压力等。
一、技术篇
1.1、软件开发并不简单
软件开发本身就是一个非常复杂的过程。一个软件系统可能包含成千上万行代码,涉及多个模块和功能。
下图是历史上最庞大的代码库代码行数,排在最下面的是 Google:
- Google 全家桶代码行数大概在:20亿左右
- 微软 Windows11 代码行数在:1亿左右
即使是最有经验的程序员,也很难在第一次写代码时就考虑到所有可能的情况。比如,用户可能会输入一些奇怪的数据,或者在某些极端情况下系统会崩溃,这些都需要在开发过程中逐步发现和修复。
假如一个简单的计算器代码,也就是加、减、乘、除的功能,以下的代码感觉已经比较完善了。
def calculator():
print("欢迎使用简单计算器!")
# 获取用户输入
num1 = float(input("请输入第一个数字: "))
num2 = float(input("请输入第二个数字: "))
operation = input("请选择操作 (+, -, *, /): ")
# 执行操作
if operation == '+':
result = num1 + num2
elif operation == '-':
result = num1 - num2
elif operation == '*':
result = num1 * num2
elif operation == '/':
result = num1 / num2
else:
result = "无效的操作"
# 输出结果
print("结果是:", result)
# 调用计算器函数
calculator()
但是如何用户输入
- 用户输入非数字:如果用户输入的不是数字,程序会崩溃。
- 除以零:如果用户选择除法并且第二个数字是零,程序会崩溃。
这时就会产生 bug,就需要修改 bug 了。以下是修改后的 代码:
def calculator():
print("欢迎使用简单计算器!")
try:
# 获取用户输入
num1 = float(input("请输入第一个数字: "))
num2 = float(input("请输入第二个数字: "))
operation = input("请选择操作 (+, -, *, /): ")
# 执行操作
if operation == '+':
result = num1 + num2
elif operation == '-':
result = num1 - num2
elif operation == '*':
result = num1 * num2
elif operation == '/':
if num2 == 0:
result = "错误: 除以零"
else:
result = num1 / num2
else:
result = "无效的操作"
# 输出结果
print("结果是:", result)
except ValueError:
print("错误: 请输入有效的数字")
except Exception as e:
print("发生了一个错误:", e)
# 调用计算器函数
calculator()
即使修复了上述问题,程序仍然可能存在其他潜在的 bug或边界情况。比如输入超长数值、输入负数(当前程序员有考虑到负数)等等。
除了软件本身存在的复杂度来说,还有另外一些因素。
1.2、软件需求不完善或误解
软件需求根据产品人员、业务复杂度相关,随着项目的深入和产品的熟悉,认知加深,会发现需求不完善的问题,此时需求需要完善。这就意味着程序员需要不断地调整代码,以满足这些变化。即使需求没有变,开发者对用户需求的理解有误,导致开发的功能与用户期望不符。
1.3、Bug 发现者
一般来说发现 bug 最多的应该就是测试。虽然测试是发现Bug的重要手段,但测试覆盖率永远不可能达到100%。程序中有无数的分支也就是无数的可能性,开发自己单元测试都可能无法覆盖 100%。再加上用户硬件、系统、网络及数据都会有差异这个覆盖 100%就更难了。随着经验的积累,自动化测试和手动测试只能覆盖一部分场景,很多Bug只有在实际使用中才会暴露出来。所以,即使测试通过了,也不代表代码就没有问题。
1.4、代码质量
代码质量也是一个问题。为了赶进度,程序员可能会写一些“临时性”代码,这些代码可能在短期内有效,但随着项目的扩展,可能会引发新的Bug。这就需要程序员在后续的开发中逐步优化和修复。
另外如在并发的业务中开发人员使用了 Java HashMap 在多线程环境下是非线程安全的,如果多个线程同时修改同一个 HashMap,可能会导致数据不一致 使业务异常。这种 Bug 与开发者的经验与能力都有关联。
1.5、 编程语言Bug
某些编程语言本身的设计可能存在缺陷,导致某些操作的行为不符合预期。所以程序语言也在不断的升级和更新。
二、白话篇
如果你不是程序员,可能不太理解为什么写代码这么麻烦。其实,我们可以用一些生活中的例子来解释。
比如软件开发就像盖房子。即使你设计得再好,房子建成后,你可能会发现某些地方需要调整,比如水管漏水、电线布局不合理,或者房间的采光不够好。软件开发也是一样,即使程序员设计得再完美,总会有一些小问题需要修复。
软件是由成千上万行代码组成的,就像一张巨大的拼图。即使拼图的每一块都正确,拼在一起时也可能出现缝隙。Bug就是这些缝隙,程序员的工作就是找到并修复它们。让它不断更新和改进,随着技术的进步和用户需求的变化,软件也需要不断升级,修复Bug并添加新功能。
我是栈江湖,如果你喜欢此文章,不要忘记点赞+关注!