《Test-Driven development By Example》阅读(二)

前端之家收集整理的这篇文章主要介绍了《Test-Driven development By Example》阅读(二)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
第四章 变质的对象(Degenerate Objects)——使用数值对象(value object),不必担心别名问题。
1、clean code that works!
要达到这一目标,可以分步实施: 先达到“that works”,在达到“clean code”。——这与“体系结构驱动开发”相反
第五章 众生平等(Equality for All)——解决判等问题:equals()
1、三角法——或称为“间接法”
只有当例子达到2个或者更多时才对代码进行一般化。
2、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数;——拟解决问题
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
3、同步工程实践:
重写Dollar类中equals()方法
publicclassDollar{
publicintamount=0;
publicDollar(intamount){
this.amount=amount;
}
publicDollartimes(intmultiplier){
returnnewDollar(amount*multiplier);
}
publicbooleanequals(Objectobject){
Dollardollar=(Dollar)object;
returnamount==dollar.amount;
}
}
对equals()方法书写测试代码:
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Dollarfive=newDollar(5);
Dollarproduct=five.times(2);
assertEquals(10,product.amount);
product=five.times(3);
assertEquals(15,product.amount);
}
publicvoidtestEquality(){
assertTrue(newDollar(5).equals(newDollar(5)));
assertFalse(newDollar(5).equals(newDollar(6)));
}
}
测试通过,消除问题(6)。
第六章 私有性(privacy)——把公有变成私有
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;——解决问题
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
2、同步工程实践:
对原有测试代码进行调整,引入内联(inline)语句:
(1)去除原来的product对象,同时消除了product对amount的引用;
(2)让对象之间进行比较;
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Dollarfive=newDollar(5);
assertEquals(newDollar(10),five.times(2));
assertEquals(newDollar(15),five.times(3));
}
publicvoidtestEquality(){
assertTrue(newDollar(5).equals(newDollar(5)));
assertFalse(newDollar(5).equals(newDollar(6)));
}
}
经过修改,现在Dollar类是唯一个使用实例变量amount的类,可以把amount 设为private
修改Dollar类代码
publicclassDollar{
privateintamount=0;
publicDollar(intamount){
this.amount=amount;
}
publicDollartimes(intmultiplier){
returnnewDollar(amount*multiplier);
}
publicbooleanequals(Objectobject){
Dollardollar=(Dollar)object;
returnamount==dollar.amount;
}
}
若直接修改Dollar类amount为私有,不进行测试代码修改,则会出错:
java中访问私有变量只能使用getter()和setter()!
第七章 法郎在诉说(Franc-ly Speaking)——处理法郎问题
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;——待解决问题
2、同步工程实践:
建立同dollar一样的类以及方法
publicclassFranc{
privateintamount=0;
publicFranc(intamount){
this.amount=amount;
}
publicFranctimes(intmultiplier){
returnnewFranc(amount*multiplier);
}
publicbooleanequals(Objectobject){
Francdollar=(Franc)object;
returnamount==dollar.amount;
}
}
这样就完成了问题(10),但同时新增加了三个问题!
(11)Dollar与Franc之间的重复设计问题;
(12)普通判等;
(13)普通相乘;
第八章 再议众生平等(Equality for All:Redux)——解决判等问题
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
(11)Dollar与Franc之间的重复设计问题;
(12)普通判等;——解决问题
(13)普通相乘;
2、同步工程实践:
(1)抽取父类Money,使Dollar和Franc都继承Money;
(2)把子类公共代码抽取到父类;——在父类Money中声明amount为protected,以便子类能够看到。
(3)把equals()方法上移到父类中;
父类Money代码如下:
publicclassMoney{
protectedintamount=0;
publicbooleanequals(Objectobject){
Moneymoney=(Money)object;
returnamount==money.amount;
}
}
子类Franc代码如下:
publicclassFrancextendsMoney{
publicFranc(intamount){
this.amount=amount;
}
publicFranctimes(intmultiplier){
returnnewFranc(amount*multiplier);
}
}
子类Dollar代码如下:
publicclassDollarextendsMoney{
publicDollar(intamount){
this.amount=amount;
}
publicDollartimes(intmultiplier){
returnnewDollar(amount*multiplier);
}
}
测试代码不作任何变化:
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Dollarfive=newDollar(5);
assertEquals(newDollar(10),five.times(3));
}
publicvoidtestEquality(){
assertTrue(newDollar(5).equals(newDollar(5)));
assertFalse(newDollar(5).equals(newDollar(6)));
}
}
第九章 苹果和橘子(Apples and Oranges)——两个对象的判等问题(数值和类均相等时才相等)
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
(11)Dollar与Franc之间的重复设计问题;
(12)普通判等;
(13)普通相乘;
2、同步工程实践:
(1)进一步修改测试代码,比较Dollar和Franc两个对象
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Dollarfive=newDollar(5);
assertEquals(newDollar(10),five.times(3));
}
publicvoidtestEquality(){
assertTrue(newDollar(5).equals(newDollar(5)));
assertFalse(newDollar(5).equals(newDollar(6)));
assertTrue(newFranc(5).equals(newFranc(5)));
assertFalse(newFranc(5).equals(newFranc(6)));
assertFalse(newFranc(5).equals(newDollar(5)));
}
}
测试失败!——表明当前的对象比较还存在问题!
新引入问题:
(14)对象之间的判等;
(15)货币表示?
(2)继续修改equals()代码,并进行断点调试,结果如下:
publicclassMoney{
protectedintamount=0;
publicbooleanequals(Objectobject){
Moneymoney=(Money)object;
returnamount==money.amount
&&getClass().equals(money.getClass());
}
}

分析语句 assertFalse(newFranc(5).equals(newDollar(5))):
其中 newFranc(5).equals()中equals()调用继承自父类Money的方法,其中getClass()返回值为Franc实例的类型Franc;而参数中money.getClass()返回的是Dollar实例的类型类Dollar。
第十章 制造对象(Makin' Objects)——使用工厂方法制造对象
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
(11)Dollar与Franc之间的重复设计问题;
(12)普通判等;
(13)普通相乘;
(14)对象之间的判等;
(15)货币表示?
2、同步工程实践:
(1)主要是对两个子类中极为相似的times()函数进行修改
修改后的Money类:
publicabstractclassMoney{
protectedintamount=0;
publicbooleanequals(Objectobject){
Moneymoney=(Money)object;
returnamount==money.amount
&&getClass().equals(money.getClass());
}
publicstaticDollardollar(intamount){
returnnewDollar(amount);
}
publicstaticFrancfranc(intamount){
returnnewFranc(amount);
}
publicabstractMoneytimes(intmultiplier);
}
修改后的Dollar类和Franc类:
publicclassDollarextendsMoney{
publicDollar(intamount){
this.amount=amount;
}
publicMoneytimes(intmultiplier){
returnnewDollar(amount*multiplier);
}
}
publicclassFrancextendsMoney{
publicFranc(intamount){
this.amount=amount;
}
publicMoneytimes(intmultiplier){
returnnewFranc(amount*multiplier);
}
}
修改后的测试代码
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Moneyfive=Money.dollar(5);
assertEquals(Money.dollar(10),five.times(2));
assertEquals(Money.dollar(15),five.times(3));
}
publicvoidtestEquality(){
assertTrue(Money.dollar(5).equals(newDollar(5)));
assertFalse(Money.dollar(5).equals(newDollar(6)));
assertTrue(Money.franc(5).equals(newFranc(5)));
assertFalse(Money.franc(5).equals(newFranc(6)));
assertFalse(Money.franc(5).equals(Money.dollar(5)));
}
}
下一步消除times()的重复设计!
第十一章 我们所处的时代(Times we are live in)——消除times()重复设计!
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
(11)Dollar与Franc之间的重复设计问题;
(12)普通判等;
(13)普通相乘;
(14)对象之间的判等;
(15)货币表示?
2、同步工程实践:
(1)增加货币属性
publicabstractclassMoney{
protectedintamount=0;
protectedStringcurrancy;
publicMoney(intamount,Stringcurrancy){
this.amount=amount;
this.currancy=currancy;
}
publicstaticDollardollar(intamount){
returnnewDollar(amount,"USD");
}
publicstaticFrancfranc(intamount){
returnnewFranc(amount,"CHF");
}
publicabstractMoneytimes(intmultiplier);
publicbooleanequals(Objectobject){
Moneymoney=(Money)object;
returnamount==money.amount
&&getClass().equals(money.getClass());
}
publicStringcurrancy(){
returncurrancy;
}
}
publicclassFrancextendsMoney{
publicFranc(intamount,Stringcurrancy){
super(amount,currancy);
}
publicMoneytimes(intmultiplier){
returnMoney.franc(amount*multiplier);
}
}
publicclassDollarextendsMoney{
publicDollar(intamount,currancy);
}
publicMoneytimes(intmultiplier){
returnMoney.dollar(amount*multiplier);
}
}
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Moneyfive=Money.dollar(5);
assertEquals(Money.dollar(10),five.times(2));
assertEquals(Money.dollar(15),five.times(3));
}
publicvoidtestCurrancy(){
assertEquals("USD",Money.dollar(1).currancy());
assertEquals("CHF",Money.franc(1).currancy());
}
}
第十二章 有趣的Times方法(Interesting Times)——消除times()重复设计!
1、存在的问题:
(1)汇率转换问题,当汇率为2:1时,5美元 + 10法郎 = 10美元;
(2)5美元 * 2 = 10美元;
(3)将amount定义为私有;
(4)Dollar类有副作用吗?
(5)钱数为整数;
(6)实现equals()函数
(7)实现hashCode()函数
(8)与空对象判等;
(9)与非同类对象判等;
(10)5法郎 * 2 = 10法郎;
(11)Dollar与Franc之间的重复设计问题;
(12)普通判等;
(13)普通相乘;
(14)对象之间的判等;
(15)货币表示?
2、同步工程实践:
提取times方法父类中:
publicclassMoney{
protectedintamount=0;
protectedStringcurrancy;
publicMoney(intamount,Stringcurrancy){
this.amount=amount;
this.currancy=currancy;
}
publicstaticDollardollar(intamount){
returnnewDollar(amount,"USD");
}
publicstaticFrancfranc(intamount){
returnnewFranc(amount,"CHF");
}
publicMoneytimes(intmultiplier){
returnnewMoney(amount*multiplier,currancy);
}
publicbooleanequals(Objectobject){
Moneymoney=(Money)object;
returnamount==money.amount
&&this.currancy.equals(money.currancy());
}
publicStringcurrancy(){
returncurrancy;
}
}
publicclassFrancextendsMoney{
publicFranc(intamount,Stringcurrancy){
super(amount,currancy);
}
}
publicclassDollarextendsMoney{
publicDollar(intamount,currancy);
}
}
publicclasstestDollarextendsTestCase{
publicvoidtestMultiplication(){
Moneyfive=Money.dollar(5);
assertEquals(Money.dollar(10),five.times(2));
assertEquals(Money.dollar(15),five.times(3));
}
publicvoidtestCurrancy(){
assertEquals("USD",Money.dollar(1).currancy());
assertEquals("CHF",Money.franc(1).currancy());
}
}
测试通过!

猜你在找的设计模式相关文章