上次我們建立了一個簡陋的存款功能原型,而非常容易的就能看出,程式充滿了缺陷,不精確的名稱,使用者不需要看到的資訊等等
public class Main {
// 紀錄存款交易的列表
private static List<Integer> save;
public static void main(String[] args) {
save = new ArrayList<>();
Scanner sc = new Scanner(System.in);
System.out.println("請輸入金額:");
int value = sc.nextInt();
save.add(value);
// 為了確認而加上的檢查,並不屬於程式邏輯,應該盡速建立測試取代
for (int s : save) {
System.out.println(" "+s);
}
}
}
取為Main是代表這裡是整個程式的進入點,這是我的開發習慣,而很明顯的,存款功能並非主流程中應該實現的部分,所以我們決定第一個調整是把存款功能提取成一個函式
deposit(); // called
private static void deposit() {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入金額:");
int value = sc.nextInt();
save.add(value);
// 為了確認而加上的檢查,並不屬於程式邏輯,應該盡速建立測試取代
for (int s : save) {
System.out.println(" "+s);
}
}
接著,value是什麼?不明確的名稱帶來誤解和錯誤,我們知道它其實是指存款金額,所以我們把它改成amountOfDeposit
而此處介面和邏輯混雜,只能手動測試結果的狀況顯然是很糟糕的情況,因此我們分離出第一個邏輯"增加存款紀錄"
AddDepositLog(amountOfDeposit);
private static void AddDepositLog(int amountOfDeposit) {
save.add(amountOfDeposit);
}
接著我們就把最後為了確認而印出save的行為移到測試程式之中
@Test
public void AddDepositLog_should_add_log_into_save() {
Main.AddDepositLog(1);
List<Integer> expect = new ArrayList<>();
expect.add(1);
Assert.assertEquals(expect, Main.save);
}
在這次的修改之後,我們發現無論是AddDepositLog還是save,都不適合放在Main裡,所以我們必須為它們找到更合適的位置,我們先看save,它是什麼?
// 紀錄存款交易的列表
這是註解中清楚說明的事情,所以我第一個動作是創建一個新的類別,它負責管理交易紀錄
public class TransactionLogger {}
接下來我們把save放進去,毫不意外的,語法檢查忠實的報出錯誤
public class TransactionLogger {
// 紀錄存款交易的列表
public static List<Integer> save = new ArrayList<>();
}
ps.我不會在這個教學裡面使用重構工具,那當然方便,但你可能因此而對重構不夠了解,甚至換個環境就只能等死,所以我也希望你至少在學習過程中不要使用自動化工具做事,而當你已經能夠了解整個流程,自動化工具才能幫你許多忙,而不是埋下一堆不定時炸彈
原因在於我們忘記了把存取方式改成新的了,所以:
save 改成 TransactionLogger.save
接著執行測試,Oops!出錯了,喔!原來這裡的存取也還沒改
更改之後測試也通過了
save移動成功後,我們想要移動
AddDepositLog,一樣移到
TransactionLogger上
public class TransactionLogger {
// 紀錄存款交易的列表
public static List<Integer> save = new ArrayList<>();
public static void AddDepositLog(int amountOfDeposit) {
TransactionLogger.save.add(amountOfDeposit);
}
}
一樣更改各處的存取方式,這時候我們發現一件有趣的事實,原先的MainTest現在完全為了
TransactionLogger服務,所以我們改變它的名稱
public class TransactionLoggerTest {
@Test
public void AddDepositLog_should_add_log_into_save() {
TransactionLogger.AddDepositLog(1);
List<Integer> expect = new ArrayList<>();
expect.add(1);
Assert.assertEquals(expect, TransactionLogger.save);
}
}
這下你可以看到,
TransactionLogger已經真正的獨立了
這是程式現在的執行流程
Get Money -> Record transaction
最後,執行測試,通過,這篇就到這裡,下次將開發新的功能,讓我們看看如何將新功能整合進已有的實作之中
NEXT: ATM 03
沒有留言:
張貼留言