Test-driven development
41 of 133 
faster with the refactorings in the instance of time. If I go too fast, please tell me to 
slow down. Oh, wait, this is a book. Perhaps I just won’t speed up much.) 
Franc
Franc  
private
private String currency;
Franc(
int
int amount) { 
thiiss.amount 
=
 amount
;
currency 
=
currency 
=
 "CHF"
"CHF";;
String currency() { 
return currency;
return currency;
We can do the same with Dollar: 
Dollar
Dollar  
private
private String currency;
Dollar(
int
int amount) { 
thiiss.amount 
=
 amount
;
currency 
=
currency 
=
 "USD"
"USD";;
String currency() { 
return currency;
return currency;
Now we can push up the declaration of the variable and the implementation of 
currency(), since they are identical: 
Mone
Moneyy  
protected
protected String currency;
String currency() { 
return
return currency;
If we move the constant strings “USD” and “CHF” to the static factory methods, the 
two constructors will be identical and we can create a common implementation. 
First we’ll add a parameter to the constructor: 
Franc
Franc  
Franc(
int
int amount
,
 String currency
String currency) { 
thiiss.amount 
=
 amount
;
thiiss.
currency 
=
 "CHF";
This breaks the two callers of the constructor: 
Break a pdf into multiple files - Merge, append PDF files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provide C# Demo Codes for Merging and Appending PDF Document
append pdf files reader; reader merge pdf
Break a pdf into multiple files - VB.NET PDF File Merge Library: Merge, append PDF files in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET Guide and Sample Codes to Merge PDF Documents in .NET Project
asp.net merge pdf files; combine pdf online
Test-driven development
42 of 133 
Money
Money  
stat
ic
stat
ic Money franc(
int
int amount) { 
return
return nneww Franc(amount
,
 null
null
)
;
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Franc(amount * mul
t
iplier,
 null
null
)
;
Wait a minute! Why is Franc.times() calling the constructor instead of the factory 
method? Do we want to make this change now, or will we wait? The dogmatic answer 
is that we’ll wait, not interrupting what we’re doing. The answer in my practice is that 
I will entertain a brief interruption, but only a brief one, and I will never interrupt an 
interruption (rule thanks to Jim Coplien). To be realistic, we’ll fix times() before 
proceeding: 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return Money.
franc(amount * mul
t
iplier)
;
Now the factory method can pass “CHF”:  
Money
Money  
stat
ic
stat
ic Money franc(
int
int amount) { 
return
return nneww Franc(amount
,
 "CHF"
"CHF")
;
And finally we can assign the parameter to the instance variable: 
Franc
Franc  
Franc(
int
int amount
,
 String currency) { 
thiiss.amount 
=
 amount
;
thiiss.
currency 
=
 currency
currency;
I’m feeling defensive again about taking such teeny-tiny steps. Am I recommending 
that you actually work this way? No. I’m recommending that you be able to work this 
way. What I actually did just now was I worked in larger steps and made a stupid 
mistake half way through. I unwound a minute’s worth of changes, shifted to a lower 
gear, and did it over with little steps. I’m feeling better now, so we’ll see if we can 
make the analogous change to Dollar in one swell foop: 
C# PDF File Split Library: Split, seperate PDF into multiple files
SharePoint. C#.NET control for splitting PDF file into two or multiple files online. Support to break a large PDF file into smaller files.
add pdf together; add pdf files together online
VB.NET PDF File Split Library: Split, seperate PDF into multiple
Split PDF file into two or multiple files in ASP.NET webpage online. Support to break a large PDF file into smaller files in .NET WinForms.
add two pdf files together; c# merge pdf
Test-driven development
43 of 133 
Money
Money  
stat
ic
stat
ic Money dollar(
int
int amount) { 
return
return nneww Dollar(amount
,
 "USD"
"USD")
;
Dollar
Dollar  
Dollar(
int
int amount
,
 String currency) { 
thiiss.amount 
=
 amount
;
thiiss.
currency 
=
 currency
currency;
Money t
imes(
int
int mul
t
iplier) { 
return
return Money.dollar(amount * mul
t
iplier)
;
Money.dollar(amount * mul
t
iplier)
;
And it worked first time. Whew! 
This is the kind of tuning you will be doing constantly with TDD. Are the teeny-tiny 
steps feeling restrictive? Take bigger steps. Are you feeling a little unsure? Take 
smaller steps. TDD is a steering process— a little this way, a little that way. There is 
not right step size, now and forever. 
The two constructors are now identical, so we can push up the implementation: 
C# PDF Page Insert Library: insert pages into PDF file in C#.net
Offer PDF page break inserting function. the ability to inserting a new PDF page into existing PDF processing functions, such as how to merge PDF document files
combine pdf files; pdf combine pages
VB.NET PDF Page Insert Library: insert pages into PDF file in vb.
Able to add and insert one or multiple pages to existing adobe Offer PDF page break inserting function. DLLs for Adding Page into PDF Document in VB.NET Class.
c# merge pdf pages; pdf merge documents
Test-driven development
44 of 133 
Money
Money  
Money(
int
int amount
,
 String currency) { 
thiiss.amount 
=
 amount
;
thiiss.
currency 
=
 currency;
Franc
Franc  
Franc(
int
int amount
,
 String currency) { 
super(amount
,
 currency)
;
super(amount
,
 currency)
;
Dollar
Dollar  
Dollar(
int
int amount
,
 String currency) { 
super(amount
,
 currency)
;
super(amount
,
 currency)
;
T
o do
:
$5 + 
10
CHF = $
10
i
f CHF
:
USD 
is
2
:1
$5 
*
2 = $
10
Make “amoun
t
” pr
iv
a
t
e
Do
ll
ar 
si
de
-
effec
ts
?
Money round
i
ng? 
Equa
ls
()
Ha
s
hCode() 
Equa
l
nu
ll
Equa
l
ob
j
ec
t
5 CHF 
*
2 = 
10
CHF
Do
ll
ar/Franc dup
li
ca
ti
on 
Common equa
ls
Common 
ti
me
s
Franc
s
!
= Do
ll
ar
s
Currency?
De
l
e
t
t
e
st
FrancMu
lti
p
li
ca
ti
on? 
We’re almost ready to push up the implementation of times() and eliminate the 
subclasses, but first, to review, we: 
· Were a little stuck on big design ideas, so we worked on something small we 
noticed earlier 
· Reconciled the two constructors by moving the variation to the caller (the 
factory method) 
· Interrupted a refactoring for a little twist (using the factory method in times()) 
· Repeated an analogous refactoring (doing to Dollar what we just did to Franc) 
in one big step 
· Pushed up the identical constructors 
Test-driven development
45 of 133 
The Root of all Evil 
When we are done with this chapter we will have a single class to represent Money. 
The two implementations of times() are close, but not identical. 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return Money.
franc(amount * mul
t
iplier)
;
Doollarr  
Money t
imes(
int
int mul
t
iplier) { 
return
return Money.dollar(amount * mul
t
iplier)
;
There’s not an obvious way to make them identical. Sometimes you have to go 
backwards to go forwards, a little like a Rubik’s Cube. What happens if we inline the 
factory methods? (I know, I know, we just called the factory method for the first time 
just one chapter ago. Frustrating, isn’t it?) 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Franc(amount * mul
t
iplier,
 "CHF")
;
Dollar
Dollar  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Dollar(amount * mul
t
iplier,
 "USD")
;
In Franc, though, we know that the currency instance variable is always “CHF”, so we 
can write: 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Franc(amount * mul
t
iplier,
 currency
currency)
;
That works. The same trick words in Dollar: 
Dollar
Dollar  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Dollar(amount * mul
t
iplier,
 currency
currency)
;
We’re almost there. Does it really matter whether we have a Franc or a Money? We 
could carefully reason about this given our knowledge of the system. However, we 
have clean code and we have tests that give us confidence. Rather than apply minutes 
of suspect reasoning, we can just ask the computer by making the change and running 
the tests. In teaching TDD I see this situation all the time— excellent programmers 
spending 5-10 minutes reasoning about a question that can be answered by the 
computer in 15 seconds. Without the tests you have no choice, you have to reason. 
Test-driven development
46 of 133 
With the tests you can decide whether an experiment would answer the question 
faster. Sometimes you should just ask the computer. 
To run our experiment we change Franc.times() to return a Money: 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Money
Money(amount * mul
t
iplier,
 currency)
;
The compiler tells us that Money must be a concrete class: 
Money
Money  
class
class Money  
Money t
imes(
int
int amount) { 
return
return null
null;
And we get a red bar. The error message says, “expected:<Money.Franc@31aebf> but 
was: <Money.Money@478a43>”. Not as helpful as we would perhaps like. We can 
define toString() to give us a better error message: 
Money
Money  
public
public String toString() { 
return
return amount 
+
 " " 
+
 currency;
Whoa! Code without a test? Can you do that? We could certainly have written a test 
for toString() before we coded it. However: 
· We are about to see the results on the screen 
· Since toString() is only used for debug output, the risk of it failing is low 
· We already have a red bar, and we’d prefer not to write a test when we have a 
red bar 
Exception noted. 
Now the error message says: “expected:<10 CHF> but was:<10 CHF> ”. That’s a little 
better, but still confusing. We got the right data in the answer, but the class was 
wrong— Money instead of Franc. The problem is in our implementation of equals(): 
Money
Money  
public
public boolean
boolean equals(Object object) { 
Money money 
=
 (Money) object
;
return
return amount 
==
 money.amount && getClass()
.equals(money.getClass())
;
We really should be checking to see that the currencies are the same, not that the 
classes are the same. 
We’d prefer not to write a test when we have a red bar. However, we are about to 
change real model code, and we can’t change model code without a test. The 
conservative course is to back out the change that caused the red bar so we’re back to 
Test-driven development
47 of 133 
green. Then we can change the test for equals(), fix the implementation, and re-try the 
original change. 
This time, we’ll be conservative (sometimes I plough ahead and write a test on a red, 
but not while the children are awake.) 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Franc
Franc(amount * mul
t
iplier,
 currency)
;
That gets us back to green. The situation that we had was a Franc(10, “CHF”) and a 
Money(10, “CHF”) that were reported to be not equal, even though we would like 
them to be equal. We can use exactly this for our test: 
public
public voidd test
DifferentClassEquali
ty() { 
assert
True(nneeww Money(10
,
 "CHF")
.equals(neww Franc(10
,
 "CHF")))
;
It fails, as expected. The equals() code should compare currencies, not classes: 
Money
Money  
public
public boolean
boolean equals(Object object) { 
Money money 
=
 (Money) object
;
return
return amount 
==
 money.amount && currenc
currency()
.equals(money.
currency()
y()
.equals(money.
currency())
;
Now we can return a Money from Franc.times() and still pass the tests: 
Franc
Franc  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Money(amount * mul
t
iplier,
 currency)
;
Will the same will work for Dollar.times()? 
Dollar
Dollar  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Money
Money(amount * mul
t
iplier,
 currency)
;
Yes! Now the two implementations are identical, so we can push them up. 
Test-driven development
48 of 133 
Money
Money  
Money t
imes(
int
int mul
t
iplier) { 
return
return nneww Money(amount * mul
t
iplier,
 currency)
;
T
o do
:
$5 + 
10
CHF = $
10
i
f CHF
:
USD 
is
2
:1
$5 
*
2 = $
10
Make “amoun
t
” pr
iv
a
t
e
Do
ll
ar 
si
de
-
effec
ts
?
Money round
i
ng? 
Equa
ls
()
Ha
s
hCode() 
Equa
l
nu
ll
Equa
l
ob
j
ec
t
5 CHF 
*
2 = 
10
CHF
Do
ll
ar/Franc dup
li
ca
ti
on 
Common equa
ls
Common 
ti
me
s
Franc
s
!
= Do
ll
ar
s
Currency?
De
l
e
t
t
e
st
FrancMu
lti
p
li
ca
ti
on? 
The two subclasses have only their constructors, so we can replace references to the 
subclasses by references to the superclass without changing the meaning of the code. 
First Franc: 
Franc
Franc  
stat
ic
stat
ic Money franc(
int
int amount) { 
return
return nneww Mone
Moneyy(amount
,
 "CHF")
;
Then Dollar: 
Dollar
Dollar  
stat
ic
stat
ic Money dollar(
int
int amount) { 
return
return nneww Money
Money(amount
,
 "USD")
;
Since there are no references to Dollar, we can delete it. Franc still has one reference, 
in the test we just wrote. Looking at the equality test: 
public void testEquality() { 
assertTrue(Money.dollar(5).equals(Money.dollar(5))); 
assertFalse(Money.dollar(5).equals(Money.dollar(6))); 
assertTrue(Money.franc(5).equals(Money.franc(5))); 
assertFalse(Money.franc(5).equals(Money.franc(6))); 
assertFalse(Money.franc(5).equals(Money.dollar(5))); 
it looks like we have the cases for equality well covered, too well covered, actually. 
We can delete the third and fourth assertions since they duplicate the exercise of the 
first and second assertions: 
public void testEquality() { 
assertTrue(Money.dollar(5).equals(Money.dollar(5))); 
assertFalse(Money.dollar(5).equals(Money.dollar(6))); 
assertFalse(Money.franc(5).equals(Money.dollar(5))); 
Test-driven development
49 of 133 
The test we wrote forcing us to compare currencies instead of classes only makes 
sense if there are multiple classes. Since we are trying to eliminate the Franc class, a 
test to ensure that the system works if there is a Franc class is a burden, not a help. 
Away testDifferentClassEquality() goes, and Franc goes with it. 
T
o do
:
$5 + 
10
CHF = $
10
i
f CHF
:
USD 
is
2
:1
$5 
*
2 = $
10
Make “amoun
t
” pr
iv
a
t
e
Do
ll
ar 
si
de
-
effec
ts
?
Money round
i
ng? 
Equa
ls
()
Ha
s
hCode() 
Equa
l
nu
ll
Equa
l
ob
j
ec
t
5 CHF 
*
2 = 
10
CHF
Do
ll
ar/Franc dup
li
ca
ti
on
Common equa
ls
Common 
ti
me
s
Franc
s
!
= Do
ll
a
r
s
Currency?
De
l
e
t
t
e
st
FrancMu
lti
p
li
ca
ti
on? 
Similarly, there are separate tests for dollar and franc multiplication. Looking at the 
code, we can see there is no difference in the logic at the moment based on the 
currency (there was a difference when there were two classes). We can delete 
testFrancMultiplication() without losing any confidence in the behavior of the system. 
T
o do
:
$5 + 
10
CHF = $
10
i
f CHF
:
USD 
is
2
:1
$5 
*
2 = $
10
Make “amoun
t
” pr
iv
a
t
e
Do
ll
ar 
si
de
-
effec
ts
?
Money round
i
ng? 
Equa
ls
()
Ha
s
hCode() 
Equa
l
nu
ll
Equa
l
ob
j
ec
t
5 CHF 
*
2 = 
10
CHF
Do
ll
ar/Franc dup
li
ca
ti
on
Common equa
ls
Common 
ti
me
s
Franc
s
!
= Do
ll
ar
s
Currency?
De
l
e
t
t
e
st
FrancMu
lti
p
li
ca
ti
on?
Multiplication in place, we are ready to tackle addition. First, to review, we: 
· Reconciled two methods (times()) by first inlining the methods they called and 
then replacing constants with variables 
· Wrote a toString() without a test just to help us debug 
· Tried a change (returning Money instead of Franc) and let the tests tell us 
whether it worked 
Test-driven development
50 of 133 
· Backed out an experiment and wrote another test. Making the test work made 
the experiment work. 
· Finished gutting subclasses and deleted them 
· Eliminated tests that made sense with the old code structure but were 
redundant with the new code structure 
Documents you may be interested
Documents you may be interested