소프트웨어시스템설계 2023-03-15 수업정리

Flow

Refactoring Example


아래의 UML과 코드들은 리펙토링을 하기 이전의 원본 상태이다.

Original UML

Original UML

Original Code - Run

Customer customer1 = new Customer("David");
Movie movie1 = new Movie("Madagascar", Movie.CHILDRENS);
Rental rental1 = new Rental(movie1, 6);
Movie movie2 = new Movie("Star Wars", Movie.NEW_RELEASE);
Rental rental2 = new Rental(movie2, 2);
Movie movie3 = new Movie("Gone with the Wind", Movie.REGULAR);
Rental rental3 = new Rental(movie3, 8);
customer1.addRental(rental1);
customer1.addRental(rental2);
customer1.addRental(rental3);
System.out.println(customer1.statement());
Rental Record for David
	Madagascar 6.0
	Star Wars 6.0
	Gone with the Wind 11.0
Amount owed is 23.0
You earned 4 frequent renter points

Original Code - class Movie

public class Movie {
	public static final int CHILDREN = 2;
	public static final int REGULAR = 0;
	public static final int NEW_RELEASE = 1;
	private String _title;
	private int _priceCode;
	public Movie(String title, int priceCode) {
		_title = title;
		_priceCode = priceCode;
	}
	public int getPriceCode() { return _priceCode; }
	public void setPriceCode(int arg) { _priceCode = arg; }
	public String getTitle () { return _title; }
}

Original Code - class Rental

class Rental {
	private Movie _movie;
	private int _daysRented;
	public Rental(Movie movie, int daysRented) {
		_movie = movie;
		_daysRented = daysRented;;
	}
	public int getDaysRented() { return _daysRented; }
	public Movie getMovie() { return _movie; }
}

Original Code - class Customer

class Customer {
	private String _name;
	private Vector<Rental> _rentals = new Vector<Rental>();
	public Customer (String name) { _name = name; }
	public void addRental(Rental arg) { _rentals.addElement(arg); }
	public String getName() { return _name; }
	public String statement() {
		double totalAmount = 0;
		String result = "Rental Record for " + getName() + "\n";
		for(Rental each: _rentals) {
			double thisAmount = 0;
			switch(each.getMovie().getPriceCode()){
				case Moviie.REGULAR:
					thisAmount += 2;
					if(each.getDaysRented() > 2)
						thisAmount += (each.getDaysRented() -2) * 1.5;
					break;
				case Movie.NEW_RELEASE:
					thisAmount += each.getDaysRented() * 3;
					break;
				case Movie.CHILDREN:
					thisAmount += 1.5;
					if(each.getDaysRented() > 3)
						thisAmount += (each.getDaysRented() - 3) * 1.5;
					break;
			}
			frequentRenterPoints++;
			if((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) 
				&& each.getDaysRented() > 1)
				frequentRenterPoints++;
			result += "\t" + each.getMovie().getTitle() + "\t"
			+ String.valueOf(thisAmount) + "\n";
			totalAmount += thisAmount;
		}
		result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
		result += "You earned " + String.valueOf(frequentRenterPoints) 
			+ " frequent renter points";
		return result;
	}
}

문제점들과 해결 방법

Step1 - UML

Statement method의 implementation을 여러 별개의 method로 extract method한다. 이 과정에서 다른 클래스의 feature를 더 많이 사용한다면 Move method 한다. uml step1

Step2 - UML

새로운 클래스를 추상 클래스 형태로 추가하여 Polymorphism을 통해 OCP를 만족시키도록 설계한다. step1에서 다른 class의 feature를 더 많이 사용하여 이동된 method를 확인할 수 있다. uml step2