当前位置: 首页 > article >正文

《A++ 敏捷开发》- 16 评审与结对编程

客户:我们的客户以银行为主,他们很注重质量,所以一直很注重评审。他们对需求评审、代码走查等也很赞同,也能找到缺陷,对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。
我:你听说过敏捷的结对编程吗?
客户:听过,也给客户做过培训,但是一般管理层都接受不了用两个人干一个人的活,所以几乎都没有团队在实际工作中使用。
我:单做培训确实难以推动并持续,必须按3步走,按部就班才有效果,让我分享一下。

背景

4月

现场结对编程培训之前8个月,首次见这家客户的总监。他们想用一年时间改进软件开发质量。事后知道原来他们有个超过12月的大型项目,因为验收时质量不达标,不能通过风险的验收测试,被拒收。因为公司是老字号,不想影响声誉,请求客户给机会让他们重头再做,客户同意但估计产生的损失超过100万,所以高层下定决心必须改进软件质量,避免类似情况再发生。

7月

与客户签了CMMI服务合同后首先做差距分析, 首先收集各领导的关注点。
某部门经理最担心的是系统维护:如果有人员离职,新人要花很长时间才能上手。
技术总监更担心是有些交付后的缺陷会很花工作量:如某系统交付后开始使用的时候很正常,但过了9个月,用户量和数据量都增加了,偶尔会出现有些报表出错,我们架构师、工程师等,花了3个半月才发现其中某接口的参数有问题。
另外发现开发人员水平参差,也没有做好单元测试和代码评审,代码可读性低,其他程序员难以理解,在分析后的汇报里,建议利用TDD和面向对象的设计原则改善编码规范,并加强培训,推行结对编程培训,提高代码的可读性,方便日后维护。
最后发现很多项目资源不足,没有充分的时间确保代码的质量。

给管理层汇报
因缺陷绝大部分都是后期测试才发现、缺陷修改的总工作量很大(估计占项目总工作量30%),建议加强开发单元测试。
因代码都是个别程序员负责,建议团队用结对编程,除了能提高质量也防止一人离开其他人无法跟进的风险。
也预警管理层开始时要预留15-25%时间给开发团队,当后面返工量减少,以后的总工作量会降低(生产率提升)。

2天培训课

第一天讲面向对象设计原理,设计模式,测试驱动开发;
第二天讲结对编程:

Interview Parnas Screenshot 2025-01-21 162541.jpg

问:在软件工程常被忽略的最大风险是什么?

答:不称职的开发人员。据估计,美国需要的程序员数量超过20万。这完全是误导。这不是数量问题。我们有质量问题:一位糟糕的程序员一年内便很容易就会产生两个新岗位(的工作量)。如果我们有更多优秀的程序员,并且能够轻松识别他们,我们需要的就会减少,而不是增多。

“也有人说:“卓越的程序员比优秀的程序员,不仅是好一些,而是倍数级的差异。”
请问你们觉得团队里程序员的水平也存在很大的差异?”
培训开始,对应以上幻灯片,我问大家。

你们是否觉得:

  • 交付后的软件难以维护
  • 其他人难以读懂其他人的代码,员工离职后其他成员难以跟进和维护
  • 代码总体设计不好,如缺乏良好架构,不灵活
  • 系统交付后,有些缺陷需要很长时间才能修复好

如大家希望提高代码质量,必须从人入手。

如果你们团队也有同样问题,有什么好的解决办法呢?培训?
编码的最佳学习方式并非读书,而是动手做,所以单靠搞内部培训效果有限。有什么好方法帮助开发人员提升?

代码评审

就算评审规范做得很好能帮助初级程序员提升吗? 很难,因为代码都已经写完了。
比如我跟另一位老师看团队的代码,他们都写了起码几千行。我们的结论就是:虽然代码的设计很有问题,但已经到了这个地步,除非重写,否则单靠修正部分代码并没有帮助。这也是代码评审常常难以做好的主要原因。而且大家都要面子,如果在评审里,直接说他设计有问题,也可能会影响到大家的关系,所以在设计评审时难以找出缺陷,这很正常。
团队主管看程序员代码 只能把关防止严重错误,对程序员提升没有作用,所以评审不能有效保证代码质量,也不能帮助团队能力提升。
当写完了几千行代码后,就很难在评审时要求开发改动。程序员会觉得又不是不对,测试也跑得通,为什么要改。所以代码的质量问题应在写的时候就避免,这是结对编程的原理。你可以把结对编程看成是提高团队之间互相交流的培训方法。因为结对编程是在编码时针对具体问题集思广益进行解决,很容易落地,效果会比培训或评审好。
两个人互相讨论写代码才就是有效的培训,不能单挑单靠设计和编码规范和指南。

培训设计

有些人误以为:

  • 结对编程必须要找一位合适的搭档,人与人之间是否合得来最重要
  • 结对时只是在旁边看
  • 以为仅仅是教同伴应怎么做
  • 以为只是看,作为人手编译器,只看代码是否写对,能否通过编译

我们针对这些重点设计一天培训。

培训重点

要培训有效,必须利用练习,让学员动手动脑筋。

结对编程和实践说明

练习#1和讨论:代码阅读
结对编程说明

练习#2和讨论:设计和结对编程
练习#3和讨论:Code Review和Pair Programming
练习#4 怎样开始结对编程:10分钟结对编程
讨论:10分钟正确结对编程
练习#5:队伍结对编程
Pair-Solo Programming

练习一:用10条代码实例,每一条分A与B两种方式写,问学员那种更容易读懂,说明代码应怎样写才能让一般人容易读懂
练习二:先自己按面向对象做总体设计 然后两人结对分享设计做出最终设计学员讨论结对是否有效
然后解释若要持久,必须轮流替换伙伴,也介绍各类结对方式的利弊,例如:

Public-private pair programming ; pair - solo programming

练习四:先2人试试结对
练习五:六人为一队,轮流合作写程序,让学生体验交换。(详见附件)

经验分享

结对编程需要2人对话沟通,例如某人写代码时,另外一个人提问题,有些不习惯编写代码边说话沟通,培训时,预先写好台词。如果想多了解结对编程如何沟通,可参考书的实例。
有些程序员比较内向,不想说话,我们会用角色扮演: 先写好台词,让他们展示在结对编程时如何沟通。 帮助他们先打出一步,鼓励尝试。
注:如果想了解结对编程如何沟通,可以参照Robert MARTIN先生的保龄球游戏实例(参考书里第6章),了解两个人如何从需求、总体类设计、按TDD写单元测试用例、然后写代码,让它通过,一步一步最终完成整个程序。

总结

培训开始时用例子说明结对编程除了能帮助团队知识分享和提高团队精神以外,更能:

  • 提高代码质量和可读性(编码规范)
  • 提高代码复用
  • 加强测试驱动开发

利用互动练习让学员亲身体验结对编程的原则:

  1. 一边写代码一边说
  2. 提问,如:这方法是否归为这个类
  3. 每人带纸和笔(最好铅笔)
  4. 不断想复用

--- *** === *** ---

客户:我猜你说的3步是:
第一步,高层认同软件质量问题的严重性,为此交过学费,知道损失多大
第二步,管理层不仅了解软件的质量问题和改善措施,更需要内部立项做培训和投入资源(人力),做过程改进
第三步才是具体的培训课。因为缺乏第一步和第二步,所以之前做完了结对编程培训后,没有效果
我:厉害,完全对。结对编程只是改进的一种方法,如果高层不关注、不立项、不投入资源,不会有改进效果。
结对编程这方法在70年代已经开始,与TDD、代码重构已经都经过验证能有效改善质量减少返工。所以结对编程本身没问题,要解决的问题是总体质量改进。
若要成功推行结对编程,必须先说服管理层,投入时间和资源,但投资会有好回报。
结对只是一种有效的改进方法,团队必须有每个迭代回顾,持续提升的好习惯,不可能单靠管理层下命令来推行,更好是团队自己有改进的动力,选择使用结对编程来提升质量,减少返工。


本章最佳实践对应

  • CMMI
    • 单元测试:PR 2.X 3.X 所有实践
  • XP
    • 结对编程,代码共同拥有 都是XP里的实践

附件

Ex 5

时间组一组二组三
1A 和 B 结对并打开信封XC和D结对并打开信封YE和F结对并打开信封Z
看清楚需求,然后把X掉了看清楚需求,然后把Y掉了看清楚需求,然后把Z掉了
A和B 开始结对编程,A写B看C和D开始结对编程,C写D看E和F开始结对编程,E写F看
2过了4分钟转换
3F和A结对编程X ,F写A看B和C结对编程Y ,B写C看D 和E结对编程Z ,D写E看
4过了4分钟转换
5E和F结对编程X,E写F看A和B结对编程Y,A写B看C和D结对编程Z,C写D看
6过了4分钟转换
7……
……

相关文章:

《A++ 敏捷开发》- 16 评审与结对编程

客户:我们的客户以银行为主,他们很注重质量,所以一直很注重评审。他们对需求评审、代码走查等也很赞同,也能找到缺陷,对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。 我:你听说过敏捷的结对…...

NutUI内网离线部署

文章目录 官网拉取源代码到本地仓库修改源代码打包构建nginx反向代理部署访问内网离线地址 在网上找了一圈没有写NutUI内网离线部署的文档,花了1天时间研究下,终于解决了。 对于有在内网离线使用的小伙伴就可以参考使用了 如果还是不会联系UP主:QQ:10927…...

【实战篇】【深度介绍 DeepSeek R1 本地/私有化部署大模型常见问题及解决方案】

引言 大家好!今天我们来聊聊 DeepSeek R1 的本地/私有化部署大模型。如果你正在考虑或者已经开始了这个项目,那么这篇文章就是为你准备的。我们会详细探讨常见问题及其解决方案,帮助你更好地理解和解决在部署过程中可能遇到的挑战。准备好了…...

数据结构--双向链表,双向循环链表

双向链表的头插&#xff0c;尾插&#xff0c;头删&#xff0c;尾删 头文件&#xff1a;&#xff08;head.h&#xff09; #include <string.h> #include <stdlib.h> typedef…...

Qt学习(六) 软件启动界面 ,注册表使用 ,QT绘图, 视图和窗口绘图,Graphics View绘图框架:简易CAD

一 软件启动界面 注册表使用 知识点1&#xff1a;这样创建的界面是不可以拖动的&#xff0c;需要手动创建函数来进行拖动&#xff0c;以下的3个函数是从父类继承过来的函数 virtual void mousePressEvent(QMouseEvent *event);virtual void mouseReleaseEvent(QMouseEvent *eve…...

java练习(36)

ps:题目来自力扣 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s 的&#xff0c;而不是部分字符串。 class Solution {publ…...

go 网络编程 websocket gorilla/websocket

在 Go 语言中&#xff0c;你可以使用标准库中的 net/http 包和第三方库 gorilla/websocket 来实现一个 WebSocket 服务器。gorilla/websocket 库提供了对 WebSocket 协议的高级抽象&#xff0c;使得处理 WebSocket 连接变得相对简单。 package mainimport ("fmt"&qu…...

deepseek与其他大模型配合组合

DeepSeek与其他大模型的配合组合&#xff0c;展现了其在多个领域中的强大应用潜力和灵活性。以下是对DeepSeek与其他大模型配合组合的详细分析&#xff1a; 一、DeepSeek与华知大模型的组合 背景介绍&#xff1a; 华知大模型是同方知网与华为联手打造的&#xff0c;具备全学科…...

【Linux网络编程】IP协议格式,解包步骤

目录 解析步骤 1.版本字段&#xff08;大小&#xff1a;4比特位&#xff09; 2.首部长度&#xff08;大小&#xff1a;4比特位&#xff09;&#xff08;单位&#xff1a;4字节&#xff09; &#x1f35c;细节解释&#xff1a; 3.服务类型&#xff08;大小&#xff1a;8比特…...

Unity 位图字体

下载Bitmap Font Generator BMFont - AngelCode.com 解压后不用安装直接双击使用 提前设置 1、设置Bit depth为32 Options->Export options 2、清空所选字符 因为我们将在后边导入需要的字符。 Edit->Select all chars 先选择所有字符 Edit->Clear all chars i…...

Linux 网络与常用操作(适合开发/运维/网络工程师)

目录 OSI 七层协议简介 应用层 传输层 Linux 命令&#xff01;&#xff01;&#xff01; 1. ifconfig 命令 简介 1. 查看网络地址信息 2. 指定开启、或者关闭网卡 3. 修改、设置 IP 地址 4. 修改机器的 MAC 地址信息 5. 永久修改网络设备信息 2. route 路由命令 …...

指定定网卡名称

一、PCIe网卡名称指定 原理&#xff1a;利用udev规则匹配PCIe设备的硬件特征&#xff08;如总线位置、MAC地址等&#xff09;&#xff0c;覆盖默认命名规则 4 。 步骤&#xff1a; 获取设备信息&#xff1a; Bash udevadm info -a -p /sys/class/net/<原设备名> # 如e…...

linux 安装启动zookeeper全过程及遇到的坑

1、下载安装zookeeper 参考文章&#xff1a;https://blog.csdn.net/weixin_48887095/article/details/132397448 2、启动失败 1、启动失败JAVA_HOME is not set and java could not be found in PATH 已安装 JAVA 配置了JAVA_HOME,还是报错解决方法&#xff1a;参考&#xf…...

RD-搭建测试环境

测试团队职责 环境验证&#xff1a;确保开发部署的测试环境可访问&#xff0c;页面/接口无阻塞问题&#xff1b; 配置检查**&#xff1a;核对数据库连接、接口域名、HT证书等关键配置&#xff1b; 数据准备**&#xff1a;导入基线数据&#xff0c;隔离测试与生产数据&#xff1…...

MySQL数据库——表的约束

1.空属性&#xff08;null/not null&#xff09; 两个值&#xff1a;null&#xff08;默认的&#xff09;和not null&#xff08;不为空&#xff09; 数据库默认字段基本都是字段为空&#xff0c;但是实际开发时&#xff0c;尽可能保证字段不为空&#xff0c;因为数据为空没办法…...

ArcGIS Pro进行坡度与坡向分析

在地理信息系统中&#xff0c;坡度分析是一项至关重要的空间分析方法&#xff0c;旨在精确计算地表或地形的坡度&#xff0c;为地形特征识别、土地资源规划、环境保护、灾害预警等领域提供科学依据。本文将详细介绍如何利用ArcGIS Pro这一强大的地理信息系统软件&#xff0c;进…...

【MySQL常见疑难杂症】MySQL数据库底层图例

● Connectors&#xff08;连接者&#xff09;​&#xff1a;指的是不同语言中与SQL的交互&#xff0c;从图3-1中可以看到目前流行的语言都支持MySQL客户端连接。 ● Connection Pool&#xff08;连接池&#xff09;​&#xff1a;管理缓冲用户连接、线程处理等需要缓存的需求。…...

nats集群搭建

本次使用三台机器搭建nats集群&#xff0c;ip分别为192.168.20.7、192.168.20.8、192.168.20.10&#xff0c;预先在三台机器上装好nats&#xff0c;版本为0.0.35。 1. 在192.168.20.7机器上操作&#xff0c;配置server.conf # 为节点设置唯一的名称 server_name: node1 port: …...

谈谈对线程的认识

面对这样的一个多核CPU时代, 实现并发编程是刚需. 多进程实现并发编程, 效果是特别理想的. 但是, 多线程编程模型有一个明显的缺点, 就是进程太重了, 效率不高. 创建一个进程, 消耗时间比较多. 销毁一个进程, 消耗时间也比较多. 调度一个进程, 消耗时间也比较多. 这里的时…...

Vue 和 React 响应式的区别

React 和 Vue 在响应式机制上的核心区别主要体现在数据变化侦测方式、更新触发逻辑和设计理念上&#xff0c;具体如下&#xff1a; 一、数据变化侦测方式 Vue 的响应式 原理&#xff1a;通过 Proxy&#xff08;Vue3&#xff09;或 Object.defineProperty&#xff08;Vue2&#…...

无人机遥控器接口作用详解!

USB接口&#xff1a; 功能&#xff1a;USB接口是一种通用串行总线接口&#xff0c;用于连接外部设备&#xff0c;如手机、平板、电脑或充电设备。在无人机遥控器上&#xff0c;USB接口通常用于数据传输和充电。 应用&#xff1a;用户可以通过USB接口将遥控器与电脑连接&#…...

【数据分析】1 认识数据分析

一、课程核心内容结构 1. 课程定位 商业数据分析导论课&#xff1a;旨在为初学者奠定扎实的基础&#xff0c;介绍数据分析的基本概念、方法和应用场景。后续模块&#xff1a;包括职业发展路径、技能要求等深入内容&#xff0c;帮助学习者规划未来的职业道路。目标群体&#x…...

ASP.NET Core 简单文件上传

使用异步 JavaScript 和 XML&#xff08;AJAX&#xff09;进行简单的文件上传&#xff1b;用 C# 编写的服务器端代码。 使用AJAX和ASP.NET Core MVC上传文件再简单不过了。这不依赖于jQuery。此代码允许上传多个文件&#xff0c;并与 .NET Core 3.1、.NET 6和.NET 8兼容。 如果…...

策略模式Spring框架下开发实例

策略类Spring框架下开发实例 先列出策略模式下需要那些类: 策略接口 (Strategy)&#xff0c;定义所有策略类必须遵循的行为。 具体策略类&#xff08;如 ConcreteStrategyA、ConcreteStrategyB&#xff09;&#xff0c;实现不同的算法或行为。 上下文类 (Context)&#xff0c;…...

量子计算驱动的金融衍生品定价革命:突破传统蒙特卡洛模拟的性能边界

引言&#xff1a;金融计算的算力困局 某国际投行采用128量子位处理器对亚洲期权组合定价时&#xff0c;其量子振幅估计算法在2.7秒内完成传统GPU集群需要68小时的计算任务。在蒙特卡洛路径模拟实验中&#xff0c;量子随机游走算法将10,000维衍生品的价格收敛速度提升4个数量级…...

华为昇腾 910B 部署 DeepSeek-R1 蒸馏系列模型详细指南

本文记录 在 华为昇腾 910B(65GB) * 8 上 部署 DeepSeekR1 蒸馏系列模型&#xff08;14B、32B&#xff09;全过程与测试结果。 NPU&#xff1a;910B3 (65GB) * 8 &#xff08;910B 有三个版本 910B1、2、3&#xff09; 模型&#xff1a;DeepSeek-R1-Distill-Qwen-14B、DeepSeek…...

pyscenic运行报错:ValueError: Intersection of gene_names and tf_names is empty

pyscenic运行报错&#xff1a;ValueError: Intersection of gene_names and tf_names is empty 首先查一下是否有重复基因 python check_common_genes.pycheck_common_genes.py import pandas as pd# 定义文件路径 #这是转置后的基因表达矩阵 expression_matrix_file "…...

Selenium实战案例2:东方财富网股吧评论爬取

上一篇文章&#xff0c;我们使用Selenium完成了网页内文件的自动下载,本文我们将使用Selenium来爬取东方财富网股吧内笔记的评论数据。 网页内容分析 网页内容的分析是web自动化中的关键一步。通过分析网页结构&#xff0c;我们可以确定需要抓取的数据位置以及操作元素的方式。…...

python的多线程机制和构造

Python的多线程机制和构造是一个复杂且多方面的主题&#xff0c;涉及到线程的基本概念、实现方式、同步机制以及实际应用。以下将详细介绍Python中的多线程机制和构造。 1. 线程的基本概念 线程是进程内的执行单元&#xff0c;每个线程共享进程的地址空间和资源。一个进程至少…...

webmin配置终端显示样式,模仿UbuntuDesktop终端

webmin配置终端显示样式&#xff0c;模仿UbuntuDesktop终端 在webmin中&#xff0c;默认情况下是没有图形化桌面的&#xff0c;因此终端界面也不会像 Ubuntu Desktop 那样有预设的紫色背景和颜色主题。不过&#xff0c;你可以通过修改 ~/.bashrc 文件&#xff0c;并结合安装和…...