Title: Lesson Two: Encapsulation and Unit Testing
1Lesson Two Encapsulation and Unit Testing
2Process1. Encapsulate ALL class variables2.
Setup unit test program 3. Unit test4.
Functionally test5. Perform Refactorings
31. Encapsulate ALL class variables
- Write get and set methods for ALL class
variablesModify ALL references to class
variables to use get and set methods.Test
methods.
4Write getters and setters for all class variables
public int getComputerStatus ()
return computerStatus public Image
getUserImage ()return userImage public
boolean getFirst () return first public
Image getComputerImage () return
computerImage public void
setComputerStatus (int computerStatus)
this.computerStatus computerStatus
public void setUserImage (Image userImage)
this.userImage userImage public void
setFirst (boolean first) this.first first
public void setCommputerImage (Image
computerImage) this.computerImage
computerImage
5Perform Refactorings 1. Self encapsulating
field2. Encapsulate field3. Encapsulate
collection
6Self Encapsulating Field
Summary You are accessing a field directly,
but the coupling to the field is becoming
awkward. Create getting and setting methods for
fields and use ONLY those to access the field.
7Self Encapsulating Field Motivation Data
fields should always be declared as
private. Getter and Setter methods should be used
to access the data. Debate exist about using
getter and setter methods inside the class. I
recommend you use these at ALL times.
8Self Encapsulating Field Example class
IntRange private int _low, _high boolean
includes (int arg) return arg gt _low arg lt
_high void grow (int factor) _high
_high factor IntRange (int low, int high)
_low low _high high // end
IntRange
9Self Encapsulating Field Example class
IntRange private int _low, _high public
getLow() return _low public setLow (int
arg) _low arg public getHigh() return
_high public setHigh (int arg) _high
arg boolean includes (int arg) return arg
gt getLlow () arg lt getHigh() void grow
(int factor) getHigh() getHigh() factor
IntRange (int low, int high) _low
low _high high // end IntRange
Encapsulate and reference.
Leave initializations as direct.
10Self Encapsulating Field Mechanics create
a getter and setter method for the field find
references to field - replace with get and set
methods make field private compile and test
11Encapsulate Field
Summary There is a public field. Make it
private and provide accessors.
12Encapsulate Field Motivation Sharing data
reduces modularity of the program .
Encapsulation hides the data and adds accessors
to protect the data and program integrity.
13Encapsulate Field Example
public String _name private String
)name public String getName () return )name
public void setName (String arg) _name arg
Should be
14Encapsulate Field Mechanics create get
and set methods for the field find all clients
and change references declare field as
private compile and test.
15Encapsulate Collection
Summary A method returns a collection. Make
it return a read-only view and provide add/remove
methods.
16Encapsulate Collection Motivation A
collection needs the same modularization and
encapsulation that one class does. Add getter
and setter methods for the collection.
17Encapsulate Collection Example
class Course public course (String name,
boolean isAdvanced) public boolean
isAdvanced ( ) class Person
public Set getCourses() return _courses
public void setCourses (Set arg) _courses
arg private Set _courses
A person is taking a course
18Encapsulate Collection Example
Person kent new Person() Set s new
HashSet() s.add(new Course (Smalltalk
Programming, false)) s.add(new Course
(Appreciating Single Malts, true))
kent.setCourses(s) Assert.equals
(2,kent.getCourses().size()) Course refact
new Course (Refactoring, true)
kent.getCourses().add(refact)
kent.getCourses().add(new Course (Brutal
Sarcasm, false)) Assert.equals (4,
kent.getCourses().size())) kent.getCourses().r
emove (refact) Assert.equals
(3,kent.getCourses().size())
19Encapsulate Collection Example
Iterator iter person.getCourses().iterator(
) int Count 0 while (iter.hasNext((
Course each (Course) iter.next() if
(each.isAdvanced(( count // end while
A client that to know about courses might do this
20Encapsulate Collection Example
Class Person public void addCourse (Course
arg) _courses.add(arg) public void
removeCourse (Course arg) _courses.remove(arg)
private Set )courses new HashSet()
Create the modifiers for the collection
Initialize the field
21Encapsulate Collection Example
Class Person public void setCourses (Set
arg) Assert.isTrue()courses.isEmpty())
Iterator iter arg.iterator() while
(iter.hasNext()) addCourse ((Course)
iter.next())
Write the setter methods
22Encapsulate Collection Example
public void initialzeCourses (Set arg)
Assert.isTrue()courses.isEmpty()) Iterator
iter arg.iterator() while
(iter.hasNext()) addCourse ((Course)
iter.next()) public void initializeCourses
(Set arg) Assert.isTrue(_courses.isEmpty()
_courses.addAll(arg) // end initializeCourses
Rename the method for clarity
Initialize and remove loop
23Encapsulate Collection Example
Person kent new Person () Set a new
HashSet() s.add(new Course (Samlltalk
Programming, false)) s.add(new Course
(Appreciting Single Malts, true))
kent.initializeCourses(s) Person kent
new Person() kent.addCourse(new Course
(Samlltalk Programming, false))
kent.addCourse(new Course (Appreciating Single
Malts, true))
becomes
24Encapsulate Collection Example
kent.getCourses().add(new Course (Brutal
Sarcasm, false)) kent.addCourse(new Course
(Brutal Sarcasm, false)) public Set
getCourses() return Collections.unmodifiableSet
(_courses)
becomes
I can then check that it is not modified
25Encapsulate Collection Example
Iterator iter person.getCourses().iterator()
int count 0 while (iter.hasNext()
Course each (Course) iter.next() if
(each.isAdvanced()) count // end while
Now I can move the behavior to the class
This method is better placed in the person class
26Encapsulate Collection Example
class Person int numberOfAdvancedCourses()
Iterator iter getCourses().iterator()
int count 0 while (iter.hasNext()
Course each (Course) iter.next()
if (each.isAdvanced()) count //
end while // end numberOfAdvancedCourses
27Encapsulate Collection Example
Kent.getCourses().size()
Kent.numberOfCourses() Class Person
public int numberOfCourses() return
_courses.size()
Is more readable as
28 Mechanics Add and add and remove
method initialize the field to an empty
collection find callers of set method modify
or call find all users of getter and modify
collection modify getter to return a read-only
view find all users of getter move to
host change name of current getter compile and
test
Encapsulate Collection
29// GETS AND SETS ADDED TO CODE
public int getComputerStatus () return
computerStatus public Image getUserImage
()return userImage public boolean getFirst
() return first public Image
getComputerImage () return computerImage
public void setComputerStatus (int
computerStatus) this.computerStatus
computerStatus public void setUserImage
(Image userImage) this.userImage
userImage public void setFirst (boolean
first) this.first first public void
setCommputerImage (Image computerImage)
this.computerImage computerImage
30In this lesson, we do not make gets and sets for
arrays or other collections. That is handled
later. But for all primitive variables, and
class instance variables we must change EVERY
access to these variables to gets and sets. Many
people say that you dont have to do this inside
the class but it is simply a barrier to good
method and class partitioning so we will change
every one. The problem is that some of the
variables are used as parameters passed into
methods and this must be addressed properly for
good scoping of variables.
31//METHODS that need changes in their access to
variables int bestMove(int computerStatus, int
userStatus) has parameters making them
local variables scoping? ok boolean
legalUserMove(int canidateMove) boolean
legalComputerMove() int gameStatus(int
computerStatus, int userStatus) public void
paint(Graphics g) // paint the screen public
void mouseReleased(MouseEvent e)
32//METHODS that need changes in their access to
variables computerStatus userStatus 0
BECOMES setComputerStatus(0) setUserStatus(0)
if ((userStatus computerStatus)
ENDINGSTATE) BECOMES if ((getUserStatus()
getComputerStatus()) ENDINGSTATE)
computerImage getImage(getCodeBase(),
"oimage.gif") BECOMES setComputerImage(getImage(g
etCodeBase(), "oimage.gif"))
332. Setup Unit Test Program
- Either implement J or N unit testing in Java or C
sharp ORWrite your own unit testing
program. 1) Divide your program into two
programs a) One that executes b) One that
contains all methods etc. 2) Write a program
that uses your containing class methods
unit by unit for tests.
342. Setup Unit Test Program
Exec class
Your class
Makes an instance All code in constructor
needed To execute
352. Setup Unit Test Program
Your class
Method addit (int a, int b)int return a b
Your test class
Method addit (int a, int b)int int a 4
int b 5 int answer super (a,b) if
answer ltgt 9 print Error in addit print
expected, 9 print received, answer
362. Setup Unit Test Program
Exec class
Your test class
Makes an instance of the TEST CLASS Execute as
usual
372. Setup Unit Test Program
Copy your program and call it xxxxTest extending
your class Take out any GUI stuff (not this
test) Here we are testing methods. What else to
do??????
382. Setup Unit Test Program
Decide what you are going to test int
bestMove(int computerStatus, int userStatus)
boolean legalUserMove(int canidateMove)
boolean legalComputerMove() We will not test
since it is tested functionally public void
init() public void paint(Graphics g) //
paint the screen
392. Setup Unit Test Program
We do need to test public void mouseReleased(Mouse
Event e) However we will have to separate
the GUI from the domain functionality
402. Setup Unit Test Program
// user clicked applet // GUI code int x
e.getX() // get mouse x location int y
e.getY() // get mouse y location Needs to stay
in mouseReleased() since it is GUI
41// domain functionality and GUI switch
(gameStatus()) // determine status case
WIN case LOSE case STALEMATE
play(getCodeBase(), "audio/return.au")
computerStatus userStatus 0 if (first)
// reset first computerStatus 1 ltlt
(int)(Math.random() 9) // end if
first !first repaint() // GUI
controlling when to display // RED LINED code
NEEDS TO BE A METHOD TO TEST
42Make it a METHOD public void resetFirst()
if (getComputerFirst()) // reset who is
first setComputerStatus ( 1 ltlt
(int)(Math.random() 9)) // end if
setComputerFirst (!getComputerFirst())
// end resetStatus
43Call the METHOD Now this is all GUI code
switch (gameStatus()) // determine status
case WIN case LOSE case STALEMATE
play(getCodeBase(), "audio/return.au")
resetStatus() repaint() return //
end switch
44 3. Unit test program shown
in the next slides 4.
Functionally test program
45UNIT methods to test int bestMove(int
computerStatus, int userStatus) boolean
legalComputerMove() boolean legalUserMove(int
canidateMove) int gameStatus( ) public void
resetFirst()
46FIRST METHOD TO TEST int bestMove(int
computerStatus, int userStatus) //
bestMove TEST 1 // test if can find best
strategic move 4th position //
bestMove TEST 2 // test if can find next best
strategic move 0th // bestMove TEST 3
// test if can block win // bestMove
TEST 4 // test if can take win
47FIRST METHOD TO TEST -- WRITE THE bestMove
test int bestMove(int computerStatus, int
userStatus) public int bestMove (int
computerStatus, int userStatus, int correctMove )
int tempBestMove super.bestMove (
computerStatus, userStatus) if
(tempBestMove correctMove)
System.out.print (" good ") else
System.out.print ("NOT good ")
System.out.print (" tempBestMove "
tempBestMove) System.out.print ("
correctMove " correctMove)
System.out.println (" userStatus "
getUserStatus () ) return tempBestMove
// end best move
1
1
Add a variable of return type that is the CORRECT
return value
48FIRST METHOD TO TEST -- WRITE THE bestMove
test int bestMove(int computerStatus, int
userStatus) public int bestMove (int
computerStatus, int userStatus, int correctMove )
int tempBestMove super.bestMove (
computerStatus, userStatus) if
(tempBestMove correctMove)
System.out.print (" good ") else
System.out.print ("NOT good ")
System.out.print (" tempBestMove "
tempBestMove) System.out.print ("
correctMove " correctMove)
System.out.println (" userStatus "
getUserStatus () ) return tempBestMove
// end best move
2
2
Add a statement to call the super.xxxx method for
testing
49FIRST METHOD TO TEST -- WRITE THE bestMove
test int bestMove(int computerStatus, int
userStatus) public int bestMove (int
computerStatus, int userStatus, int correctMove )
int tempBestMove super.bestMove (
computerStatus, userStatus) if
(tempBestMove correctMove)
System.out.print (" good ") else
System.out.print ("NOT good ")
System.out.print (" tempBestMove "
tempBestMove) System.out.print ("
correctMove " correctMove)
System.out.println (" userStatus "
getUserStatus () ) return tempBestMove
// end best move
3
3
Add an IF statement to see if the returned value
is correct
50FIRST METHOD TO TEST -- WRITE THE bestMove test
method int bestMove(int computerStatus, int
userStatus) public int bestMove (int
computerStatus, int userStatus, int correctMove )
int tempBestMove super.bestMove (
computerStatus, userStatus) if
(tempBestMove correctMove)
System.out.print (" good ") else
System.out.print ("NOT good ")
System.out.print (" tempBestMove "
tempBestMove) System.out.print ("
correctMove " correctMove)
System.out.println (" userStatus "
getUserStatus () ) return tempBestMove
// end best move
4
4
I like to print out pertinent values to allow
easy debugging.
51FIRST METHOD TO TEST -- NOW write the tests int
bestMove(int computerStatus, int userStatus)
public void testBestMove ()
System.out.println (" ") System.out.println
("testBestMove") // bestMove TEST 1 //
test if can find best strategic move 4th
position bestMove (0, 0 ( 1 ltlt 1) (1
ltlt 8), 4) // bestMove TEST 2 // test if
can find next best strategic move 0th
bestMove (0, 0 ( 1 ltlt 4), 0) //
bestMove TEST 3 // test if can block win
bestMove (0, 0( 1 ltlt 3)( 1 ltlt 4), 5)
// TEST 4 // test if can take win
bestMove (0 ( 1 ltlt 6)( 1 ltlt 7), 0( 1 ltlt 3)( 1
ltlt 4), 8) // end testBestMove
52FIRST METHOD TO TEST -- NOW run the tests int
bestMove(int computerStatus, int userStatus)
Place the test calls in the main or paint
method of the sub class public void
paint(Graphics g) testBestMove ()
testLegalComputerMove()
testLegalUserMove() testGameStatus(
) bestMove Test 1 good temp 4 correct
4 user 258
53 // bestMove TEST 1 // test if can find best
strategic move bestMove (0, 0 ( 1
ltlt 1) (1 ltlt 8), 4) public int bestMove (int
computerStatus, int userStatus, int correctMove )
int tempBestMove super.bestMove (
computerStatus, userStatus) if
(tempBestMove correctMove)
System.out.print (" good ") else
System.out.print ("NOT good ")
System.out.print (" tempBestMove "
tempBestMove) System.out.print ("
correctMove " correctMove)
System.out.println (" userStatus "
getUserStatus () ) return tempBestMove
bestMove Test 1 good temp 4
correct 4 user 258 TEST 2, 3, 4 similar
54 boolean legalUserMove(int legalComputerMove, int
legalUserMove, int canidateMove, boolean
correctAns) boolean tempLegalUserMove
super.legalUserMove (computerStatus,
userStatus, canidateMove) if(tempLegalUserMove
correctAns ) System.out.print ("good ")
else System.out.print ("NOT good ")
System.out.print (" computer "
computerStatus) System.out.print ("
user " userStatus) System.out.print
(" canidate " canidateMove)
System.out.print ( " userMove "
tempLegalUserMove) System.out.println ("
correctAns " correctAns) return
tempLegalUserMove // end legalUserMove
55// legalUserMove TEST 1 // test if within range
of squares userStatus 0 ( 1 ltlt 0)
computerStatus 0 ( 1 ltlt 2)
legalUserMove (computerStatus, userStatus, 9,
false) // TEST 1 // legalUserMove TEST
2 // test if empty false // legalUserMove TEST
3 // test if empty true legalUserrMove Test
1 good computer 4 user 1 canidate
9
userMove false correctAns
false
56boolean legalComputerMove (int
computerStatus, int userStatus, boolean
correctAns) boolean tempLegalComputerMove
super.legalComputerMove (computerStatus,
userStatus) if(tempLegalComputerMove
correctAns) System.out.print ("good
") else System.out.print ("NOT good ")
System.out.print (" computer "
computerStatus) System.out.print (" user
" userStatus) System.out.print ("
computerMove " tempLegalComputerMove)
System.out.println (" correctAns "
correctAns) return tempLegalComputerMove
// end tryLegalComputerMove
57// legalComputerMove TEST 1 // test if ending
state userStatus 0 ( 1 ltlt 0) (1 ltlt
1) (1 ltlt 3) (1 ltlt 5) (1 ltlt 8)
computerStatus 0 ( 1 ltlt 2) (1 ltlt 4) (1 ltlt
6) (1 ltlt 7) legalComputerMove
(computerStatus, userStatus, false) //
TEST 1 // legalComputerMove TEST 2 // test if
NOT in ending state legalComputerMove Test
1 good computer 212 user 299
computerMove false
correctAns false
58 int gameStatus(int computerStatus, int
userStatus, int correctStatus) int
tempGameStatus super.gameStatus
(computerStatus, userStatus) if
(tempGameStatus correctStatus)
System.out.print ("good ") else
System.out.print ("NOT good ")
System.out.print (" computer "
computerStatus) System.out.print (" user
" userStatus) System.out.print ("
status " tempGameStatus)
System.out.println (" correctStatus "
correctStatus) return tempGameStatus
// end gameStatus
59 void testGameStatus() // gameStatus TEST 1
// test if WIN userStatus 0 ( 1 ltlt 0)
computerStatus 0 (1 ltlt 3) (1 ltlt
4) (1 ltlt 5) gameStatus
(computerStatus, userStatus, WIN) //
TEST 1 // gameStatus TEST 2 // test if LOSE //
gameStatus TEST 3 // test if STALEMATE //
gameStatus TEST 4 // test if CONTINUE testGameSta
tus Test 1 good computer 56 user 1
status 1 correctStatus 1
60 public boolean resetFirst (boolean
computerFirst, boolean correctFirst)
boolean tempResetFirst super.resetFirst
(computerFirst) if (tempResetFirst
correctFirst) System.out.print ("good ")
else System.out.print ("NOT good ")
System.out.print (" computer "
computerStatus) System.out.print ("
computerFirst " computerFirst)
System.out.print (" reset " tempResetFirst)
System.out.println (" correctFirst "
correctFirst) return tempResetFirst
// end resetFirst
61 public void testResetFirst () // TEST
1 resetFirst ( false, true) //
TEST 2 resetFirst ( true, false)
// end resetFirst testResetForst Test 1
good computerfirst false
reset
true correct true
62NOW we have defined our functional test and our
unit testing Other refactorings we do will be
tested each time to assure we do not loose
functionality or correctness in our program.