《重構》的第一章表演了一段「什麼是重構?」
在這,把程式碼弄成C++,同義的表演抄一次。
程式規格:
- 影片出租店用的程式
計算每一位顧客的消費金額並列印報表(statment) - 操作者告訴程式 顧客租了哪些影片?
租期多長?
程式便計算出費用 - 影片分為三類普通片、兒童片、新片
- 除了計算費用,還要為常客計算點數依照「是否為新片」而所有不同
原本的程式碼
第一個類別#include<string>
class Movie
{
std::string _title; //名稱
int _priceCode; //價格(代號)
public:
static int CHILDERNS = 2;
static int REGULAR = 0;
static int NEW_RELEASE = 1;
Moive(String title, int priceCode);
int getPriceCode();
void setPriceCode(int arg);
String getTitle();
};
inline Movie::Moive(String title, int priceCode)
{
_title = title;
_priceCode = priceCode;
}
inline int Movie::getPriceCode()
{
return _priceCode;
}
inline String Movie::getTitle()
{
return _title;
}
inline void Movie::setPriceCode()
{
_priceCode = arg;
}
第二個類別
#include "CMovie.h"
class Rental
{
Movie _movie; //影片
int _dayRented; //租期
public:
Rental(Movie movie, int dayRented);
int getDaysRented();
Movie getMovie();
};
inline Rental::Rental(Movie movie, int dayRented)
{
_movie = movie;
_dayRented = daysRented;
}
inline int Rental::getDaysRented()
{
return _dayRented;
}
inline Movie Rental::getMovie()
{
return _movie;
}
第三個類別
#include <string>
#include <vector>
#include "CRental.h"
class Customer
{
std::string _name; //姓名
std::vector _rentals; //租借
public:
Customer(std::string name);
void addRental(Rental arg);
std::string getName();
//接續下一頁
std::string statement();
};
inline Customer::Customer(std::string name)
{
_name = name;
}
inline void Customer::addRental(Rental arg)
{
_rentals.push_back(arg);
}
inline std::string Customer::getName()
{
return _name;
}
inline std::string Customer::statement()
{
double totalAmount = 0; //消費總金額
int frequentReterPoints = 0; //常客積點
std::vector::const_iterator rentals = _rentals.begin();
std::string result = "Rental Record for " + getName() + "\n";
while(retals.hasMoreElements())
{
double thisAmount = 0;
Rental each = (Rental)rentals.next(); //取得一筆租借記錄
//determine amounts for each line
switch(each.getMovie().getPriceCode()) //取得影片出租價格
{
case Movie.REGULAR:
thisAmount += 2;
if (each.getDayRented() > 2)
thisAmount += (each.getDayRented()-2)*1.5;
break;
case Movie.NEW_RELEASE:
thisAmount += each.getDayRented()*3;
break;
case Movie.CHILDRENS:
thisAmount += 1.5;
if (each.getDayRented() > 3)
thisAmount += (each.getDayRented()-3)*1.5;
break;
}
//add frequent renter points(累加 常客積點)
frequentReterPoints++;
//add bonus for a two day new release rental
if ((each.getMovie().getPriceCode() == Movie.NEW.RELEASE) && each.getDayRented() > 1))
frequentReterPoints++;
//show figures for this rental (顯示這筆租借資料)
result += "\t" + each.getMovie().getTitle() + "\t" + std::string.valueOf(thisAmount) + "\n";
totalAmount += thisAmount;
}
//add footer lines(結尾列印)
result += "Amount owed is " + std::string.valueOf(totalAmount) + "\n";
rental += "You earned " + std::string.valueOf(frequentReterPoints) + " frequent renter points";
return result;
}
理性:
差的系統→很難找到修改點→很難修改
程式設計師很容易犯錯→引入bug
感性:
不好看,不美的程式
評價:
設計得不好,不符合物件導向的精神
Quick and dirty(快速而隨性)
Customer::statement()做的事,應該是由其它class完成的
接下來
使用者希望對系統做一些修改
希望以html的格式列印報表,直接在網頁上顯示,符合潮流
困難點
根本不可能reuse目前statement()的任何行為
唯一能做的就是做一個htmlStatement(),copy-past statement()的內容再修改
若再修改,不就??
接下來
使用者希望改變影片分類規則,但是還沒決定怎麼改
設想的方案中,都會影響顧客消費和常客積點的計算方式。
所以,我們需要開始重構(待續...)
沒有留言:
張貼留言
(什麼是留言欄訊息?)