阿里、蚂蚁、晟腾、中科加禾精彩分享 AI 基础设施洞见,现购票可享受 9 折优惠 |AICon 了解详情
写点什么

敏捷咨询工具箱(二)──OO 训练营

  • 2010-12-31
  • 本文字数:2911 字

    阅读完需:约 10 分钟

犯错误是最好的学习方式

──莎伦·德雷珀

背景

我们为客户提供咨询,刚开始做了很多敏捷的实践,包括:持续集成、测试驱动、用户故事需求分析、迭代开发等等之后,发现如果再想深入下去,就会面临一些“硬骨头”:遗留系统和开发设计能力的问题。在一些客户那里,他们产品有 10 多年了,但是很少有人新加程序文件,写代码习惯于复制粘贴,都是在已有的类和函数上修修补补。团队缺少追求好代码的品质和能力,到处是大函数,上帝类(超大类,任何功能变化都要修改此类),重复代码,混乱逻辑,开发和维护成本太高。作为一个顾问,如何才能从根本解决这样的开发设计能力问题呢?

在 ThoughtWorks,如果招聘了一个没有经验的开发人员,会把他们送到印度的 TWU(ThoughtWorks University) 培养 2-6 个月,OO 训练营是开发人员的主要课程之一。它专门用来训练开发人员如何使用面向对象,如何进行测试驱动开发。通过这样的训练之后,开发人员可以很快的掌握面向对象开发和简单设计能力,养成追求好代码的品质。所以,我们也为客户的团队引入了 TWU 的 OO 训练营活动。

活动方式

clip_image002

OO 训练营的培训方式和我们传统的“填鸭式”教育完全相反。它采用的是苏格拉底式教学法,顾问不会给你任何标准答案,而是通过问题的引导,让学员自己一步一步找到最佳的解决方案。我的 OO 训练营的组织方式一般是:

一、顾问提出需求

顾问在训练营活动会扮演着客户的角色。活动一开始的时候,会以客户的身份提出一个需求,让大家去完成。例如:要求建模一个长方形。

二、简单设计

以分组讨论方式做一个简单设计,一般从如下三个方面进行设计。

  1. 类名是什么?
  2. 类的职责是什么?对于复杂需求,可能会要求画一个简洁的 UML 对象关系图。
  3. 类的测试用例会有哪些,并且找到第一个测试用例

讨论结束之后,每组介绍一下各自的讨论结果。通过分组讨论和顾问的引导,对建模一个长方形需求一般会得到如下的设计结果:

  1. 类名是: Rectangle
  2. 类的职责是计算周长和面积
  3. 计算周长的测试用例:
  • a. 正常场景。如果长是 2,宽是 3,那么周长是 10
  • b. 异常场景,宽为 0 的情况。如果长是 2,宽是 0,那么应该抛出异常
  • c. 异常场景,宽为负数的情况。如果长是 2,宽是 -3,那么应该抛出异常

这些测试用例完全是由学员自己设计出来的,没有标准答案。作为顾问只是引导大家,让每组的测试用例更具体和全面。假设没有一组学员没有考虑到异常情况的测试用例,这时也也不用指出来,等后面代码展示的时候,再指出这个问题,因为犯错是最好的学习方式。

三、测试驱动(TDD)开发

学员根据设计和讨论的结果,用测试驱动的方式进行结对编码开发。要求先写单元测试,写完一个单元测试之后,运行测试失败,然后再去写业务代码。如果没有失败的测试,不允许写一行业务代码。这样严格的要求,让大家养成测试驱动开发的好习惯。

两个人一组使用结对方式进行开发,要求使用乒乓式的结对方法。假设是 A 和 B 进行结对开发,A 先写一个测试用例,编译通过但是测试失败。然后把键盘和鼠标交给 B,B 写业务代码,让测试通过,然后为 A 再写一个失败的测试。通过这种乒乓的方式,一个人写测试用例,一个人实现业务代码,并且不停的变换角色。这样两个人可以很好的进行配合,互相给对方出“难题”,一个人在写实现的时候,另一个人会思考下一个测试用例会是什么。

有的时候,我们会对团队提出一些更高的要求。比如编程过程中不允许使用鼠标,一切都是快捷键操作,这样能提高开发的效率。编程过程中不允许使用复制和粘贴功能,如果是相同的功能或者代码,第一应该考虑到的是如何进行功能重用,而不是复制一遍,这样可以杜绝这样错误的编程习惯。

四、代码展示和顾问点评

写完代码之后,每个人开始展示自己的代码。这时,顾问就开始从代码里面寻找代码怀味道 (Bad smell),告诉大家什么样的是好代码,什么样的是坏代码。坏代码会有哪些危害,让后让大家重构。

例如:在实现长方形周长的时候,有人实现了 getLength 了 getWidth 方法,把长方形的长和宽的数据暴露出来了。那么这就是一个代码坏味道(Bad smell),顾问会指出这个问题,告诉大家面向对象最重要的一个特征是封装,不应该把数据直接暴露出来。因为数据暴露出来之后,一方面造成数据的依赖和耦合,另一方面其它代码在调用长方形这个对象的时候,也许会拿到长和宽的数据自己进行运算,这样就破坏了封装,对象之间耦合增大,并且容易产生重复的代码。然后提问大家,正确的做法应该是什么?

答案应该会是长方形不应该把长和宽的数据暴露出来,所有长方形相关的运算和逻辑都应该在长方形这个领域对象里面进行。这也正是面向对象设计的一个重要原则:Tell don’t ask 的体现。通过这样的引导的方式,带领大家一步一步找到正确的面向对象设计方法和原则,同时纠正那些错误的编码和设计习惯。

每次活动就是类似这样的流程。顾问提出需求,然后是讨论和设计,结对开发,最后展示代码和点评。一轮结束之后,顾问又给大家一些新的需求,进行第二轮,如此一直的循环下去。

经验和教训

我多次为客户的团队组织过类似的训练营活动。最长的一次坚持了 3 个月,每周 2 次,每次两个小时,完成了 OO 训练营的所有课程。坚持参加完这个活动之后,开发人员和技术 Leader 的都能真正的全面掌握面向对象设计方法和原则,并且把这些用到自己的项目中。下面是我的一些经验和教训:

  • 活动时间安排。如果每次活动 2 个小时,一般是安排在下班左右,一小时工作时间和一小时个人时间。因为大部分团队都有交付的任务和压力,完全占用工作时间不现实。
  • 家庭作业。由于我培训的一些团队技术基础不是很好,大部分开发人员无法在 2 个小时内完成编码任务。所以我会把没有完成的任务留作家庭作业,让大家在活动之后完成,这样在 OO 训练营的时候主要是进行设计讨论和代码的展示点评。这样也有一个好处,每个人都会有时间进行独立思考,对代码进行重构产生一个更好的设计。
  • 活动整个过程是以引导为主,让大家自己进行编码、重构和讨论,自己解决问题,寻找设计的最佳解决方案。顾问只是担任一个类似主持人的角色。

参考资料

如果你也想在自己的团队或者公司引入这样的活动,下面一些资料可供参考:

关于作者

钱安川,ThoughtWorks 公司高级软件咨询师、敏捷过程教练、资深讲师、Team Leader、开发者、 BeiJing Open Party 组织者和主持人。个人博客:敏捷开发训练

2010-12-31 06:242584

评论

发布
暂无评论
发现更多内容

K8s 安全是云安全的未来

HummerCloud

Kubernetes k8s

【web 开发】PHP 特殊的对象引用 "$this"(62)

迷彩

php 面向对象 this指针 三周年连更

Flink应用框架层

阿泽🧸

flink 三周年连更

GitHub爆赞!阿里P9架构师的JDK源码笔记也太强了!

做梦都在改BUG

Java 源码 jdk 高并发

【Python实战】Python采集热搜数据

BROKEN

三周年连更

Mac M1 安装SD不折腾版本

IT蜗壳-Tango

三周年连更

C++智能指针和内存管理:使用指南和技巧

小万哥

c++ 后端 开发 内存管理 智能指针

appuploader 入门使用

雪奈椰子

一文了解 Zebec Labs 投资的 Coral Finance,空投计划或在不久推出

股市老人

与伙伴同行,Serverless 让创新触手可及

阿里巴巴云原生

阿里云 Serverless 云原生

一文了解获得 Zebec Labs 投资的 Coral Finance,空投计划或在不久推出

西柚子

五张图带你看透Redis数据结构

做梦都在改BUG

ZooKeeper 避坑指南: ZooKeeper 3.6.4 版本 BUG 导致的数据不一致问题

阿里巴巴云原生

zookeeper 阿里云 开源 云原生

如何使用nobelium 1小时快速搭建你的私人博客

黑微狗‮‮

Blog nobelium

公开下载 | 300页《Java面试宝典》,收藏近万,多位翰林院成员推荐

Java你猿哥

Java MySQL spring 面试 ssm

针对容器层的五种攻击手段

穿过生命散发芬芳

容器安全 三周年连更

Django操作异步任务

乌龟哥哥

三周年连更

爆赞!GitHub上久经不衰的经典教程:Springboot精髓参考指南手册

做梦都在改BUG

Java spring 微服务 Spring Boot 框架

查询最新汽车新闻资讯

DS小龙哥

三周年连更

云原生技术实践营「微服务X消息队列专场」

阿里巴巴云原生

阿里云 微服务 云原生 消息队列

“双智天花板”闪耀鹏城,问界M5智驾版深圳首场尊享品鉴会成功举办

Geek_2d6073

一文看懂:StopWatch 源码解读

后台技术汇

三周年连更

云原生底座之上,这些企业领跑行业的秘密

阿里巴巴云原生

阿里云 容器 微服务 云原生

新手如何学习挖漏洞?看这篇就够了【网络安全】

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 漏洞挖掘

什么是数据库分片?

Java架构历程

Java 数据库 三周年连更

三种常用的以太网端口链路类型:Access、Hybrid和Trunk

wljslmz

网络 三周年连更

KubeVela 稳定性及可扩展性评估

阿里巴巴云原生

阿里云 开源 云原生 KubeVela

2023-05-03:给你一棵 二叉树 的根节点 root ,树中有 n 个节点 每个节点都可以被分配一个从 1 到 n 且互不相同的值 另给你一个长度为 m 的数组 queries 你必须在树上执行

福大大架构师每日一题

Go 算法 福大大

AI 作画火了,如何用 Serverless 函数计算部署 Stable Diffusion?

阿里巴巴云原生

阿里云 Serverless 云原生 AIGC

一文了解获得 Zebec Labs 投资的 Coral Finance,空投计划或在不久推出

EOSdreamer111

习惯了和AI聊天,感觉我更加社恐了......

FN0

人工智能 AI AIGC

敏捷咨询工具箱(二)──OO训练营_研发效能_钱安川_InfoQ精选文章