来聊聊统计吧 - 面向软件质量的统计入门(No.15 统计质量管理(SQC)实践案例介绍)
Back to Top
为了覆盖更广泛的受众,这篇文章已从日语翻译而来。
您可以在这里找到原始版本。
引言:终于迎来质量分析的集大成
#“为什么缺陷没有减少?” “这个流程真的稳定吗?”
—— 对于这样的疑问,你能用统计来回答吗?
到目前为止,我们围绕软件质量这一主题,从统计视角学习了许多分析方法。
而在“来聊聊统计吧”系列的第15期,作为本系列的集大成,首次登场的是统计质量管理(SQC: Statistical Quality Control)。
SQC是利用统计手法,将过程和成果物的质量“可视化”并持续改进的框架。
不仅在制造业,在软件开发和测试领域,缺陷趋势分析和过程稳定性确认等方面也大有帮助。
“质量不是偶然,而是应当被管理的”——SQC强力支撑了这一理念。
本章将在此前学到的知识基础上,结合具体案例,解说如何将其应用于实际的软件质量管理。
实务中可用的SQC主要指标
#“将质量可视化”具体意味着什么?
那就是拥有能够定量把握现场状况的“指标(度量)”。
不是依赖个人的感觉或经验,而是需要一种基于数据进行判断的工具。
在这里,将介绍在软件质量管理中实际常用的SQC代表性指标。
这些指标都是用来“用数值来描述质量”的有力武器。
指标 | 用途示例 |
---|---|
缺陷密度 | 质量的定量评估(例如每KLOC的缺陷数) |
评审指摘率 | 确认评审的覆盖度和效果 |
缺陷分布(Pareto) | 把握缺陷原因的集中位置 |
假设检定(如t检定) | 用统计方法验证质量改进措施或评审改进的效果 |
回归分析(如单回归) | 分析测试工作量或评审对象规模与成果的关系,定量把握改进或设计的妥当性 |
指标不应只是用于报告的数字,而应成为引发“洞察”和“行动”的线索。
案例1:缺陷密度与交付判定
#● 背景:
#在某个项目(PJ)中,作为判断最终发布可否的质量标准,引入了“缺陷密度(缺陷数/KLOC)”。
该指标不是单纯的缺陷件数,而是考虑了源代码规模的指标,因此在项目间比较或与过往实绩对比时具有优势。
● 应对措施:
#- 收集过去项目的平均缺陷密度及其标准偏差(σ),作为比较基准
- 如果目标项目的缺陷密度达到或超过“平均+3σ”,则视为统计上异常的缺陷发生水平,
- 判定为存在质量风险
- 进行追加评审或重点确认,重新审视发布判定
● 要点:
#- 通过以每KLOC的缺陷数作为归一化指标,可比较大规模与小规模项目。
- 利用3σ法则,可实现客观且可说明的判断。
- 此方法是实现摆脱“交付判定的个人化”,以定量方式运作质量标准文化的第一步。
用数值来描述的质量判定是提升整个项目成员认同感和决策透明度的关键。
● 示例:基于缺陷密度的交付判定逻辑(Python)
#import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Meiryo'
# 过去项目的缺陷密度(缺陷数/KLOC)示例数据
past_defect_densities = np.array([12.5, 15.0, 11.8, 14.3, 13.2, 16.1, 12.9])
# 当前项目的缺陷密度
current_density = 23.7 # ← 修改这里即可检查其他项目
# 计算平均值和标准偏差
mean = np.mean(past_defect_densities)
std_dev = np.std(past_defect_densities, ddof=1) # 按样本而非总体计算
# 阈值 = 平均 + 3σ
threshold = mean + 3 * std_dev
# 判定
print(f"过去平均: {mean:.2f}, 标准偏差: {std_dev:.2f}, 阈值: {threshold:.2f}")
print(f"当前项目的缺陷密度: {current_density:.2f}")
if current_density > threshold:
print("△:存在质量风险:请考虑进行追加评审。")
else:
print("○:质量风险较低,判断合格。")
结果如下。
过去平均: 13.69, 标准偏差: 1.51, 阈值: 18.23
当前项目的缺陷密度: 23.70
△:存在质量风险:请考虑进行追加评审。
● 统计方法解说
#1. 缺陷密度的计算
- 定义:
- 作用:将软件质量按代码规模归一化的指标。可用于项目间比较。
2. 使用基本统计量(平均值·标准偏差)
- 平均(Mean):把握过去实绩值的“集中趋势”。
- 标准偏差(Standard Deviation):评估缺陷密度的离散程度(=质量的稳定性)。
- 使用目的:判断当前项目是否处于“过去的常规范围”内。
3. 3σ法则(基于正态分布的离群点检测)
- 思路:
- 在假设正态分布的情况下,约99.7%的数据会落在“平均 ± 3σ”范围内。
- 超出该范围的数据被判断为“统计上异常”。
- 实务解读:
- 缺陷密度超过平均+3σ → 判定为质量风险较高,并进行追加评审等对策。
4. 离群值检测与决策支持
- 此方法用于基于数学依据定量化风险,并摒弃个人化判断,以客观标准进行质量判定。
● 案例1总结
#在此案例中,通过将“缺陷密度”这一实务指标与描述性统计(平均值·标准偏差)+3σ法则相结合,实现了对过程稳定性的评估和发布判定的支持。
可谓是SQC(统计质量管理)最基础的基本方法。
案例2:评审指摘率的分析
#● 背景:
#尽管进行了代码评审,但在后续阶段仍发现了大量缺陷。
从“明明做过评审,为什么还是有缺陷被遗漏?”的疑问出发,开始了调查。
● 应对措施:
#- 以文件为单位,将“评审发现问题数”与“评审执行数”的比率(即评审指摘率)进行可视化
- 结果发现,在特定领域评审指摘率极低
- 推测该领域“虽然名义上进行了评审,但实际上只是形式化评审”
- 针对相关部分,检讨评审体制(明确评审视角、引入结对评审等)
● 要点:
#- 评审指摘率的优势在于能够可视化形式化的评审,并质疑其实际有效性。
- 通过检测极端的零指摘或倾向性偏差,能够揭示暗藏的质量风险迹象。
● 示例:评审指摘率可视化(Python)
#import matplotlib.pyplot as plt
import numpy as np
# 日语字体(Windows环境)
plt.rcParams['font.family'] = 'Meiryo'
# 各模块的评审执行数和发现问题数
modules = ['ModuleA', 'ModuleB', 'ModuleC', 'ModuleD', 'ModuleE']
review_counts = np.array([10, 12, 9, 15, 13]) # 评审执行数
defect_counts = np.array([4, 0, 5, 1, 6]) # 发现问题数
# 计算指摘率(避免除以0)
with np.errstate(divide='ignore', invalid='ignore'):
review_rates = np.where(review_counts > 0, defect_counts / review_counts, 0)
# 通过柱状图可视化
plt.figure(figsize=(8, 5))
bars = plt.bar(modules, review_rates, color='skyblue')
plt.ylabel('评审指摘率')
plt.ylim(0, 1.0)
plt.title('各模块评审指摘率')
# 在柱状图上方显示数值
for bar, rate in zip(bars, review_rates):
plt.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.02,
f'{rate:.2f}', ha='center')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
结果如下。
ModuleB
在12次评审中指摘0件 → 可能只是形式化评审ModuleD
指摘率也低(1/15)→ 可能是评审视点不足或评审人员熟练度影响
通过这样的可视化,可以定量提取存在问题的评审领域,并将其用于精准的流程改进。
● 统计方法解说
#-
比率指标(评审指摘率)
- 指摘率 = 发现问题数 ÷ 评审执行数
- 用于衡量评审“质量”的典型流程度量
-
视觉化异常值检测(EDA的一部分)
- 通过柱状图可视化极端的零值或离散情况,发现形式化/僵化评审的迹象
-
引入实务性的定量改进循环
- 以“为什么指摘数少?”为起点,改进评审的目标、方法与视角
● 案例2总结
#此案例通过使用**“比率”而非指摘数来可视化评审质量,是一个通过数据凸显“形式化评审”这一难以察觉问题的事例。
虽然不是高级统计分析,但却是与实务直接相关的SQC基础方法**。
案例3:缺陷分布(Pareto分析)下的重点管理
#● 背景:
#缺陷频发,但优先从何处着手的优先级不明确。
由于资源不足,无法“面面俱到”,导致改进效果不佳。
● 应对措施:
#- 按缺陷原因类别和模块分类汇总缺陷件数
- 绘制帕累托图,确认前20%的原因占整体近80%
- 对主要原因优先开展改进活动(培训、重点评审、设计改进)
● 要点:
#- 在“无法事事兼顾”的现场,可视化有限资源应投放于何处的方法。
- 基于数值进行改进“重点化”,因此现场的说服力和认同感更强。
- 改进成果易于显现,是可视化“SQC成果”的典型方法。
● 示例:按缺陷类别绘制帕累托图(Python)
#import matplotlib.pyplot as plt
import numpy as np
# 日语字体设置(面向Windows环境)
plt.rcParams['font.family'] = 'Meiryo'
# 缺陷类别及其件数(示例)
categories = ['规格遗漏', '设计错误', '编码错误', '评审不足', '测试遗漏']
counts = np.array([35, 25, 20, 10, 5])
# 按件数降序排序
sorted_idx = np.argsort(counts)[::-1]
sorted_categories = np.array(categories)[sorted_idx]
sorted_counts = counts[sorted_idx]
# 计算累积比率
cumulative = np.cumsum(sorted_counts)
cumulative_percent = cumulative / cumulative[-1] * 100
# 绘制图表
fig, ax1 = plt.subplots()
ax1.bar(sorted_categories, sorted_counts, color='skyblue', label='缺陷件数')
ax1.set_ylabel('缺陷件数')
ax1.set_ylim(0, max(sorted_counts)*1.2)
ax2 = ax1.twinx()
ax2.plot(sorted_categories, cumulative_percent, color='red', marker='o', label='累积比率(%)')
ax2.set_ylabel('累积比率(%)')
ax2.set_ylim(0, 110)
plt.title('按缺陷类别分类的帕累托图')
fig.tight_layout()
plt.grid(True, axis='y', linestyle='--', alpha=0.6)
plt.show()
结果如下。
● 统计方法解说
#1. 帕累托分析(Pareto Analysis)
- 基于80:20法则,可视化“少数原因产生大多数结果”的现象
- 将柱状图(个别值)与折线图(累计比率)结合
2. 项目优先级设定
- 不仅按照件数多少排序,也可考虑“影响度”“频率”等因素
- 改进的“重点化”可拥有数值依据
3. SQC中的改进决策支持
- 帕累托图作为用于解释改进活动的说服力和优先级的可视化工具极为有效
● 案例3总结
#此案例是以数据展示“应将资源集中于何处”的SQC典型应用例子。
有助于在有限的时间、人力和成本内取得最大效果的“重点管理”。
案例4:评审改进措施的效果验证
#● 背景:
#实施了强化评审视角的改进措施(引入检查清单、明确评审视角等),但需验证“评审质量(指摘件数)是否实际提高”。
● 应对措施:
#- 通过t检定检验平均值差异
- 收集评审改进措施“实施前”和“实施后”的评审指摘件数数据
- 使用**t检定(无配对的两样本检验)**评估两组平均指摘数是否存在差异
- 若差异具有统计显著性,则判定“措施有效”
● 要点:
#- 可以用数据而非感觉来判断措施是否有效。
- 检验是为质量改进决策提供统计依据的最直接手段。
- 包含了零假设与备择假设、p值、显著性水平等统计核心概念。
● 示例:评审改进措施前后效果验证(Python)
#import numpy as np
from scipy import stats
# 日语字体(Windows环境)
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Meiryo'
# 改进前的评审指摘件数(示例:每次评审的指摘数)
before = np.array([2, 3, 1, 2, 3, 2, 1])
# 改进后的评审指摘件数
after = np.array([4, 5, 3, 4, 5, 6, 4])
# t检定(不假定等方差的Welch t检定)
t_stat, p_value = stats.ttest_ind(after, before, equal_var=False)
print(f"t値: {t_stat:.2f}")
print(f"p値: {p_value:.4f}")
# 结果判定
alpha = 0.05
if p_value < alpha:
print("○ 存在显著差异:判定该措施在统计上有效。")
else:
print("△ 无显著差异:该措施的效果在统计上无法确认。")
结果如下。
t值: 5.05
p值: 0.0003
〇 有显著差异:判定该措施在统计上有效。
● 统计方法解说
#1. 假设检验(t检定)
- 零假设 : “改进前后指摘件数的平均值无差异”
- 备择假设 : “平均值存在差异”
- 计算t值和p值,并在**5%显著性水平(p < 0.05)**下判断是否存在差异
2. Welch t检定
- 假定母体方差可能不同,使用不假定等方差的t检定
- 在实务中样本量往往较小,Welch方法更为通用
3. 决策支持
- 检验结果成为数值化说明改进活动有效性的依据
- 与SQC中“检测质量变化”直接相关
● 案例4总结
#此案例是一个以统计依据回答“措施是否有意义?”这一问题的事例。
检验作为支撑SQC“判定时刻”的技术,是一个恰到好处的收尾方法。
案例5:评审规模与发现问题数的关系分析
#● 背景:
#假设评审涉及的行数越多,发现的问题数也会越多,验证这一假设。
目的是确认评审负荷是否与成果相匹配,并将其用于优化评审设计和视角。
● 应对措施:
#- 从过往评审记录中收集“评审行数(SLOC)”和“指摘件数”数据
- 通过单回归分析,对评审规模与指摘件数的关系进行建模
- 确认相关强度与回归方程的斜率,探讨合适的评审粒度
● 要点:
#- 验证“查看越多,发现越多吗?”这一评审质量与数量的平衡
- 通过回归系数,定量获得评审效果的“期望值”
- 若发现的问题数少于预期,也可怀疑评审视角遗漏或形式化的迹象
● 示例:评审规模与指摘件数的回归分析(Python)
#import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
plt.rcParams['font.family'] = 'Meiryo'
# 评审目标行数(SLOC)与指摘件数的数据
x = np.array([100, 200, 300, 400, 500]).reshape(-1, 1)
y = np.array([2, 4, 6, 7, 8])
# 回归分析
model = LinearRegression()
model.fit(x, y)
# 回归系数与截距
a = model.coef_[0]
b = model.intercept_
print(f"回归方程:指摘件数 = {a:.2f} × 行数 + {b:.2f}")
# 可视化
x_pred = np.linspace(50, 600, 100).reshape(-1, 1)
y_pred = model.predict(x_pred)
plt.scatter(x, y, color='blue', label='实测数据')
plt.plot(x_pred, y_pred, color='red', label='回归直线')
plt.xlabel('评审对象行数(SLOC)')
plt.ylabel('指摘件数')
plt.title('评审规模与指摘件数的关系')
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
结果如下。
● 统计方法解说
#1. 单回归分析
- 自变量:评审目标行数(SLOC)
- 因变量:指摘件数
- 回归直线:估计 并用于预测和比较
2. 回归系数的含义
- 系数较大时,表示“行数增加时指摘数也增加” = 指摘密度保持稳定
- 系数较小时,即使行数增加,指摘数也不增加 → 可怀疑评审已形式化
3. 模型评估与残差
- 通过 和残差图,确认模型拟合度,并评估解释力及模式偏差
以下是模型评估和残差分析(Pythonによる可视化):
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
plt.rcParams['font.family'] = 'Meiryo'
# 数据
x = np.array([100, 200, 300, 400, 500]).reshape(-1, 1)
y = np.array([2, 4, 6, 7, 8])
# 模型训练
model = LinearRegression()
model.fit(x, y)
# 预测与决定系数
y_pred = model.predict(x)
r2 = r2_score(y, y_pred)
print(f"决定系数 R^2 = {r2:.3f}")
# 计算残差
residuals = y - y_pred
# 绘制残差图
plt.figure(figsize=(6, 4))
plt.scatter(y_pred, residuals, color='purple')
plt.axhline(0, color='red', linestyle='--')
plt.xlabel('预测值(指摘件数)')
plt.ylabel('残差(实测值 - 预测值)')
plt.title('残差图(评审行数与指摘件数)')
plt.grid(True)
plt.tight_layout()
plt.show()
回归模型的 决定系数 已算出,并绘制了残差图。
由决定系数 可知,评审行数能很好地解释指摘件数之间的关系。
残差呈随机分布,可判断线性回归模型的合理性也很高。
该结果可作为预测评审规模与成果关系的实务可靠依据。
● 案例5总结
#在此案例中,通过回归分析可视化评审规模与成果(指摘数)之间的关系,获得了用于评审活动优化及评审体制验证的依据。
这是深入探讨质量活动“数量”与“成果”关系的极具实务性的做法。
SQC导入要点(统计不必过于复杂)
#-
SQC的本质不应仅仅停留在数值报告,而是发现“变化”与“偏离”,从而引发洞察。
即使不使用复杂的公式或模型,仅通过简单的柱状图、帕累托图、指标的时序趋势等可视化,也能产生足够的实用效果。 -
在本系列实际案例中,许多案例也是由“比率”“密度”“差异检定”等基本描述性统计+简单手法构成。
无需使用复杂理论,关键在于能够“发现”“判断”“说明”。 -
另外,不要期望个人单兵完成SQC也是一大要点。
将其纳入团队内定期共享·可视化·评审的机制,可更容易地培养持续质量改进的文化。
与“统计知识”相比,SQC更注重的是“观察、思考与对话的态度”。
本系列结束之际
#感谢您在这15期内阅读“来聊聊统计吧”系列文章。
本系列以**“统计在软件质量现场如何发挥作用”为主题,从基本统计方法到实践案例进行了介绍。
若能让您不仅停留于理论解说,还学会将质量“可视化”,并与改进相结合的思路与技术**,实属幸甚。
统计是一种用于“观察·洞察·对话”的工具,而非晦涩难懂的公式。
此次系列暂告一段落,今后仍计划根据需要以番外篇形式发布在实务或教学中有用的统计与质量管理话题。
请务必在您各自的现场,推广用统计来讨论质量的文化。
希望能为您在数据分析中提供帮助。