⌨️ 第五章 从设计到测试
📄 本篇摘要

代码的第一读者不是计算机,是半年后的你自己。本篇讲可读性三基石:注释(说为什么,不说是什么)、缩进(用空白把结构画出来——Python 里甚至直接是语法)、嵌套(层数越深脑子越炸,能扁则扁)。

📝 关系

上一节:字符串查找与 BM 算法 | 下一节:命名规则与编码规范 本章主题:怎么写、怎么测、怎么管——从设计到测试的开发方法,后半章进入面向对象。

一、代码是写给人看的

计算机不挑食——写成什么样它都能跑。可读性是为了人:读代码的时间通常远多于写代码的时间(接手别人的、三个月后回看自己的)。所以「能跑就行」远远不够,可读性是一种成本:现在多花一分钟整理,未来省下十分钟猜谜。

二、注释:说为什么,不说是什么

# 坏注释:翻译代码(代码本身就说明了是什么)
i += 1  # i 加 1

# 好注释:解释代码说不出来的部分
retry -= 1  # 最多重试 3 次:支付接口偶发超时,超过 3 次大概率是网络故障而非抖动

三条纪律:

  1. 说 why 不说 what——「做了什么」代码自己会说话;「为什么这么做」只有注释能说。
  2. 注释会过期——改了代码不改注释,比没注释更害人。注释跟着代码一起维护。
  3. 名字够好就不需要注释——retry_count 不用注释,rc 必须注释。先取好名,注释是最后手段。

教材还提醒:文档字符串(docstring,如 Python 的 """...""")是写给【使用者】的说明书,普通注释是写给【维护者】的便签——两者用途不同。

三、缩进:用空白画结构

缩进展示层级:哪段属于哪个 if、哪个循环。Python 更进一步——缩进直接就是语法(4.6 节树莓派课讲过:挪一格就改逻辑)。

# 缩进即结构:一眼看出两层
for student in students:
    if student.score >= 60:
        print(student.name, "及格")

两条纪律:

四、嵌套:层数是复杂度的直接度量

# 嵌套三层:读的时候要在脑子里压一层栈
for order in orders:
    if order.paid:
        for item in order.items:
            if item.stock > 0:
                ship(item)

# 护卫句(早返回)拍平一层
for order in orders:
    if not order.paid:
        continue
    for item in order.items:
        if item.stock > 0:
            ship(item)

经验法则:嵌套不超过三层。再深就动手术——提前返回(continue/return)、抽函数、翻转条件。嵌套深度是第 5-8 节【软件指标】里圈复杂度的近亲:层数越深,测试路径越爆炸。

五、动手 Demo:亲手感受嵌套税

# 找出所有及格学生的姓名,要求:已选课 且 有成绩
students = [
    {"name": "波仔", "enrolled": True,  "score": 88},
    {"name": "小明", "enrolled": False, "score": 95},
    {"name": "小红", "enrolled": True,  "score": 40},
]

# 版本一:三层嵌套
def pass_names_v1(data):
    result = []
    for s in data:
        if s["enrolled"]:
            if s["score"] is not None:
                if s["score"] >= 60:
                    result.append(s["name"])
    return result

# 版本二:护卫句拍平(行为完全相同)
def pass_names_v2(data):
    result = []
    for s in data:
        if not s["enrolled"]:
            continue
        if s["score"] is None:
            continue
        if s["score"] < 60:
            continue
        result.append(s["name"])
    return result

print(pass_names_v1(students))
print(pass_names_v2(students))
print(pass_names_v1(students) == pass_names_v2(students))

沙箱实跑输出:

['波仔']
['波仔']
True

看到什么算成功:两版输出一致、第三行 True 证明行为没变。

读结果:版本二每行只处理一个条件、失败就早早离开——行数多了两行,但每一行的脑力成本减半。可读性优化的典型账目。

六、30 秒实验

打开浏览器控制台或任意 Python:把 5-1 Demo 里的 s["score"] >= 60 改成 s["score"] > 60——波仔(88)还在,想想 60 分整的同学去哪了?边界差异就是这样藏进一行的(5-6 边值分析正要治它)。

七、常见误区

误区 真相
注释越多越专业 好名字+好结构才是主力;翻译式注释是噪音
缩进只是美观 Python 里缩进是语法,错了直接报错或改逻辑
嵌套深=逻辑严密 层数越深测试路径越指数级变多(5-8 圈复杂度)
自测三问(点击展开) 1. **好注释和坏注释的分界线是什么?** 答:说【为什么】的是好注释,翻译【是什么】的是坏注释——后者代码自己就能说。 2. **Python 的缩进和 C++ 的缩进有什么本质区别?** 答:C++ 缩进只是给人类看的,靠大括号定结构;Python 缩进本身就是语法,挪一格就改逻辑。 3. **嵌套太深的第一手术方案是什么?** 答:翻转条件+提前返回(护卫句),把异常路径逐层拍平。

相关笔记