CSC407: Programming Engineering Fall 2006 Refactoring.


44 views
Uploaded on:
Category: Sports / Games
Description
A card diversion including one or more players and a merchant. Begin with two cards, and can ask ... { private BlackjackHand hand = new BlackjackHand(); open Card getUpCard ...
Transcripts
Slide 1

CSC407: Software Architecture Fall 2006 Refactoring Greg Wilson BA 4234 gvwilson@cs.utoronto.ca

Slide 2

Announcements Seneca FSOSS http://cs.senecac.on.ca/fsoss/2006/index.html Oct 26-27, 2006, York University CUTC http://www.cutc.ca/Jan 11-13, 2007, in Toronto CUSEC http://www.cusec.net/Jan 18-20, 2007, in Montreal

Slide 3

Making Code Better The primary addresses talked about rule that great item arranged code ought to obey But imagine a scenario in which the code you have doesn\'t. Refactoring is the way toward rearranging code to enhance structure, or make space for future expansion Without evolving usefulness

Slide 4

Refactoring and Patterns Design designs depict what code looks like when it\'s stopping Refactoring designs portray how code changes after some time Usually (yet not frequently) you refactor to designs I.e., move from poor or wrong association to one or more perceived examples

Slide 5

Blackjack A card amusement including one or more players and a merchant Start with two cards, and can request more Players go first; merchant goes last Dealer must take a card when under 17 Must "remain" at 17 or over Objective is to get as near 21 as would be prudent, without going over

Slide 6

A Blackjack Hand open class BlackjackHand { private ArrayList<Card> cards = new Arraylist<Card>(); open void addCard(Card card) { cards.add(card); } open List<Card> getCards() { return cards; } open boolean isBusted() { return getCount() > 21; } open int getResult(BlackjackDealer merchant) {/make sense of in the event that this hand beats the merchant } open int getCount() {/return the estimation of this hand } open String toString() { … } Want to have the capacity to re-utilize this in other card recreations Why do we rely on upon the merchant to make sense of on the off chance that we won?

Slide 7

Cards open class Card { open enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES } open suit; private int esteem; private BlackjackHand heldBy; open Card(Suit suit, int esteem) { … } open void setHand(BlackjackHand hand) { heldBy = hand; } open BlackjackHand getHand() { return heldBy; } open int getLowValue() {/worth or 1 for ace, 10 for face cards } open int getHighValue() {/quality or 11 for ace, 10 for face cards } Won\'t have the capacity to utilize this in a poker diversion This is certain to blackjack.

Slide 8

The Dealer open class BlackjackDealer { private BlackjackHand hand = new BlackjackHand(); open Card getUpCard() { return hand.getCards().get(1); } open BlackjackHand getHand() { return hand; } open boolean mustHit() { return hand.getCount() < 17; } OK in this way, yet…

Slide 9

Players open class ComputerBlackjackPlayer { private BlackjackHand hand = new BlackjackHand(); open BlackjackHand getHand() { return hand; } open boolean wantCard(BlackjackDealer merchant) {/computerized reasoning goes here… } open class HumanBlackjackPlayer { private BlackjackHand hand = new BlackjackHand(); open BlackjackHand getHand() { return hand; } open boolean wantCard() {/UI goes here… } These two classes have nothing in the same way as each other, or with the merchant appeared on the past slide!

Slide 10

The Game open class Blackjack { open static void main(String[] args) { Blackjack bj = new Blackjack(); bj.playGame(); } open void playGame() { ArrayList<Card> deck = new ArrayList<Card>(52); for (Card.Suit suit : Card.Suit.values()) { for (int value=1; value<=13; ++value) { card = new Card(suit, esteem); deck.add(card); }  This piece is not particular to blackjack: we ought to make it reusable

Slide 11

… The Game Collections.shuffle(deck); ComputerBlackjackPlayer PC = new ComputerBlackjackPlayer(); HumanBlackjackPlayer human = new HumanBlackjackPlayer(); BlackjackDealer merchant = new BlackjackDealer(); for (int c=0; c<2; c++) { card = deck.remove(0); BlackjackHand computerHand = computer.getHand(); computerHand.addCard(card); card.setHand(computerHand); card = deck.remove(0); BlackjackHand humanHand = human.getHand(); humanHand.addCard(card); card.setHand(humanHand); card = deck.remove(0); BlackjackHand dealerHand = dealer.getHand(); dealerHand.addCard(card); card.setHand(dealerHand); }  Deals two cards to every player—without a doubt this can be more straightforward

Slide 12

… The Game System.out.println("Dealer has: " + dealer.getUpCard()); boolean computerBusted = false; while (computer.wantCard(dealer)) { card = deck.remove(0); BlackjackHand computerHand = computer.getHand(); computerHand.addCard(card); card.setHand(computerHand); if (computerHand.isBusted()) { computerBusted = genuine; break; } if (computerBusted) { System.out.println("*** Computer busted! ***"); } else { System.out.println("*** Computer stands ***"); }  Scattered println explanations as a UI? Bleah… And haven\'t we seen the lines that give players cards some time recently?

Slide 13

… The Game boolean humanBusted = false; System.out.println("Your hand: " + human.getHand()); while (human.wantCard()) { … fundamentally the same code as above… } boolean dealerBusted = false; … essentially the same code as above…  The three players play in practically the same way; the main things that vary are what they\'re called, and how they choose whether or not to take another card

Slide 14

… The Game System.out.println("*** Results ***"); int compResult = computer.getHand().getResult(dealer); if (compResult > 0) { System.out.println("Computer wins"); } else if (compResult < 0) { System.out.println("Computer loses"); } else { System.out.println("Computer pushes"); } int humanResult = human.getHand().getResult(dealer); if (humanResult > 0) { System.out.println("You win!"); } else if (humanResult < 0) { System.out.println("You lose :- ("); } else { System.out.println("You push"); } More redundancy, more inserted printing… (Oh, and "push" is blackjackese for "tie")

Slide 15

Just How Bad Is This? Blackjack ComputerBlackjackPlayer 1 * BlackjackHand Card HumanBlackjackPlayer 0… 1 BlackjackDealer Eww…

Slide 16

Problems Every Card thinks about the BlackjackHand that is holding it Which makes the Card class hard to re-use in a poker program The Blackjack class runs everything Creating a deck of cards and rearranging it should be reusable

Slide 17

… Problems Parts of the BlackjackHand class could be utilized for different sorts of "hands" There\'s a great deal of copied code BlackjackHand relies on upon BlackjackDealer Because one of BlackjackHand \'s strategies takes a BlackjackDealer as a parameter

Slide 18

… Problems BlackjackDealer has one major solid playGame strategy Quick, let me know how you\'re going to test it The UI comprises of scattered print proclamations How are we going to manufacture a GUI for this, or a web interface?

Slide 19

Step 1: Deblackjackification open class Card { open enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES } open suit; private int esteem; private BlackjackHand heldBy; open Card(Suit suit, int esteem) { … } open void setHand(BlackjackHand hand) { heldBy = hand; } open BlackjackHand getHand() { return heldBy; } open int getLowValue() {/quality or 1 for ace, 10 for face cards } open int getHighValue() {/worth or 11 for ace, 10 for face cards } References to BlackjackHand Other recreations don\'t give cards these qualities (or recognize low and high values)

Slide 20

A Non-Solution Option 1: make a dynamic Hand base class, and get BlackjackHand from that But that still leaves this delicate code: computerHand.addCard(card); card.setHand(computerHand); Do cards truly need to know what hands their in?

Slide 21

Our First Refactoring Pattern Change Bidirectional Association to Unidirectional Association BDAs aren\'t inherently awful But they are naturally harder to oversee Remove getHand and setHand from Card , expel the setHand brings in Blackjack … nothing breaks!

Slide 22

Moving Methods getLowValue and getHighValue are next Can\'t erase them, since getCount needs the data they give Options: Move into a current subclass Create a subclass and move the techniques down

Slide 23

Spotting Movable Methods If a strategy uses another item more than it utilizes itself, it\'s a contender for moving open class X { open int meth(Y y) { int y1 = y.one(); int y2 = y.two(); int y3 = y.three(); return y1 + y2 + y3; } open class Y { open int meth() { return one() + two() + three(); }

Slide 24

What About Subclassing? The other choice is to the rationale into another subclass Have Card.getValue give back the "raw" esteem Have BlackjackCard wrap getValue in two new strategies getLowValue and getHighValue Then change references from Card to BlackjackCard Votes?

Slide 25

Open-Closed Principle open Deck() { cards = new ArrayList<Card>(52); for (Card.Suit suit : Card.Suit.values()) { for (int value=1; value<=13; ++value) { card = new Card(suit, esteem); cards.add(card); } open Deck() { cards = createCards(); } secured List<Card> createCards() { List<Card> cards = new ArrayList<Card>(52); for (Card.Suit suit : Card.Suit.values) { for (int value=1; value<=13; ++value) { card = createCard(suit, esteem); cards.add(card);

Recommended
View more...