SlideShare uma empresa Scribd logo
1 de 19
Refactoring Chapter 1: 重構,第一個案例 KalinChih
何時該考慮要重構? 如果發現無法很方便地增加新 feature,或修改邏輯 作法: 先找看看是否有一套可靠的測試機制? 先重構程式 再增加新 feature
重構Step1: 了解案例 案例: 影片出租店程式 pirceCode: 決定影片類型、價錢 daysRented: 決定租片金額、積點 statement(): 列印租片紀錄清單與總金額、總積點 Example: chp1.movie_rental.v1.* Test Class: chp1.movie_rental.test.Test.java
重構Step2: Extract 金額計算 動機: 過長的程式碼不易閱讀 Extract 過長的程式區塊 (Fine-grained) 作法:Extract Method 將 Customer.statement() 的內金額計算程式區塊,Extract 成一個新 anmountFor() Example : chp1.movie_rental.v2.extract_amount.* 重構前,有一套可靠的測試機制是很重要滴~
Rename 是值得的行為 電腦可以理解和人寫出來的程式碼,但唯有寫出人類容易理解的程式碼,才是優秀的程式員
重構Step3: Move金額計算 動機: 計算金額的程式碼為何不是放在 Rental 而是放在 Customer? 大多情況下,method 應該放在他所使用的 object (class) 內 金額計算應該放在 Rental 比放在 Customer 洽當 作法: Move Method 將 Customer.statement() 內的計算金額的程式碼搬到 Rental Example: chp1.movie_rental.v3.move_amount.*
重構Step4: Move點數計算 動機: 類似於金額計算,點數計算功能應該要屬於 Rental 比較洽當 作法: 將Customer.statement() 內的點數計算程式碼搬到 Rental  Example: chp1.movie_rental.v4.move_frequentrenterpoints.*
重構Step5: 移除 Temp Variables 動機: Temp Variable 可能會是個問題,助長程式碼過長 由於變數只是暫時的,所以能見度只在這個程式區塊。若在其他區塊也想要使用這個 Temp Variable,便會驅使寫出更長的程式。 作法: 使用 Query Method 取代 temp variable 若使用 Query Method 取代 Temp Variable,至少同一個 class 內都能獲得這份資訊。 getTotalCharge() 取代 totalAmount getFrequentRenterPoints() 取代 frequentRenterPoints Example: chp1.movie_rental.v5.replace_temp_with_query.* New issue: 效能變差 原本只要一個迴圈做到的事情,現在要跑三個迴圈才能做到
關於 Performance 這件事… Performance 應該是在最佳化效能時再來擔心,在重構的階段先不用擔心這件事情 Performance 應該是透過工具來檢測,肉眼是很難看出來的 回想重構的目的… 讓程式更容易被讀取 讓程式更容易被擴充 The best way to optimize performance is to first write a well factored program, then optimize it
重構後… 現在可以透過這些 Query Methods 來取得資訊,而不需研究細節
重構Step6: Move金額計算、點數計算 動機:Rental 必須取得 Movie 才能運算金額。(物件應該在自己的資料上運算邏輯,而不是拿別人的資料來運算) 考慮該邏輯該屬於哪個物件 影片的價格邏輯是應該放到 Movie class內來計算比較洽當 作法: Move Method 將 getCharge() 與 getFrequentRenterPoints() 移到 Movie class Example: chp1.movie_rental.v6.move_selfobject public class Rental { double getCharge() { double result = 0; // 取得影片的出租價格 switch (getMovie().getPriceCode()) { // 普通片 case Movie.REGULAR:
So Far So Good… 寫了幾個新的 Query Methods 可以 reuse 程式碼更容易閱讀 But! 計算金額的那段 switch 還是 不利於將來計費邏輯的變動
考慮繼承… 使用 Polymorphism 來取代 switch 問題來了,若之後 Movie有其他類似 getCharge() 容易變動的邏輯,就很不利於維護
使用Strategy Pattern Strategy Pattern 封裝了會變動的演算法(Price subclasses),所以不會影響使用演算法的程式(Movie)
重構Step7: Replace Type Code with State/Strategy 作法(1/2): Replace Type Code with State/Strategy:  將 type code behavior 搬移到 Strategy Pattern 讓金額計算的邏輯不再綁死在 Movie ,所以將金額計算的邏輯搬移到 Price 家族 Self Encapsulate Field 時機: 當想要存取一個 super class 的 field,卻在  sub class 改變它的 value 作法: 為 field 建立 setter 與 getter,只用這些  methods 來存取這個 field(即使在同一個 class 內) Move Method Example: chp1.movie_rental.v7.strategy_pattern
重構Step8: Replace Conditional with Polymorphism 作法(2/2): Replace Conditional with Polymorphism: 在 sub Price classes 內建立 overriding method 來取代 super Price class 的 switch 將 super Price class 的 getCharge() 改為 abstract Example: chp1.movie_rental.v7.strategy_pattern 方便: 為了積點的預設值,所以不將 getFrequentRenterPoints() 也改成 abstract public class NewReleasePriceextends Price { double getCharge(intdaysRented) { 	return (double) daysRented * 3; } public abstract class Price{ double getCharge(intdaysRented) { double result = 0; switch (getPriceCode()) { case Movie.NEW_RELEASE: result += (double) daysRented * 3; break; } return result; }
Final Class Diagram
重構後的好處 讓程式碼更容易閱讀 Rename Method Extract Method Move Method 新的 Query Methods 可以 reuse Replace Temp with Query 將最容易變動的邏輯抽離出來 Replace Type Code with State/Strategy Self Encapsulate Field Replace Conditional with Polymorphism
Thank You! Slide & Example Code URL: xxxx

Mais conteúdo relacionado

Semelhante a 重構—改善既有程式的設計(chapter 1)

Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
lydiafly
 
Foundation of software development 2
Foundation of software development 2Foundation of software development 2
Foundation of software development 2
netdbncku
 
业务需求分析入门
业务需求分析入门业务需求分析入门
业务需求分析入门
zhoujg
 
Coding guideline
Coding guidelineCoding guideline
Coding guideline
斯理 衛
 
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
NCUDSC
 
软件设计原则、模式与应用
软件设计原则、模式与应用软件设计原则、模式与应用
软件设计原则、模式与应用
yiditushe
 
第六章 函數與巨集
第六章 函數與巨集第六章 函數與巨集
第六章 函數與巨集
shademoon
 
Django development
Django developmentDjango development
Django development
loveyudu
 

Semelhante a 重構—改善既有程式的設計(chapter 1) (20)

ES5 introduction
ES5 introductionES5 introduction
ES5 introduction
 
Clipper@datacon.2019.tw
Clipper@datacon.2019.twClipper@datacon.2019.tw
Clipper@datacon.2019.tw
 
Ecma script edition5-小试
Ecma script edition5-小试Ecma script edition5-小试
Ecma script edition5-小试
 
Refactoring with Patterns in PHP
Refactoring with Patterns in PHPRefactoring with Patterns in PHP
Refactoring with Patterns in PHP
 
Ch07
Ch07Ch07
Ch07
 
Foundation of software development 2
Foundation of software development 2Foundation of software development 2
Foundation of software development 2
 
业务需求分析入门
业务需求分析入门业务需求分析入门
业务需求分析入门
 
Coding guideline
Coding guidelineCoding guideline
Coding guideline
 
BizTalk練習投影片
BizTalk練習投影片BizTalk練習投影片
BizTalk練習投影片
 
张所勇:前端开发工具推荐
张所勇:前端开发工具推荐张所勇:前端开发工具推荐
张所勇:前端开发工具推荐
 
C++模板与泛型编程
C++模板与泛型编程C++模板与泛型编程
C++模板与泛型编程
 
SCJP ch09
SCJP ch09SCJP ch09
SCJP ch09
 
1 Dmaic D
1 Dmaic D1 Dmaic D
1 Dmaic D
 
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx讓你的人工智慧更智慧 - Developer Student Clubs.pptx
讓你的人工智慧更智慧 - Developer Student Clubs.pptx
 
多個敏捷團隊之間的版本控制 (4)
多個敏捷團隊之間的版本控制 (4)多個敏捷團隊之間的版本控制 (4)
多個敏捷團隊之間的版本控制 (4)
 
软件设计原则、模式与应用
软件设计原则、模式与应用软件设计原则、模式与应用
软件设计原则、模式与应用
 
第六章 函數與巨集
第六章 函數與巨集第六章 函數與巨集
第六章 函數與巨集
 
Django development
Django developmentDjango development
Django development
 
Java Script 引擎技术
Java Script 引擎技术Java Script 引擎技术
Java Script 引擎技术
 
Jvm内存管理基础
Jvm内存管理基础Jvm内存管理基础
Jvm内存管理基础
 

Mais de Chris Huang

Real time big data applications with hadoop ecosystem
Real time big data applications with hadoop ecosystemReal time big data applications with hadoop ecosystem
Real time big data applications with hadoop ecosystem
Chris Huang
 
Approaching real-time-hadoop
Approaching real-time-hadoopApproaching real-time-hadoop
Approaching real-time-hadoop
Chris Huang
 
20130310 solr tuorial
20130310 solr tuorial20130310 solr tuorial
20130310 solr tuorial
Chris Huang
 
Scaling big-data-mining-infra2
Scaling big-data-mining-infra2Scaling big-data-mining-infra2
Scaling big-data-mining-infra2
Chris Huang
 
Hbase status quo apache-con europe - nov 2012
Hbase status quo   apache-con europe - nov 2012Hbase status quo   apache-con europe - nov 2012
Hbase status quo apache-con europe - nov 2012
Chris Huang
 
Hbase schema design and sizing apache-con europe - nov 2012
Hbase schema design and sizing   apache-con europe - nov 2012Hbase schema design and sizing   apache-con europe - nov 2012
Hbase schema design and sizing apache-con europe - nov 2012
Chris Huang
 
重構—改善既有程式的設計(chapter 12,13)
重構—改善既有程式的設計(chapter 12,13)重構—改善既有程式的設計(chapter 12,13)
重構—改善既有程式的設計(chapter 12,13)
Chris Huang
 
重構—改善既有程式的設計(chapter 10)
重構—改善既有程式的設計(chapter 10)重構—改善既有程式的設計(chapter 10)
重構—改善既有程式的設計(chapter 10)
Chris Huang
 
重構—改善既有程式的設計(chapter 9)
重構—改善既有程式的設計(chapter 9)重構—改善既有程式的設計(chapter 9)
重構—改善既有程式的設計(chapter 9)
Chris Huang
 
重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1
Chris Huang
 
重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)
Chris Huang
 
重構—改善既有程式的設計(chapter 6)
重構—改善既有程式的設計(chapter 6)重構—改善既有程式的設計(chapter 6)
重構—改善既有程式的設計(chapter 6)
Chris Huang
 
重構—改善既有程式的設計(chapter 4,5)
重構—改善既有程式的設計(chapter 4,5)重構—改善既有程式的設計(chapter 4,5)
重構—改善既有程式的設計(chapter 4,5)
Chris Huang
 
重構—改善既有程式的設計(chapter 2,3)
重構—改善既有程式的設計(chapter 2,3)重構—改善既有程式的設計(chapter 2,3)
重構—改善既有程式的設計(chapter 2,3)
Chris Huang
 

Mais de Chris Huang (20)

Data compression, data security, and machine learning
Data compression, data security, and machine learningData compression, data security, and machine learning
Data compression, data security, and machine learning
 
Kks sre book_ch10
Kks sre book_ch10Kks sre book_ch10
Kks sre book_ch10
 
Kks sre book_ch1,2
Kks sre book_ch1,2Kks sre book_ch1,2
Kks sre book_ch1,2
 
Real time big data applications with hadoop ecosystem
Real time big data applications with hadoop ecosystemReal time big data applications with hadoop ecosystem
Real time big data applications with hadoop ecosystem
 
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
A Graph Service for Global Web Entities Traversal and Reputation Evaluation B...
 
Approaching real-time-hadoop
Approaching real-time-hadoopApproaching real-time-hadoop
Approaching real-time-hadoop
 
20130310 solr tuorial
20130310 solr tuorial20130310 solr tuorial
20130310 solr tuorial
 
Scaling big-data-mining-infra2
Scaling big-data-mining-infra2Scaling big-data-mining-infra2
Scaling big-data-mining-infra2
 
Applying Media Content Analysis to the Production of Musical Videos as Summar...
Applying Media Content Analysis to the Production of Musical Videos as Summar...Applying Media Content Analysis to the Production of Musical Videos as Summar...
Applying Media Content Analysis to the Production of Musical Videos as Summar...
 
Wissbi osdc pdf
Wissbi osdc pdfWissbi osdc pdf
Wissbi osdc pdf
 
Hbase status quo apache-con europe - nov 2012
Hbase status quo   apache-con europe - nov 2012Hbase status quo   apache-con europe - nov 2012
Hbase status quo apache-con europe - nov 2012
 
Hbase schema design and sizing apache-con europe - nov 2012
Hbase schema design and sizing   apache-con europe - nov 2012Hbase schema design and sizing   apache-con europe - nov 2012
Hbase schema design and sizing apache-con europe - nov 2012
 
重構—改善既有程式的設計(chapter 12,13)
重構—改善既有程式的設計(chapter 12,13)重構—改善既有程式的設計(chapter 12,13)
重構—改善既有程式的設計(chapter 12,13)
 
重構—改善既有程式的設計(chapter 10)
重構—改善既有程式的設計(chapter 10)重構—改善既有程式的設計(chapter 10)
重構—改善既有程式的設計(chapter 10)
 
重構—改善既有程式的設計(chapter 9)
重構—改善既有程式的設計(chapter 9)重構—改善既有程式的設計(chapter 9)
重構—改善既有程式的設計(chapter 9)
 
重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1重構—改善既有程式的設計(chapter 8)part 1
重構—改善既有程式的設計(chapter 8)part 1
 
重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)
 
重構—改善既有程式的設計(chapter 6)
重構—改善既有程式的設計(chapter 6)重構—改善既有程式的設計(chapter 6)
重構—改善既有程式的設計(chapter 6)
 
重構—改善既有程式的設計(chapter 4,5)
重構—改善既有程式的設計(chapter 4,5)重構—改善既有程式的設計(chapter 4,5)
重構—改善既有程式的設計(chapter 4,5)
 
重構—改善既有程式的設計(chapter 2,3)
重構—改善既有程式的設計(chapter 2,3)重構—改善既有程式的設計(chapter 2,3)
重構—改善既有程式的設計(chapter 2,3)
 

Último

10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
PUAXINYEEMoe
 
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
PUAXINYEEMoe
 
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
michaelell902
 

Último (9)

1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
1.🎉成绩单,你的成绩! 💡🔥每个人都有自己的成绩单,它记录着我们努力的成果。但有时候,看着这些数字,却发现它们好像在嘲笑我?别担心,让我来告诉你们怎么改...
 
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
啟思中國語文 - 中二 單元一 - 孟嘗君列傳 - 記敍的方法和人稱1.pptx
 
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
10.2.1 马来西亚各州名称的由来六年级历史单元练习马来西亚各州名称的由来练习
 
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
1.1.3急救你必须懂四年级设计与工艺练习活页练习单元一四年级设计与工艺急救你必须懂
 
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
1.🎉“黑客”如何修改成绩?🤔🎉 在这个信息爆炸的时代,我们经常会看到各种作弊手段。但是你知道吗?有一种作弊方式可能比你想象中更巧妙:它就是——黑客![单...
 
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdftaibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
taibif_開放資料流程-清理資料01-通則_20240509_20240509.pdf
 
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
法国蒙彼利埃国家高等建筑学院毕业证制作/德语歌德B1证书/加拿大新斯科舍省农业学院文凭加急制作一个
 
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade SixMath Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
Math Chapter3-教學PPT第03單元形體關係、體積與表面積Grade Six
 
taibif_資料標準概念介紹_20240509_20240509_20340509.pdf
taibif_資料標準概念介紹_20240509_20240509_20340509.pdftaibif_資料標準概念介紹_20240509_20240509_20340509.pdf
taibif_資料標準概念介紹_20240509_20240509_20340509.pdf
 

重構—改善既有程式的設計(chapter 1)

  • 1. Refactoring Chapter 1: 重構,第一個案例 KalinChih
  • 2. 何時該考慮要重構? 如果發現無法很方便地增加新 feature,或修改邏輯 作法: 先找看看是否有一套可靠的測試機制? 先重構程式 再增加新 feature
  • 3. 重構Step1: 了解案例 案例: 影片出租店程式 pirceCode: 決定影片類型、價錢 daysRented: 決定租片金額、積點 statement(): 列印租片紀錄清單與總金額、總積點 Example: chp1.movie_rental.v1.* Test Class: chp1.movie_rental.test.Test.java
  • 4. 重構Step2: Extract 金額計算 動機: 過長的程式碼不易閱讀 Extract 過長的程式區塊 (Fine-grained) 作法:Extract Method 將 Customer.statement() 的內金額計算程式區塊,Extract 成一個新 anmountFor() Example : chp1.movie_rental.v2.extract_amount.* 重構前,有一套可靠的測試機制是很重要滴~
  • 6. 重構Step3: Move金額計算 動機: 計算金額的程式碼為何不是放在 Rental 而是放在 Customer? 大多情況下,method 應該放在他所使用的 object (class) 內 金額計算應該放在 Rental 比放在 Customer 洽當 作法: Move Method 將 Customer.statement() 內的計算金額的程式碼搬到 Rental Example: chp1.movie_rental.v3.move_amount.*
  • 7. 重構Step4: Move點數計算 動機: 類似於金額計算,點數計算功能應該要屬於 Rental 比較洽當 作法: 將Customer.statement() 內的點數計算程式碼搬到 Rental Example: chp1.movie_rental.v4.move_frequentrenterpoints.*
  • 8. 重構Step5: 移除 Temp Variables 動機: Temp Variable 可能會是個問題,助長程式碼過長 由於變數只是暫時的,所以能見度只在這個程式區塊。若在其他區塊也想要使用這個 Temp Variable,便會驅使寫出更長的程式。 作法: 使用 Query Method 取代 temp variable 若使用 Query Method 取代 Temp Variable,至少同一個 class 內都能獲得這份資訊。 getTotalCharge() 取代 totalAmount getFrequentRenterPoints() 取代 frequentRenterPoints Example: chp1.movie_rental.v5.replace_temp_with_query.* New issue: 效能變差 原本只要一個迴圈做到的事情,現在要跑三個迴圈才能做到
  • 9. 關於 Performance 這件事… Performance 應該是在最佳化效能時再來擔心,在重構的階段先不用擔心這件事情 Performance 應該是透過工具來檢測,肉眼是很難看出來的 回想重構的目的… 讓程式更容易被讀取 讓程式更容易被擴充 The best way to optimize performance is to first write a well factored program, then optimize it
  • 10. 重構後… 現在可以透過這些 Query Methods 來取得資訊,而不需研究細節
  • 11. 重構Step6: Move金額計算、點數計算 動機:Rental 必須取得 Movie 才能運算金額。(物件應該在自己的資料上運算邏輯,而不是拿別人的資料來運算) 考慮該邏輯該屬於哪個物件 影片的價格邏輯是應該放到 Movie class內來計算比較洽當 作法: Move Method 將 getCharge() 與 getFrequentRenterPoints() 移到 Movie class Example: chp1.movie_rental.v6.move_selfobject public class Rental { double getCharge() { double result = 0; // 取得影片的出租價格 switch (getMovie().getPriceCode()) { // 普通片 case Movie.REGULAR:
  • 12. So Far So Good… 寫了幾個新的 Query Methods 可以 reuse 程式碼更容易閱讀 But! 計算金額的那段 switch 還是 不利於將來計費邏輯的變動
  • 13. 考慮繼承… 使用 Polymorphism 來取代 switch 問題來了,若之後 Movie有其他類似 getCharge() 容易變動的邏輯,就很不利於維護
  • 14. 使用Strategy Pattern Strategy Pattern 封裝了會變動的演算法(Price subclasses),所以不會影響使用演算法的程式(Movie)
  • 15. 重構Step7: Replace Type Code with State/Strategy 作法(1/2): Replace Type Code with State/Strategy: 將 type code behavior 搬移到 Strategy Pattern 讓金額計算的邏輯不再綁死在 Movie ,所以將金額計算的邏輯搬移到 Price 家族 Self Encapsulate Field 時機: 當想要存取一個 super class 的 field,卻在 sub class 改變它的 value 作法: 為 field 建立 setter 與 getter,只用這些 methods 來存取這個 field(即使在同一個 class 內) Move Method Example: chp1.movie_rental.v7.strategy_pattern
  • 16. 重構Step8: Replace Conditional with Polymorphism 作法(2/2): Replace Conditional with Polymorphism: 在 sub Price classes 內建立 overriding method 來取代 super Price class 的 switch 將 super Price class 的 getCharge() 改為 abstract Example: chp1.movie_rental.v7.strategy_pattern 方便: 為了積點的預設值,所以不將 getFrequentRenterPoints() 也改成 abstract public class NewReleasePriceextends Price { double getCharge(intdaysRented) { return (double) daysRented * 3; } public abstract class Price{ double getCharge(intdaysRented) { double result = 0; switch (getPriceCode()) { case Movie.NEW_RELEASE: result += (double) daysRented * 3; break; } return result; }
  • 18. 重構後的好處 讓程式碼更容易閱讀 Rename Method Extract Method Move Method 新的 Query Methods 可以 reuse Replace Temp with Query 將最容易變動的邏輯抽離出來 Replace Type Code with State/Strategy Self Encapsulate Field Replace Conditional with Polymorphism
  • 19. Thank You! Slide & Example Code URL: xxxx