Code Refactoring 15

Replace Primitive Type with a ClassIn this part of my code refactoring tutorial, we’ll look at how to replace a primitive type with a class.

Type safety is very important! So, what we want to do is to eliminate all operations on values that are not of the appropriate data type by protecting the program from bad input. One way we can do this is by replacing primitive types with classes. I’ll walk you step-by-step through the process. The code below will help you along.

If you like videos like this, it helps to tell Google+

Code From the Video

ATMAccessBad.java

public class ATMAccessBad { 
	
	private String state; 
  
	public final static String CARD_ENTERED = "CARD ENTERED"; 
	public final static String VALID_CARD = "VALID CARD"; 
	public final static String VALID_PIN = "VALID PIN"; 
	public final static String VALID_CASH_REQUEST = "VALID CASH REQUEST";  
	public final static String DENIED = "DENIED";
	
	public final static int CARD_NUMBER = 123456789;
	public final static int PIN_NUMBER = 1234;
	public final static double CARD_BALANCE = 1000.00;
	
	public ATMAccessBad() { state = CARD_ENTERED; }  
	
	public void verifyCard(int cardNumber) { 
		
		if (CARD_NUMBER == cardNumber) { 
			state = VALID_CARD; 
		} else state = DENIED; 
		
	}  

	public void verifyPIN(int pinNumber) { 
		
		if (PIN_NUMBER == pinNumber) { 
			state = VALID_PIN; 
		} else state = DENIED; 
		
	} 
	
	public void verifyWithdrawalAmount(double withdrawalRequest) { 
		
		if (CARD_BALANCE > withdrawalRequest) { 
			state = VALID_CASH_REQUEST; 
		} else state = DENIED; 
		
	}  

	public static void main(String[] args){
		
		ATMAccessBad user = new ATMAccessBad();
		
		System.out.println(user.state);
		
		user.verifyCard(123456789);
		
		System.out.println(user.state);
		
		user.verifyPIN(1234);
		
		System.out.println(user.state);
		
		user.verifyWithdrawalAmount(99);
		
		System.out.println(user.state);
		
	}

}

ATMAccess.java

// Type safety is very important. 
// We want to eliminate all operations on values that 
// are not of the appropriate data type by protecting
// the program from bad input.

// We can do this by replacing primitive types with classes

public class ATMAccess { 
	
	// Define a type safe field 
	
	private ATMCardState cardState;
	
	private void setState(ATMCardState cardState){
		
		this.cardState = cardState;
		
	}
	
	public ATMAccess() { 
		
		// Create type safe assignment
		
		setState(ATMCardState.CARD_ENTERED);
		
	}  
	
	public String getState() { 
		
		// REPLACED return state; 
		
		return cardState.toString();
		
	} 
	
	// 1. Encapsulation is used
	
	public void verifyCard(int cardNumber) { 
		
		if (getState().equals(ATMCardState.CARD_ENTERED.toString())){
			
			if(cardNumber == ATMCardState.CARD_NUMBER){
			
			// Create type safe assignment
			
			setState(ATMCardState.VALID_CARD);
			
			} else { setState(ATMCardState.DENIED); }
		}
		
	}  
	
	public void verifyPIN(int pinNumber) { 
		
		if (getState().equals(ATMCardState.VALID_CARD.toString())){
			
			if(pinNumber == ATMCardState.PIN_NUMBER){
			
			// Create type safe assignment
			
			setState(ATMCardState.VALID_PIN);
			
			} else { setState(ATMCardState.DENIED); }
		}
		
	}  
	
	public void verifyWithdrawalAmount(double withdrawalRequest) { 
		
		if (getState().equals(ATMCardState.VALID_PIN.toString())){
			
			if(withdrawalRequest <= ATMCardState.CARD_BALANCE){
			
			// Create type safe assignment
			
			setState(ATMCardState.VALID_CASH_REQUEST);
			
			} else { setState(ATMCardState.DENIED); }
		}
		
	}  
	
	public static void main(String[] args){
		
		ATMAccess user = new ATMAccess();
		
		System.out.println(user.getState());
		
		user.verifyCard(123456789);
		
		System.out.println(user.getState());
		
		user.verifyPIN(1234);
		
		System.out.println(user.getState());
		
		user.verifyWithdrawalAmount(1000);
		
		System.out.println(user.getState());
		
	}
	
}

// Represents the state of a ATMAccess object

class ATMCardState{
	
	private final String name;
	
	private ATMCardState(String name){

		this.name = name;
		
	}
	
	public String toString(){
		
		return name;
		
	}
	
	// These type safe constants live in the class and can't be impersonated
	
	public final static ATMCardState CARD_ENTERED = new ATMCardState("CARD ENTERED");
	public final static ATMCardState VALID_CARD = new ATMCardState("VALID CARD");
	public final static ATMCardState VALID_PIN = new ATMCardState("VALID PIN");
	public final static ATMCardState VALID_CASH_REQUEST = new ATMCardState("VALID CASH REQUEST");
	public final static ATMCardState DENIED = new ATMCardState("DENIED");
	
	public final static int CARD_NUMBER = 123456789;
	public final static int PIN_NUMBER = 1234;
	public final static double CARD_BALANCE = 1000.00;
	
}

7 Responses to “Code Refactoring 15”

  1. Stas says:

    Hi,

    Do you happen to have an aspect oriented programming video tutorial?

  2. Goutam says:

    Hey Derek,

    Why not use Enums instead of creating a class as internally an enum is converted to a class and values in enum to objects?

Leave a Reply

Your email address will not be published.

Google+