帮你做到零bug的编程方法 - ATDD

合集下载

o-block方法

o-block方法

o-block方法Objective-C中的block是一种数据类型,用于在运行时保存代码。

它类似于函数,但有一些特殊之处。

以下是关于Objective-C中block的一些方法:1. 定义block:定义格式:void (block名)();示例:void(myBlock)() {NSLog(@"Hello");}2. 调用block:使用格式:block名();示例:myBlock();3. 带有参数的block:定义格式:void (block名称)(参数列表) (参数列表) // 代码实现;示例:void(sumBlock)(int, int) (int x, int y) {NSLog(@"%d", x * y);}4. 带有参数和返回值的block:定义格式:返回类型(block名称)(参数列表) 返回类型(参数列表) // 代码实现;示例:int(sumBlock2)(int, int) int(int a, int b) {return a + b;}5. 使用typedef声明block类型:typedef int (MySum)(int, int);示例:MySum sum(int a, int b) {return a + b;}6. 在block中对局部变量进行修改:block中可以访问和修改局部变量,但需要注意防止循环引用。

可以使用弱引用(weak)来避免循环引用。

示例:weak MyClass weakSelf;block myBlock2(NSInteger count) {weakSelf.count = count;}7. 将block作为方法调用的参数:预先声明block及其属性,然后定义方法接受block作为参数。

示例:typedef int (MyBlock)(int a, int b);@property (nonatomic, copy) MyBlock myBlock2;- (int)methodTakeBlock:(MyBlock)block {int sum = 0;if (block) {sum = block(10, 20);}return sum;}调用:myBlock2 = ^(int a, int b) {NSLog(@"%d", a + b);};[self methodTakeBlock:myBlock2];以上就是Objective-C中关于block的一些方法,希望对您有所帮助。

debug指示灯代码

debug指示灯代码

DEBUG指示灯代码00 . 已显示系统的配置;即将控制ini19引导装入。

.01 . 处理器测试1,处理器状态核实,如果测试失败,循环是无限的。

处理器寄存器的测试即将开始,不可屏蔽中断即将停用。

cpu寄存器测试正在进行或者失败。

02 . 确定诊断的类型(正常或者制造)。

如果键盘缓冲器含有数据就会失效。

停用不可屏蔽中断;通过延迟开始。

cmos写入/读出正在进行或者失灵。

03. 清除8042键盘控制器,发出testkbrd命令(aah)通电延迟已完成。

rom bios检查部件正在进行或失灵。

04 . 使8042键盘控制器复位,核实testkbrd。

键盘控制器软复位/通电测试。

可编程间隔计时器的测试正在进行或失灵。

05. 如果不断重复制造测试1至5,可获得8042控制状态。

已确定软复位/通电;即将启动rom。

dma初如准备正在进行或者失灵。

06. 使电路片作初始准备,停用视频、奇偶性、dma电路片,以及清除dma电路片,所有页面寄存器和cmos停机字节。

已启动rom计算rom bios检查总和,以及检查键盘缓冲器是否清除。

dma初始页面寄存器读/写测试正在进行或失灵。

07 . 处理器测试2,核实cpu寄存器的工作。

rom bios检查总和正常,键盘缓冲器已清除,向键盘发出bat(基本保证测试)命令。

.08 . 使cmos计时器作初始准备,正常的更新计时器的循环。

已向键盘发出bat命令,即将写入bat命令。

ram更新检验正在进行或失灵。

09 . eprom检查总和且必须等于零才通过。

核实键盘的基本保证测试,接着核实键盘命令字节。

第一个64k ram测试正在进行。

0a . 使视频接口作初始准备。

发出键盘命令字节代码,即将写入命令字节数据。

第一个64k ram芯片或数据线失灵,移位。

0b . 测试8254通道0。

写入键盘控制器命令字节,即将发出引脚23和24的封锁/解锁命令。

第一个64k ram奇/偶逻辑失灵。

OD破解常用方法

OD破解常用方法

一、概论壳出于程序作者想对程序资源压缩、注册保护的目的,把壳分为压缩壳和加密壳两种顾名思义,压缩壳只是为了减小程序体积对资源进行压缩,加密壳是程序输入表等等进行加密保护。

当然加密壳的保护能力要强得多!二、常见脱壳方法预备知识1.PUSHAD (压栈)代表程序的入口点,2.POPAD (出栈)代表程序的出口点,与PUSHAD想对应,一般找到这个OEP就在附近3.OEP:程序的入口点,软件加壳就是隐藏了OEP(或者用了假的OEP/FOEP),只要我们找到程序真正的OEP,就可以立刻脱壳。

方法一:单步跟踪法1.用OD载入,点“不分析代码!”2.单步向下跟踪F8,实现向下的跳。

也就是说向上的跳不让其实现!(通过F4)3.遇到程序往回跳的(包括循环),我们在下一句代码处按F4(或者右健单击代码,选择断点——>运行到所选)4.绿色线条表示跳转没实现,不用理会,红色线条表示跳转已经实现!5.如果刚载入程序,在附近就有一个CALL的,我们就F7跟进去,不然程序很容易跑飞,这样很快就能到程序的OEP6.在跟踪的时候,如果运行到某个CALL程序就运行的,就在这个CALL中F7进入7.一般有很大的跳转(大跨段),比如jmp XXXXXX 或者JE XXXXXX 或者有RETN的一般很快就会到程序的OEP。

Btw:在有些壳无法向下跟踪的时候,我们可以在附近找到没有实现的大跳转,右键-->“跟随”,然后F2下断,Shift+F9运行停在“跟随”的位置,再取消断点,继续F8单步跟踪。

一般情况下可以轻松到达OEP!方法二:ESP定律法ESP定理脱壳(ESP在OD的寄存器中,我们只要在命令行下ESP的硬件访问断点,就会一下来到程序的OEP了!)1.开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色)。

(这只是一般情况下,更确切的说我们选择的ESP值是关键句之后的第一个ESP值)2.在命令行下:dd XXXXXXXX(指在当前代码中的ESP地址,或者是hr XXXXXXXX),按回车!3.选中下断的地址,断点--->硬件访--->WORD断点。

java中零点十分定时任务表达式

java中零点十分定时任务表达式

标题:深度探讨Java中的零点十分定时任务表达式一、引言在Java开发中,定时任务的使用频率非常高,而零点十分定时任务表达式更是常见的一种。

在本文中,我将从简单介绍零点十分定时任务表达式的基本概念开始,逐步深入探讨其用法、原理和注意事项,以帮助您更深入地理解和灵活运用这一常见的定时任务表达式。

二、什么是零点十分定时任务表达式?零点十分定时任务表达式是指一种用于在Java中进行定时任务调度的表达式格式。

在这种表达式中,我们可以指定小时、分钟、秒等时间单位,以便精确地控制定时任务的执行时间。

三、零点十分定时任务表达式的基本结构在Java中,零点十分定时任务表达式由6个字段组成,分别表示秒、分、时、日、月、周几。

其中,秒、分、时这三个字段用于表示时间,而日、月、周几这三个字段用于表示日期。

具体格式如下:秒(0-59)分(0-59)时(0-23)日(1-31)月(1-12)周几(0-7)其中,每个字段都可以设置为一个具体的值,多个值之间用逗号隔开;也可以使用“*”代表该字段的所有取值,使用“-”表示范围,使用“/”表示步长等。

以零点十分定时任务为例,要表示每天的零点十分执行一次任务的表达式为:```0 10 0 * * ?```四、零点十分定时任务表达式的高级用法除了基本的表示方式外,零点十分定时任务表达式还支持一些高级的用法,例如:- 使用“/”表示间隔时间。

“0 0/5 * * * ?”表示每隔5分钟执行一次任务。

- 使用“?”表示不指定具体的值。

在日、月、周几中,可以使用“?”来表示不指定具体的值,表示任意值都可以匹配。

五、零点十分定时任务表达式的注意事项在使用零点十分定时任务表达式时,需要注意以下几点:- 应谨慎设置秒、分、时,避免产生不必要的执行次数。

- 需要考虑定时任务的并发执行情况,避免出现多个任务同时执行的情况。

- 需要充分测试表达式的正确性和可靠性,在生产环境中谨慎调整定时任务的执行时间。

四种软件开发模式:tdd、bdd、atdd和ddd的概念

四种软件开发模式:tdd、bdd、atdd和ddd的概念

四种软件开发模式:tdd、bdd、atdd和ddd的概念看⼀些⽂章会看到TDD开发模式,搜索后发现有主流四种软件开发模式,这⾥对它们的概念做下笔记。

TDD:测试驱动开发(Test-Driven Development)测试驱动开发是敏捷开发中的⼀项核⼼实践和技术,也是⼀种设计⽅法论,TDD⾸先考虑使⽤需求(对象、功能、过程、接⼝等)。

主要是编写测试⽤例框架对功能的过程和接⼝进⾏设计,⽽测试框架可以持续进⾏验证。

⼤⾏其道的⼀些模式对TDD的⽀持都⾮常不错,⽐如MVC和MVP等。

BDD:⾏为驱动开发(Behavior Driven Development)BDD也就是⾏为驱动开发。

这⾥的B并⾮指的是Business,实际上BDD可以看作是对TDD的⼀种补充,让开发、测试、BA以及客户都能在这个基础上达成⼀致,JBehave之类的BDD框架。

ATDD:验收测试驱动开发(Acceptance Test Driven Development)通过单元测试⽤例来驱动功能代码的实现,团队需要定义出期望的质量标准和验收细则,以明确⽽且达成共识的验收测试计划(包含⼀系列测试场景)来驱动开发⼈员的TDD实践和测试⼈员的测试脚本开发。

⾯向开发⼈员,强调如何实现系统以及如何检验。

DDD:领域驱动开发(Domain Drive Design)DDD指的是Domain Drive Design,也就是领域驱动开发,DDD实际上也是建⽴在这个基础之上,因为它关注的是Service层的设计,着重于业务的实现,将分析和设计结合起来,不再使他们处于分裂的状态,这对于我们正确完整的实现客户的需求,以及建⽴⼀个具有业务伸缩性的模型。

"我们提着过去,⾛进⼈群。

"。

牛顿法求零点的方法

牛顿法求零点的方法

牛顿法求零点的方法摘要:一、牛顿法求零点的基本原理二、牛顿法求零点的步骤详解1.选择初始值2.计算导数3.更新迭代值4.判断收敛条件5.循环迭代直至满足收敛条件三、牛顿法的优缺点分析1.优点- 快速收敛- 适用于广泛函数类型2.缺点- 初始值选择影响较大- 可能不适用于非线性方程组四、实际应用案例及注意事项1.案例:求解非线性方程2.注意事项- 合理选择初始值- 判断方程是否可求解- 注意迭代过程中的数值稳定性和精度正文:一、牛顿法求零点的基本原理牛顿法(Newton"s method)是一种求解非线性方程或方程组的高效数值方法。

它的基本原理是利用函数的导数来修正初始值,使得迭代值更加接近零点。

牛顿法具有收敛速度快、适用范围广等优点,但同时也存在一定的局限性。

二、牛顿法求零点的步骤详解1.选择初始值:首先,需要选择一个初始值作为迭代起点。

初始值的选择对收敛速度和稳定性有很大影响,因此需要合理选择。

2.计算导数:对于给定的函数,需要计算其导数。

导数可以帮助我们了解函数在不同点处的变化趋势,从而选择合适的迭代方向。

3.更新迭代值:根据初始值和导数,可以计算出新的迭代值。

新的迭代值是通过在初始值的基础上进行修正得到的,使其更加接近零点。

4.判断收敛条件:判断迭代值是否满足收敛条件。

收敛条件可以根据实际情况设定,例如残差阈值或迭代次数阈值等。

5.循环迭代直至满足收敛条件:如果迭代值不满足收敛条件,则继续迭代。

迭代过程中需要注意数值稳定性和精度,以防止出现错误的收敛。

三、牛顿法的优缺点分析1.优点:- 快速收敛:牛顿法通常能够快速收敛到零点,尤其在函数较为光滑的情况下。

- 适用于广泛函数类型:牛顿法适用于一次、二次及更高次的非线性方程和方程组,具有较强的通用性。

2.缺点:- 初始值选择影响较大:初始值的选择对收敛速度和稳定性有很大影响,有时需要多次尝试才能找到合适的初始值。

- 可能不适用于非线性方程组:当方程组中某些方程的导数接近零时,牛顿法可能不适用。

O操作的代码技巧与建议

编写高效的I/O操作的代码技巧与建议在编写高效的I/O操作代码时,我们需要重点关注优化数据读取、写入和处理的过程,以提高程序的运行效率和性能。

以下是一些关于高效I/O操作的代码技巧和建议:1.使用缓冲区在进行I/O操作时,使用缓冲区可以大大提高数据的读取和写入效率。

缓冲区可以减少I/O操作的次数,将数据批量读取或写入到内存中,减少系统调用和磁盘访问次数,从而提高程序的性能。

在Java 中,可以使用BufferedInputStream和BufferedOutputStream来进行缓冲读写操作。

例如:```javaBufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"));byte[] buffer = new byte[1024];int len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len);}```2.使用更高效的I/O类有些I/O类比其他类更高效。

在选择I/O类时,应该根据应用的需求和性能要求来选择更高效的类。

例如,在Java中,使用RandomAccessFile类可以实现对文件的随机访问,提高文件读取和写入的效率。

3.使用非阻塞I/O在网络编程中,使用非阻塞I/O可以提高程序的并发性能。

非阻塞I/O允许一个线程处理多个I/O事件,减少了线程切换的开销,提高了程序的并发处理能力。

在Java中,可以使用NIO来实现非阻塞I/O操作。

4.使用零拷贝技术在进行文件复制和网络数据传输时,可以使用零拷贝技术来避免数据在内核态和用户态之间的多次复制,提高数据传输的效率。

Java开发最容易写的10个bug

Java开发最容易写的10个bug原⽂链接:那个谁,今天⼜写 bug 了,没错,他说的好像就是我。

作为 Java 开发,我们在写代码的过程中难免会产⽣各种奇思妙想的 bug ,有些 bug 就挺让⼈⽆奈的,⽐如说各种空指针异常,在 ArrayList 的迭代中进⾏删除操作引发异常,数组下标越界异常等。

如果你不⼩⼼看到同事的代码出现了我所描述的这些 bug 后,那你就把我这篇⽂章甩给他你甩给他⼀篇⽂章,并让他关注了⼀波cxuan,你会收获他在后⾯像是如获⾄宝并满眼崇拜⼤神的⽬光。

废话不多说,下⾯进⼊正题。

错误⼀:Array 转换成 ArrayListArray 转换成 ArrayList 还能出错?这是哪个笨。

等等,你先别着急说,先来看看是怎么回事。

如果要将数组转换为 ArrayList,我们⼀般的做法会是这样List<String> list = Arrays.asList(arr);Arrays.asList() 将返回⼀个 ArrayList,它是 Arrays 中的私有静态类,它不是 java.util.ArrayList 类。

如下图所⽰Arrays 内部的 ArrayList 只有 set、get、contains 等⽅法,但是没有能够像是 add 这种能够使其内部结构进⾏改变的⽅法,所以 Arrays 内部的 ArrayList 的⼤⼩是固定的。

如果要创建⼀个能够添加元素的 ArrayList ,你可以使⽤下⾯这种创建⽅式:ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));因为 ArrayList 的构造⽅法是可以接收⼀个 Collection 集合的,所以这种创建⽅式是可⾏的。

错误⼆:检查数组是否包含某个值检查数组中是否包含某个值,部分程序员经常会这么做:Set<String> set = new HashSet<String>(Arrays.asList(arr));return set.contains(targetValue);这段代码虽然没错,但是有额外的性能损耗,正常情况下,不⽤将其再转换为set,直接这么做就好了:return Arrays.asList(arr).contains(targetValue);或者使⽤下⾯这种⽅式(穷举法,循环判断)for(String s: arr){if(s.equals(targetValue))return true;}return false;上⾯第⼀段代码⽐第⼆段更具有可读性。

bugfree解决方案

bugfree解决方案
《bugfree》解决方案
在软件开发过程中,bug是无法避免的问题。

但是,如何有效
地解决bug成了开发者们所面临的挑战。

在这里,我们将介绍一些解决bug的方法,帮助您打造一个bugfree的软件。

首先,进行彻底的测试是非常重要的。

在软件开发的每个阶段都要进行测试,包括单元测试、集成测试和系统测试等。

通过测试,可以及时发现并解决bug,确保软件的质量。

其次,合理利用版本控制系统也是解决bug的关键。

通过版本控制系统,可以记录软件的每一个版本,便于开发者们追踪bug的来源,并进行适当的修改。

另外,采用有效的调试工具也是解决bug的好办法。

调试工具可以帮助开发者们快速定位bug,并找出解决bug的最佳方法。

此外,建立一个开放的沟通渠道也是解决bug的有效途径。

开发者们可以利用沟通渠道及时交流bug的情况,并进行合作解决bug,提高解决bug的效率。

最后,定期进行代码审查也是解决bug的好方法。

通过代码审查,可以发现潜在的问题,并及时加以修正,确保软件的稳定性和可靠性。

总之,解决bug需要开发者们的共同努力和不懈探索。

希望通
过上述方法,您可以打造一个bugfree的软件,为用户提供更好的体验。

ddd领域事件的实现方式

ddd领域事件的实现方式
在软件开发中,领域事件是指领域中发生的重要事情或变化,
它们可以被用来触发其他操作或者通知其他部分系统。

实现领域事
件的方式有多种,以下是一些常见的方式:
1. 发布-订阅模式,这是一种常见的实现领域事件的方式。


这种模式下,事件发布者将事件发布到一个中心位置,订阅者可以
注册对特定事件的兴趣,并在事件发生时接收通知。

这种方式可以
实现松耦合,使得事件发布者和订阅者之间互相独立,同时也能够
支持多个订阅者。

2. 观察者模式,观察者模式也是一种常见的实现领域事件的方式。

在这种模式下,事件发布者维护一个观察者列表,当事件发生时,它会通知所有观察者。

观察者模式可以实现一对多的依赖关系,当事件发生时,所有的观察者都会得到通知。

3. 消息队列,使用消息队列来实现领域事件也是一种常见的方式。

事件发布者将事件发布到消息队列中,订阅者可以从消息队列
中获取事件并进行处理。

消息队列可以实现异步处理,提高系统的
性能和可伸缩性。

4. 回调函数,在一些编程语言中,可以使用回调函数来实现领域事件。

事件发布者在事件发生时调用注册的回调函数,通知订阅者进行处理。

总的来说,实现领域事件的方式有很多种,选择合适的方式取决于具体的业务需求和系统架构。

在设计时需要考虑系统的可扩展性、性能和可维护性等因素。

希望这些信息能够帮助你更好地理解领域事件的实现方式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ATDD的原则传统的软件需求(Specification)存在一个问题:需要特别的努力才能做得好。

然而一旦它们编写完成,很快就会因为各种原因(你能控制的,或无法控制的)而迅速过时。

举个例子,如果一个竞争对手发布了一个新特性,你的需求要立刻响应以保持你的市场份额。

由于这显然是一个非技术决策,所以至少需要一些有业务背景的人参与需求决策过程。

在确定需求过程中获得的意见越是多样化,你就越能看清楚整个应用的全景。

通常来说,你至少需要从三个不同的视角考虑。

首先,需要考虑业务视角。

在敏捷团队中,这方面需求通常由客户代表、客户代理人或是Scrum中的产品负责人(Product Owner)来提出。

其次需要考虑技术视角。

在传统的团队中,资深开发人员或技术负责人通常会站在这个视角。

在敏捷团队中,你会希望讨论会中有一个参与实际开发工作并熟悉源代码的团队成员参加。

最后,需要有人在这两种视角中充当中间人。

在传统项目中,你会发现业务分析人员会提供这种视角。

一个富有经验的软件测试人员会带来同样的价值。

1 见识“三的力量”可是为什么这三种不同的视角可以帮助我们确定产品的需求呢?设计软件系统包含很多对这两个方面的权衡:业务功能与技术限制。

我们的软件代码中充满了对功能和限制所做的折衷。

另一方面,我们的缺陷数据库中则充满了由明显决策失误而导致的问题。

这些决策中,有些在软件开发过程中很难改变,有些则很容易改正。

通过尽早让业务功能和技术限制这两种不同的视角接触,我们可以尽早找到正确的决策平衡点。

因而,可以将引入难以改正的bug和容易改正的bug 的概率降到最低。

顺便我们也可以避免这两种极端情况中间的那些bug。

软件系统的功能分布在一个解决方案空间中[GW89]。

这个解决方案空间中存在很多可以实现所需功能的可行设计方案。

这就解释了为什么你可以带着性能或负载等特性的需要去探索解决方案空间。

这些特性限制了解决方案空间中能满足用户期望的方案的数量。

另一方面,软件实现还存在技术方面的制约。

这些制约同样限制了实现所有功能以及特性的设计方案数目。

将业务功能和特性与技术的制约尽早放在一起考虑,可以帮助参与者在解决方案空间中探索可能的设计。

这是验收测试驱动开发方法可以成功的重要因素之一。

并且,它证明了测试人员在这个探索过程中也能发挥作用,他们可以对软件在功能、特性以及制约方面提出问题和建议。

但是,怎么看待独立的测试团队能带来独特的视角这一观点呢?在过去数十年的测试培训中,我们学到的观点是:开发人员和测试人员应当基于需求文档这一共同的基础而完全独立的工作。

这避免了在现代心理学中被称为共识偏见(confirmation bias)的现象。

测试人员必须避免受到开发人员观点的影响,并且在应当在适当的时候对产品作出评价。

一些团队将这条规则发挥到这样一种极致:开发人员与测试人员被完全禁止与对方交谈。

与开发人员一起描述软件需求并不会给测试人员带来先入为主的偏见。

相反,开发人员、测试人员与业务专家应该一起捕捉软件需求。

如果你认为这也会使测试人员产生偏见,那么你是不是该开始怀疑阅读需求文档也同样会使测试人员产生偏见?对于测试人员,与开发人员以及业务专家一起描述需求实例和参加需求讨论会的功用是一样的,这也是大多数测试人员在他们的职业生涯中都梦想能做到的。

事实上,在Gojko Adzic的书《实例化需求》(Specification by Example)[Adz11]中采访到的团队反映,由至少一个开发人员和一个测试人员提供的综合观点,会让我们在项目初期就更好地理解需求。

就像我们在机场的实例中看到的一样,这种讨论通常会达到以下的效果,开发人员通过提出技术性的问题来澄清业务流程,同时测试人员提出的问题则增加了需求的可理解性,并且用表格这一更加可视化的方式记录了需求。

1在迭代过程中,开发人员与测试人员基于对特性共同的基本理解开展工作。

作为验收测试的实例则成为衡量团队进度的指标。

为了达到最好的结果,确认需求的过程应包含以下三种不同的角色:一个业务专家(例如Produce Owner,或驻厂的用户)、一个开发人员和一个测试人员。

基于所包含的角色个数,Janet Gregory和Lisa Crispin把这叫做“三的力量”。

“三种解释原则”[Wei93,90页]提醒我们在对收到的信息下结论之前,至少要想到3种可能的情况。

如果我对收到的信息不能想到至少3种解释,就说明我对它的含义考虑的还不够全面。

“三的力量”可以帮助我们克服想象力的不足。

让代表三种视角的人坐在一张桌子旁,充分理解特性或用户故事的可能性就会大大增加。

这就是“三的力量”为何如此强大的原因。

“三的力量”不仅限于功能性需求。

开发人员会注意到代码可能存在的性能问题,而要求澄清这方面的需求。

测试人员通常会注意到可用性方面的问题。

开发人员、测试人员和业务代表可以澄清对所有特性在质量方面的要求——有些时候这被称为非功能性需求。

记住,要考虑到自动化测试无法覆盖的问题,并使用测试象限(见图9-2)来构建你的测试交响曲(见9.4节)。

大多数的性能、负载以及稳定性的需求可以通过自动化测试来检测。

2 举办讨论会如同我们在第一部分看到的,讨论会可以使整个团队对将要实现的功能获得一致的理解。

你必须仔细考虑以下方面,才能组织一场让大家(包括不出席会议的)都满意的需求讨论会。

2 1 参加者首先,你要确保自己选择了正确的参与者。

对有些团队来说,这可能意味着包含整个开发团队以及来自不同公司的所有用户。

这些团队通常都会举办一次比较大型的会议,但每个迭代都会开个小的碰头会。

另一方面,也有团队在讨论会中只包含三个角色的代表,就是只有三个人参加的小型会议。

无论哪种情况,你都需要保证存在不同的视角。

通常这意味着要包含熟悉产品业务方面的人。

你同样需要有直接能接触到专业用户的人[Coc06]。

如同我在10.1节中提到的,你应当包含至少一个开发人员和一个测试人员。

这个开发人员要熟悉代码。

在需求讨论会中,开发人员会基于功能的技术实现提出问题。

由于他们自身的特点,开发人员会考虑功能如何实现并且在他们的脑海中构建领域模型。

讨论会能使他们对新功能点对应的业务领域取得一致的理解。

测试人员通过他们批判性的眼光,可以很快发现业务规则中的漏洞。

测试人员在需求讨论会中发挥的另一个独特作用是:他们能够使用表格记录业务规则,使其变得清楚透明。

无论他们是否使用过被称为“敏捷友好”的自动化测试框架,有经验的测试人员都知道如何使用决策表以及如何用表格形式表达复杂的业务规则。

如果大家在需求讨论会中使用这样的表达方式,那么开发人员、测试人员和业务专家就可以在没有写任何代码之前就对讨论的功能点达成共识。

2 2 讨论会的目标为了使需求讨论会能开得成功,你要知道谁是你的主要听众。

虽然领域专家带来了关于新特性的必要知识,但是开发团队(开发人员和测试人员)才是你的主要听众。

还要记住很重要的一点,客户和外部业务专家通常都很忙。

如果你邀请他们参加会议,而会上你的开发人员们在激烈争论是否要使用最新的Web服务器,以及要使用哪种技术,那么下一次他们可能就不会再参加你的讨论会了。

你需要一个有经验的引导者使会议集中于讨论特性,而不是争论具体实现的技术问题。

讨论会的目标是对业务规则取得一致的理解。

你可以在业务代表离开之后再接着讨论所有的技术问题。

在需求讨论会上花费的时间应该用来使团队获得共同的理解和愿景。

2 3 频率与时长下面要讨论的问题是你应当多频繁地组织这样的讨论会。

当然,这很大程度上取决于领域专家是否有时间。

如果你需要联系一些业务代表,你会发现他们都很忙。

另一方面,你可能有驻厂的客户,那你就可以经常向他请教一些问题。

你可以根据实际情况,每个月为需求讨论会预留一个时间段,或者在每个迭代开始前开一个简短的讨论会。

你可以根据与领域专家一起参加需求讨论会频率的高低,为会议预留不同的时间长度。

如果你不经常举行需求讨论会,那么你可能希望每次多讨论一些特性,因此你需要多预留一些时间。

另一方面,如果你既希望保持会议简短,又希望开会不那么频繁,那么你只能选择少讨论一些特性,或者提前做一些准备工作。

如果你希望少讨论一些特性,那么你需要根据最新确定的优先级,从代办事项列表中挑选要讨论的特性。

应当首先讨论那些最有可能在下一个迭代中开发的特性。

你可能需要在讨论中跳过一些对团队来说已经比较清楚的特性,例如登录功能或者网页上的某个注释信息。

这会让你有更多时间讨论更复杂的特性中充满挑战的业务规则。

如果你想事先做一些准备,可以在讨论会之前研究一下代办事项列表,准备一些需要业务专家回答的问题。

你可以在大多数Scrum团队都有的代办事项列表准备会(backlog grooming meeting)上收集一些开放性问题。

也可以在讨论会前几天召集一个简短的会议讨论一下将要实现的特性。

另一种收集关于业务规则的想法和开放性问题的方式是在会议中将当前的理解可视化,通过思维导图(mindmap)来收集开放性问题。

但是你要记住,如果你在需求讨论会中打开投影仪,利用思维导图来收集答案,这样的会议就开始变成一种折磨。

因为你在强迫所有人安静地坐着,看你用投影仪打出来的字。

使用非高科技的工具,例如索引卡片、白板或者翻页纸版可以让你避免那些低效的会议,但你需要有人辅助你来记录讨论结果。

3 捕捉需求需求通常都不是收集到的[Coh04]。

客户与业务专家认为他们清楚地知道他们想要的是什么。

但当他们看到最终成果后,你和你的团队就会发现他们需要的是完全不同的东西。

这就是为什么说使用“收集”需求这个隐喻并不恰当的原因。

只有当它们明显地摆在那里,每个人都可以捡起来去实现所期望的软件时,才能说是收集需求。

不幸的是,需求并不是躺在那里等你去捡的。

大多数团队付出了很大的代价才明白这一点。

Mike Cohn建议采用一个不同的隐喻来取代“收集”。

既然需求不是躺在那里等着我们去收集的,因此我们需要付出一些努力才能抓住它们。

有一些技巧可以在不同层面帮我们做到这一点,就像使用不同网眼大小的渔网可以捕捞不同种类的鱼,而漏过其它种类的鱼一样。

这个类比可以很好地用来解释“实例化需求”中的各种不同技巧。

在前面的例子中,我们见到过两种应用都很广泛的实例化需求实践。

第一种是有一个独立的测试团队,可以在实现软件某个特性时与开发人员并行工作。

在这种情况下,我们的渔网意味着在产品中加入任何新的特性之前获得对特性的一致理解。

停车场例子中,整个团队在一起捕捉需求。

因为每个人对停车场都有一个基本的理解,所以团队成员通过提一些问题就可以对机场停车费用计算取得一致的理解。

这些问题就是我们捕捉实例所用的工具。

测试人员Tony很快就发现他可以通过记录实例来表达他对业务规则的理解。

在他记录的同时,Phyllis和Bill可以观察,并讨论他们的“渔网”还漏掉了什么。

相关文档
最新文档