refactoring classes lesson six: classes. refactoring classes class decomposition is difficult....

72
Refactoring Classes Lesson Six: Classes

Upload: gwen-barnett

Post on 17-Jan-2016

256 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Lesson Six: Classes

Page 2: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal] Data Driven Design[Mellor] State Driven Design[Schlaer] Responsibility Driven Design[Wirths-Brock] Discovery Driven Design [Norththrop] Framework Driven Design etc.

Page 3: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Learning objective – have “good” classes which are reusable and easily maintained.

Page 4: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

We will use an approach which depends on clustering of methods, variables, and constants reside defined by McFadden. It is a data driven approach.

Page 5: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Kind TypeVariables and Constants METHODS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

init

de

stro

y

dra

wG

rid

dra

wIm

ag

es

squ

are

Occ

up

ied

pa

int

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

use

Re

lea

sed

const int NINE-SHIFTING-BITSconst int ENDINGSTATE r r rconst int LOSE r r rconst int CONTINUE r r rconst int STALEMATE r r rconst int WIN r r rconst int NUMBER_OF_COLUMNS r r rconst int NUMBER_OF_ROWS r r rconst int FIRST_CELL r r rconst int LAST_CELL r r r

?? ??

SOME RED FLAGSSOME CLUSTERS

CONSTANTS

Page 6: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

VARIABLES

Kind Type Variables and Constants METHODS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

init

de

stro

y

dra

wG

rid

dra

wIm

ag

es

squ

are

Occ

up

ied

pa

int

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

use

Re

lea

sed

var int computerStatus p p p p p g s s s,g gvar int userStatus p p p p p p g s p s,gvar boolean computerFirst g svar Image computerImage s gvar Image userImage s gvar arrayint winningState[] u r r r

?? OK ??

Page 7: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

METHODS

Kind Type Variables, Constants, Methods METHODS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

init

de

stro

y

dra

wG

rid

dra

wIm

ag

es

squ

are

Occ

up

ied

pa

int

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

use

Re

lea

sed

ge

tUse

rMo

veS

tatu

s

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r rmethod void initmethod void destroymethod void drawGrid rmethod void drawImages rmethod boolean squareOccupied rmethod void paintmethod void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r rmethod void moveComputer rmethod void mouseReleased

Page 8: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

It is clear we need a GUI class that is separate from the domain of the game. This is a standard factorization and part of an architectural pattern called MVC (model view controller). We should have done this already in the previous lecture.

So I copy my class into a class called Domain and extract out from the TTT class all but the GUI related statements.

Page 9: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public class TTTV61 extends Applet implements MouseListener {

// CONSTANTS static final int NUMBER_OF_COLUMNS = 3; static final int NUMBER_OF_ROWS = 3; // VARIABLES private Domain myDomain; // THIS IS ADDED private Image userImage; // user image private Image computerImage; // computer image

These variables belong with the GUI class(es).

Page 10: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

// GETS AND SETS public Image getUserImage (){return userImage;} public Image getComputerImage () { return computerImage;} public void setUserImage (Image userImage) { this.userImage = userImage;} public void setComputerImage (Image computerImage) { this.computerImage = computerImage; }

These methods also belong with the GUI class(es).

Page 11: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

//METHODS

public void init() { // initialize applet, load images, add listener setComputerImage(getImage(getCodeBase(), "oimage.gif")); setUserImage(getImage(getCodeBase(), "ximage.gif")); addMouseListener(this); myDomain = new Domain (); // ADDED } // end init

public void destroy() { removeMouseListener(this); } // end destroy

This method belongs to the commanding GUI class.

Page 12: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void drawGrid(Graphics g, Dimension d, int xoff, int yoff){ g.drawLine(xoff, 0, xoff, d.height); // draw first horizontal line g.drawLine(2*xoff, 0, 2*xoff, d.height); // draw second horizontal line g.drawLine(0, yoff, d.width, yoff); // draw first verticle line g.drawLine(0, 2*yoff, d.width, 2*yoff); // draw second verticle line } // end drawGrid

This method also belongs with the GUI class(es).

Page 13: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void drawImages(Graphics g, Dimension d, int xoff, int yoff){ int i = 0; for (int row = 0 ; row < NUMBER_OF_ROWS ; row++) { // draw computer and user images

for (int col = 0 ; col < NUMBER_OF_COLUMNS ; col++, i++) { int cs = myDomain.getComputerStatus();// THESE STATEMENTS CHANGED and TWO new methods in mydomain if (myDomain.computerOccupiesSquare (i)) {

g.drawImage(getComputerImage(), col*xoff + 1, row*yoff + 1, this); } else if (myDomain.userOccupiesSquare ( i)) {

g.drawImage(getUserImage(), col*xoff + 1, row*yoff + 1, this); } // end if }// end for

} // end for } // end draw Images

Again this method belong with the GUI class(es).

Page 14: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void paint(Graphics g) { // paint the screen

Dimension d = getSize(); g.setColor(Color.black);

int xoff = d.width / NUMBER_OF_ROWS; // compute x offsets int yoff = d.height / NUMBER_OF_COLUMNS; // compute y offsets

drawGrid (g, d, xoff, yoff); drawImages (g, d, xoff, yoff); } // end paint

This method belongs to the commanding GUI class.

Page 15: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void mouseReleased(MouseEvent e) { // user clicked applet int x = e.getX(); // get mouse x location int y = e.getY(); // get mouse y location Dimension d = getSize(); int col = (x * NUMBER_OF_COLUMNS) / d.width; // determine the column int row = (y * NUMBER_OF_ROWS) / d.height; // determine the row

if (gameOver (gameStatus(getComputerStatus(), getUserStatus()))) { resetGame(); repaint(); return; } // end if

Here there are methods and statements that are domain in nature.

For example the gameOver has to do with the domain of the game not the GUI. We need to extract out some of these methods from the GUI..

Page 16: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

int canidateMove = col + row * 3; if (legalUserMove(getComputerStatus(), getUserStatus(), canidateMove)) { repaint(); int status = getUserMoveStatus (canidateMove);

if (status == CONTINUE) { if (legalComputerMove(getComputerStatus(), getUserStatus())) { repaint(); moveComputer(getUserStatus());

} else { play(getCodeBase(), "audio/beep.au"); } // end else

} else { postGameStatus (status); } // end else } else { // not legal user move play(getCodeBase(), "audio/beep.au"); }// end else

} // end mouseReleased

All of these statements are domain in nature.

They need to be extracted in a method so they can be extracted to another class – The domain class.

Page 17: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void mouseReleased(MouseEvent e) { // user clicked applet int x = e.getX(); // get mouse x location int y = e.getY(); // get mouse y location Dimension d = getSize(); int col = (x * NUMBER_OF_COLUMNS) / d.width; // determine the column int row = (y * NUMBER_OF_ROWS) / d.height; // determine the row

// THIS CODE ADDED WITH ALL THE DOMAIN STATEMENTS EXTRACTED// NOTE: the this is passed to allow for repainting by the non applet myDomain.playGame(row,col, this); } // end mouseReleased

THUS, we extract the previous code into ONE method called playGame. Now mouseRelease is now only doing things associated with the GUI and calling a method for domain activity. No domain statements are included in the GUI, only calls to the DOMAIN class(es).

Page 18: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public class TTTV61 extends Applet implements MouseListener { // CONSTANTS static final int NUMBER_OF_COLUMNS = 3; static final int NUMBER_OF_ROWS = 3; // VARIABLES private Domain myDomain; private Image userImage; // user image private Image computerImage; // computer image

// GETS AND SETS public Image getUserImage (){return userImage;} public Image getComputerImage () { return computerImage;} public void setUserImage (Image userImage) { this.userImage = userImage;} public void setComputerImage (Image computerImage) { this.computerImage = computerImage; }

Here is the GUI class after all methods have been extracted that belong to the DOMAIN.

I HAVE TO ADD a variable for the domain class DOMAIN.

Page 19: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

//METHODS

public void init() { // initialize applet, load images, add listener setComputerImage(getImage(getCodeBase(), "oimage.gif")); setUserImage(getImage(getCodeBase(), "ximage.gif")); addMouseListener(this); myDomain = new Domain (); } // end init

public void destroy() { removeMouseListener(this); } // end destroy

WE keep the init and destroy methods in the GUI.

Here I make an instance of the new class called DOMAIN.

Page 20: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void drawGrid(Graphics g, Dimension d, int xoff, int yoff){ g.drawLine(xoff, 0, xoff, d.height); // draw first horizontal line g.drawLine(2*xoff, 0, 2*xoff, d.height); // draw second horizontal line g.drawLine(0, yoff, d.width, yoff); // draw first verticle line g.drawLine(0, 2*yoff, d.width, 2*yoff); // draw second verticle line } // end drawGrid

WE keep the drawGrid method in the GUI.

Page 21: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void drawImages(Graphics g, Dimension d, int xoff, int yoff){ int i = 0; // draw computer and user images for (int row = 0 ; row < NUMBER_OF_ROWS ; row++) {

for (int col = 0 ; col < NUMBER_OF_COLUMNS ; col++, i++) { int cs = myDomain.getComputerStatus(); if (myDomain.computerOccupiesSquare(i)) {

g.drawImage(getComputerImage(), col*xoff + 1, row*yoff + 1, this); } else if (myDomain.userOccupiesSquare(i)) {

g.drawImage(getUserImage(), col*xoff + 1, row*yoff + 1, this); } // end if }// end for

} // end for } // end draw Images

WE keep the drawImages method in the GUI.

Note the references to the DOMAIN class.

Page 22: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void paint(Graphics g) { // paint the screen

Dimension d = getSize(); g.setColor(Color.black);

int xoff = d.width / NUMBER_OF_ROWS; // compute x offsets int yoff = d.height / NUMBER_OF_COLUMNS; // compute y offsets

drawGrid (g, d, xoff, yoff); drawImages (g, d, xoff, yoff); } // end paint

WE keep the paint method in the GUI and it uses other GUI methods.

Page 23: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void mouseReleased(MouseEvent e) { // user clicked applet

int x = e.getX(); // get mouse x location int y = e.getY(); // get mouse y location

Dimension d = getSize();

int col = (x * NUMBER_OF_COLUMNS) / d.width; // determine the column int row = (y * NUMBER_OF_ROWS) / d.height; // determine the row

myDomain.playGame(row,col, this);

} // end mouseReleased

WE keep the mouseReleased method in the GUI.

It calls the playGame method in the DOMAIN class.

Page 24: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void mousePressed(MouseEvent e) { }

public void mouseClicked(MouseEvent e) { }

public void mouseEntered(MouseEvent e) { }

public void mouseExited(MouseEvent e) { }

public String getAppletInfo() {return "TicTacToe by Arthur van Hoff"; }} // end TTT

WE keep the these methods in the GUI.

Page 25: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now we need to look at the domain class because it currently has a hodge podge of statements and methods that may need more class refactoring.

Next few slides show the resulting DOMAIN class.

Page 26: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

import java.applet.*;

public class Domain { // CONSTANTS static final int NINE_SHIFTING_BITS = 9; static final int ENDINGSTATE = (1 << NINE_SHIFTING_BITS) - 1; static final int LOSE = 2; // status for user wins static final int CONTINUE = 0; // OLD OK status for game continues static final int STALEMATE = 3; // status for a tie static final int WIN = 1; // status for computer wins static final int FIRST_CELL = 0; // first cell at row 1 col 1 static final int LAST_CELL = 8; // last cell at row 3, col 3

Page 27: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

// VARIABLES

private int computerStatus; ; // computer bitmask denotes squares occupied private boolean computerFirst = true; // who goes first next game private int userStatus; // user bitmask denotes user squares occupied private static boolean winningState[] = new boolean[1 << 9]; // winning states

private Applet myApplet;

WE need to declare the myApplet here so we can call repaint when we need to in the movment of the TTT tokens.

Page 28: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

private static void setWinningState(int winState) { // mark squares as true win for (int i = 0 ; i < ENDINGSTATE ; i++) { if ((i & winState) == winState) {winningState[i] = true; } } // end for } // end isWon static { // initialize winning squares by shifting a one n bits setWinningState((1 << 0) | (1 << 1) | (1 << 2)); // row one 000 000 111 setWinningState((1 << 3) | (1 << 4) | (1 << 5)); // row two 000 111 000 setWinningState((1 << 6) | (1 << 7) | (1 << 8)); // row three 111 000 000 setWinningState((1 << 0) | (1 << 3) | (1 << 6)); // col one 100 100 100 setWinningState((1 << 1) | (1 << 4) | (1 << 7)); // col two 010 010 010 setWinningState((1 << 2) | (1 << 5) | (1 << 8)); // col three 001 001 001 setWinningState((1 << 0) | (1 << 4) | (1 << 8)); // dia right 100 010 001 setWinningState((1 << 2) | (1 << 4) | (1 << 6)); // dia left 001 010 100 } // end static

Page 29: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public int getComputerStatus () { return computerStatus; } public boolean getComputerFirst () { return computerFirst; } public int getUserStatus () { return userStatus; } public void setComputerStatus (int computerStatus) { this.computerStatus = computerStatus; } public void setComputerFirst (boolean computerFirst) { this.computerFirst = computerFirst; } public void setUserStatus (int userStatus) { this.userStatus = userStatus; }

public void setMyApplet (Applet myApplet) { this.myApplet = myApplet;}

WE need a setMyApplet method to set the class variable for use in many methods. Remember it was a parameter called by playGame in the GUI class.

Page 30: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

//METHODSpublic void Domain () { } NEW CONSTRUCTOR

public void playGame(int row, int col,Applet myApplet) { setMyApplet (myApplet); if (gameOver (gameStatus(getComputerStatus(), getUserStatus()))) { resetGame(); myApplet.repaint(); // NOTE REFERENCE return; } // end if

WE NEED a CONSTRUCTOR method.

Note the reference to myApplet.repaint which allows you to redraw the images after a move has been made.

Page 31: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

// playGame CONTINUED int canidateMove = col + row * 3;

if (legalUserMove(getComputerStatus(), getUserStatus(), canidateMove)) { makeMoves( canidateMove);

} else { // not legal user move myApplet.play(myApplet.getCodeBase(), "audio/beep.au"); }// end else } // end playGame

Page 32: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void continuePlaying ( ) { if (legalComputerMove(getComputerStatus(), getUserStatus())) { myApplet.repaint(); moveComputer(getUserStatus()); postGameStatus(gameStatus(getComputerStatus(), getUserStatus())); } else { myApplet.play(myApplet.getCodeBase(), "audio/beep.au"); } // end else } // end continueGame

public void makeMoves (int canidateMove) { myApplet.repaint(); moveUser(canidateMove); int status = gameStatus(getComputerStatus(), getUserStatus()); if (status == CONTINUE) { continuePlaying(); } else { postGameStatus (status); } // end else } // end makeMoves

NEW METHODS as a further refactoring to make methods functional.

Page 33: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public boolean cellEmpty(int computerStatus,int potentialComputerMove,int userStatus) { return ((computerStatus & (1 << potentialComputerMove)) == 0) && ((userStatus & (1 << potentialComputerMove)) == 0); } // end cellEmpty

public boolean userWins (int potentialComputerStatus, int userStatus) { for (int userMove = FIRST_CELL ; userMove <= LAST_CELL ; userMove++) { // for square = 0 to < 9 if (cellEmpty (potentialComputerStatus, userMove, userStatus)) { int potentialUserStatus = userStatus | (1 << userMove);

if (winningState[potentialUserStatus]) { // user wins, take another return true; } // end if won

} // end if cellEmpty } // end for return false; } // end checkIfUserWon

Page 34: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public int bestMove(int computerStatus, int userStatus) { // compute best move int mostStrategicMove[] = {4,0,2,6,8,1,3,5,7};// square order of importance int bestMoveNotFound = -1; int bestmove = bestMoveNotFound;

Page 35: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

loop: for (int i = FIRST_CELL ; i <= LAST_CELL ; i++) { int potentialComputerMove = mostStrategicMove[i]; if (cellEmpty (computerStatus, potentialComputerMove, userStatus)) { int potentialComputerStatus = computerStatus | (1 << potentialComputerMove); if (winningState[potentialComputerStatus]) { // computer wins, take it!

return potentialComputerMove;} /// end if (not user taken ) && ( not computer taken )

if (userWins (potentialComputerStatus, userStatus)) { continue loop;} if (bestmove == bestMoveNotFound) { // neither can win, move will do bestmove = potentialComputerMove; } // end if } // end if && } // end for

Page 36: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

if (bestmove != bestMoveNotFound) { // if no move found return the best one return bestmove;

} // end if bestmove

// no great move, try first one open for (int anyMove = FIRST_CELL ; anyMove <= LAST_CELL ; anyMove++) { int firstAvailableComputerMove = mostStrategicMove[anyMove]; if (cellEmpty (computerStatus, firstAvailableComputerMove, userStatus)) { return firstAvailableComputerMove; } // end if && } // end for return bestMoveNotFound; // return no more moves } // end best move

Page 37: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public boolean legalUserMove(int computerStatus, int userStatus, int canidateMove) { if ((canidateMove < FIRST_CELL) || (canidateMove > LAST_CELL)) { return false; } // end if if (squareOccupied (canidateMove, userStatus | computerStatus)) {

return false; } // end if return true; } // end legalUserMove

public boolean legalComputerMove(int computerStatus, int userStatus) { if ((userStatus | computerStatus) == ENDINGSTATE) { return false; } // end if return true;} // end legalComputerMove

Page 38: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Public int gameStatus(int computerStatus, int userStatus ) { // if (win, loose, tie) if (winningState [computerStatus]) { return WIN; } // end if if (winningState [userStatus]) { return LOSE; } // end if if ((userStatus | computerStatus) == ENDINGSTATE) { return STALEMATE; } // end if return CONTINUE; } // end gameStatus public boolean squareOccupied (int i, int playerStatus) { return (( playerStatus & (1 << i)) != 0); } // end squareOccupied

Page 39: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void playComputerIfFirst ( ) { if (getComputerFirst()) {setComputerStatus ( 1 << (int)(Math.random() * 9)); }} // end playcomputerIfFirst

public void resetGame () { setComputerStatus(0); setUserStatus(0); playComputerIfFirst (); setComputerFirst (!getComputerFirst()); } // end resetGame

Page 40: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public boolean gameOver(int status) { // check if over after computer move switch (status) {

case WIN:case LOSE:case STALEMATE:

return true; default:

return false; } // end switch } // end gameOver

Page 41: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void postGameStatus (int status) { switch (status) { case WIN: System.out.println ("I win ");

break; case LOSE: System.out.println ("You win "); break; case STALEMATE:

System.out.println ("No Winner "); break; default:

} // end switch } // end checkGameStatus

Page 42: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

public void moveComputer( int userStatus) { setComputerStatus (getComputerStatus() | 1 << bestMove(getComputerStatus(), userStatus)); } // end computerMove public void moveUser (int canidateMove) { setUserStatus (getUserStatus ( ) | 1 << canidateMove); } // end moveUser

Page 43: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

For EACH variable 1. Find the set method(s) for that VARIABLE. 2. Determine the SET of methods that use the set methods.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

bes

tMo

ve

leg

alU

serM

ove

leg

alC

om

pute

rMo

ve

gam

eS

tatu

s

pla

yCo

mpu

terI

fFirs

t

rese

tGa

me

gam

eO

ver

pos

tGa

meS

tatu

s

mo

veC

om

pu

ter

get

Use

rMo

veS

tatu

s

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

upie

d

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod int getUserMoveStatus rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean spaceOccupied r rmethod boolean continuePlayingmethod void constructor

var int computerStatus p p p p p s s s,g g g pi gvar int userStatus p p p p p p s p g,s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r rvar Applet myApplet p

Page 44: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

3. For each method in the SET (set method callers)4. Determine the variables referenced and set by each

method.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

bes

tMo

ve

leg

alU

serM

ove

leg

alC

om

pute

rMo

ve

gam

eS

tatu

s

pla

yCo

mpu

terI

fFirs

t

rese

tGa

me

gam

eO

ver

pos

tGa

meS

tatu

s

mo

veC

om

pu

ter

get

Use

rMo

veS

tatu

s

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

upie

d

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod int getUserMoveStatus rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean spaceOccupied r rmethod boolean continuePlayingmethod void constructor

var int computerStatus p p p p p s s s,g g g pi gvar int userStatus p p p p p p s p g,s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r rvar Applet myApplet p

Page 45: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

These X references are STRONG clusters. THUS, the STRONG Canidates for clustering are playComputerIfFirst and resetGame and moveComputer

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

bes

tMo

ve

leg

alU

serM

ove

leg

alC

om

pute

rMo

ve

gam

eS

tatu

s

pla

yCo

mpu

terI

fFirs

t

rese

tGa

me

gam

eO

ver

pos

tGa

meS

tatu

s

mo

veC

om

pu

ter

get

Use

rMo

veS

tatu

s

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

upie

d

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod int getUserMoveStatus rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean spaceOccupied r rmethod boolean continuePlayingmethod void constructor

var int computerStatus p p p p p s s s,g g g pi gvar int userStatus p p p p p p s p g,s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r rvar Applet myApplet p

Page 46: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now we look at the LOOSE clusterings. THUS the WEAK canidates for clustering are playGame and continuePlaying and bestMove.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

bes

tMo

ve

leg

alU

serM

ove

leg

alC

om

pute

rMo

ve

gam

eS

tatu

s

pla

yCo

mpu

terI

fFirs

t

rese

tGa

me

gam

eO

ver

pos

tGa

meS

tatu

s

mo

veC

om

pu

ter

get

Use

rMo

veS

tatu

s

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

upie

d

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod int getUserMoveStatus rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean spaceOccupied r rmethod boolean continuePlayingmethod void constructor

var int computerStatus p p p p p s s s,g g g pi gvar int userStatus p p p p p p s p g,s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r rvar Applet myApplet p

Page 47: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

We can determine ALL the STRONG methods, labeled in red.

computerStatus

userStatus

computerFirst

winningStatus

resetGame

playComputerIfFirst

moveComputer

resetGame

moveUser

resetGame

setWinningState

Page 48: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Note that the resetGame method is Strong in with several class variables, so I will place it in the undecided box.

computerStatus

userStatus

computerFirst

winningStatus

resetGame

playComputerIfFirst

moveComputer

resetGame

moveUser

resetGame

setWinningState

Undecided

resetGame-S

Page 49: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

We can see that the two strong methods of computerStatus. The method playComputer references nonone but does a get on computerFirst. The method moveComputer references bestMove and does a get to computerStatus and userStatus .

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 50: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now we look at what these methods are referenced by. The Strong method playComputeIfFirst is referenced by resetGame. The Strong method moveComputer is referenced by continueplaying.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 51: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

The STRONG method playComputerFirst references noone. It is referenced by resetGame and gets the class variable computerFirst. We can see how these items begin to cluster together to form natural classes.

We show these sets, gets, references and parameters using a Rosetta-like map. A legend below shows how to read the map.

params

playGame

continuePlaying

Page 52: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

bestMove

params

continuePlaying

Now we look at the next STRONG method moveComputer.

The method moveComputer references bestMove, gets computerStatus, and is referenced by continuePlaying.

playGame

Page 53: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

bestMove

params

continuePlaying

Now we look at the next STRONG method moveComputer.

The method moveComputer references bestMove, gets computerStatus, and is referenced by continuePlaying.

playGame

Page 54: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

The STRONG method playComputerFirst references noone. It is referenced by resetGame and gets the class variable computerFirst. We can see how these items begin to cluster together to form natural classes.

We show these sets, gets, references and parameters using a Rosetta-like map. A legend below shows how to read the map.

params

playGame

continuePlaying

Page 55: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

bestMove

params

continuePlaying

Now we look at the next STRONG method moveComputer.

The method moveComputer references bestMove, gets computerStatus, and is referenced by continuePlaying.

playGame

Page 56: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

We then look at the Strong methods for userStatus and continue to trace its related references.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 57: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

bestMove

params

Now we look at the next STRONG method moveUser.

The method moveUser references nothing but is referenced by makeMoves. The methods continuePlaying and playGame perform gets on userStatus.

makeMoves

continuePlaying

playGame

Page 58: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

The third variable computerFirst has its only strong method resetGame in undecided. It does have a get from playComputerIfFirst but that has already been noted on the graph.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 59: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

The last variable winninStatus is updated (set) by the strong method setWinningStatus and setWinningStatus references nothing.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 60: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

set

getref

bestMove

params

STRONG methods for computerFirst and for winningStatus

The method setWinningStatus references nothing. But winningStatus does havereferences (gets) from userWins, bestMove, and gameStatus. We will do params later.

makeMoves

continuePlaying

playGame

userWins

gameStatus

Page 61: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

setgetrefparams

We will begin by defining variable clusters first.

It is clear that variable clusters computerStatus and userStatus are tightly coupled.

The winningStatus cluster could be moved out with or without bestMove.

The computerFirst cluster could be moved out or included with the computerStatus cluster.

computerStatus

userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

bestMove

makeMoves

continuePlaying

playGame

userWins

gameStatus

Page 62: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses set

getrefparams

Now we need to group and expand this graph to see how the others cluster.

We begin by defining computerStatus/userStatus as one cluster and expand it out.

At this point we have the computerStatus/userStatus cluster with the methods moveUser and moveComputer as Strong and weak methods of continuePlaying, playGame, makeMoves, and bestMove.

computerStatus/userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-ScomputerFirst

bestMove makeMoves

continuePlaying

playGame

userWins

gameStatus

Page 63: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now we need to trace backwards from the weak methods to see their references. We first do it for the new cluster computerStatus/userStatus. Those include continuePlaying, playGame, and makeMoves.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 64: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

setgetrefparams

This tightens this clustering. The extended method makeMoves calls two of the weaker methods continuePlaying and playGame and also performs gets to both of the class variables. The extended methods are labeled in blue.

The methods continuePlaying, playGame and makeMoves are now classified as strong with the references to one another and the references to the class variables.

computerStatus/userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-S computerFirst

bestMove

makeMoves

continuePlaying

playGame

userWins

gameStatus

gameOver

postGameStatus

legalUserMove

legalComputerMove

Page 65: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Before we decide to bring the strong methods into the cluster, we look at the methods that are also reference these strong methods. Since no more methods are referenced then we try them in the cluster.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 66: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

setgetrefparams

After we bring in the strong methods into the computerStatus/userStatus cluster, we can then look at the extended methods. This is not a one shot process. It make several attempts at clustering until you find the BEST solution since a perfect solution may not be possible. I usually save each version of clustering to allow regression.

The extended methods are legalComputerMove, legalUserMove, gameOver and postGameStatus

computerStatus/userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-S computerFirst

bestMove

makeMoves

continuePlaying

playGame

userWins

gameStatus

gameOver

postGameStatus

legalUserMove

legalComputerMove

Page 67: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

We look at these methods we note while the use the class variables of the current cluster as parameters or indirect parameters, they call one other method squareOccupied. Then we look at who references them and see those methods are already in the cluster.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 68: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

setgetrefparams

However, we show the linkages. These are the leaves of the linkages and they are targets for clustering with other clusters. It is difficult to know when you should stop and liik at the other potential clusterings. Possible scenarios are to do all the potential clusters and their weak methods then look at what might can be enclosed in a cluster.

We will stop here and look at what methods remain

computerStatus/userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-S computerFirst

bestMove

makeMoves

continuePlaying

playGame

userWins

gameStatus

gameOver

postGameStatus

legalUserMove

legalComputerMove

squareOccupied

Page 69: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now lets look at the methods that are included in the first cluster.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 70: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now lets look at the methods that are included in the first cluster.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

Page 71: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

setgetrefparams

Houston, we have clustering of two classes. The computerStatus/userStatus cluster now named PlayGame, will contain all the methods it takes to actually play the game. Another cluster named GameStrategy, will contain all the methods, regardless how simple, we are using to help the computer to win the game.

It only makes sense to put resetGame, and playComputerIfFirst in the Game class.

computerStatus/userStatus

winningStatus

playComputerIfFirst

moveComputer

moveUser

setWinningState

Undecided

resetGame-S

computerFirst

bestMove

makeMoves

continuePlaying

playGame

userWins

gameStatus

gameOver

postGameStatus

legalUserMove

legalComputerMove

squareOccupied

cellEmpty

userWins

Page 72: Refactoring Classes Lesson Six: Classes. Refactoring Classes Class Decomposition is difficult. Several Techniques exist: Behavioral Driven Design[Kowal]

RefactoringClasses

Now lets look at the methods that are included in the first cluster.

Kind Type Variables, Constants, Methods DOMAIN CLASS

setW

inn

ing

Sta

te

cellE

mp

ty

use

rWin

s

be

stM

ove

leg

alU

serM

ove

leg

alC

om

pu

terM

ove

ga

me

Sta

tus

pla

yCo

mp

ute

rIfF

irst

rese

tGa

me

ga

me

Ove

r

po

stG

am

eS

tatu

s

mo

veC

om

pu

ter

mo

veU

ser

ma

keM

ove

s

pla

yGa

me

squ

are

Occ

up

ied

con

tinu

eP

layi

ng

method void setWinningStatemethod boolean cellEmpty r rmethod boolean userWins rmethod int bestMove rmethod boolean legalUserMove rmethod boolean legalComputerMove rmethod int gameStatus r r

method void playComputerIffirst rmethod void resetGame rmethod boolean gameOver rmethod void postGameStatus r r

method void moveComputer rmethod void moveUser rmethod void makeMoves rmethod void playGamemethod boolean squareOccupied rmethod boolean continuePlaying rmethod void constructor

var int computerStatus p p p p p s s pi pi s,g g pi gvar int userStatus p p p p p p s pi pi p s g pi gvar boolean computerFirst g s,gvar arrayint winningState[] u r r r

`