code refactoring using eclipse
TRANSCRIPT
用 Eclipse 重構程式碼 Code Refactoring Using Eclipse
中華電信 黃培棠
2013/02/26
WHAT IS REFACTORING?
2
𝑥2 − 1 = 𝑥 + 1 (𝑥 − 1)
3
Factoring:
因式分解
參考資料: http://zh.wikipedia.org/zh-tw/代碼重構
𝑥2 − 1 = 𝑥2 − 𝑥 + 𝑥 − 1= 𝑥 𝑥 − 1 + 𝑥 − 1= 𝑥 + 1 (𝑥 − 1)
4
循序漸進, Re-
不影響外部行為
怎麼證明?
• Given f x = 𝑥2 − 1
– We know that f 3 = 8
• 單元測試 3A 原則:
– Arrange: f 3 = 8, f′ x = 𝑥 + 1 𝑥 − 1
– Act: f ′ 3 = 3 + 1 3 − 1 = 4 × 2 = 8
– Assert: f 3 = f ′(3)
5
數學家看了可能會搖頭,
還好我們是 Programmer!
重構前… 重構後…
6
重構是 Programmer 自爽的事?
Refactoring 定義
• Refactoring (名詞)
– A change made to the internal structure of
software to make it easier to understand and
cheaper to modify without changing its observable
behavior.
• 除非你想參加 OMG WTF
7 “Refactoring: Improving the Design of Existing Code”, Martin Fowler, Kent Beck, et al., 1999
http://thedailywtf.com/Articles/The-Worse-Than-Failure-Programming-Contest.aspx
Any fool can write code
that a computer can understand.
Good programmers write code
that humans can understand.
- Martin Fowler
8 “Refactoring: Improving the Design of Existing Code”, Martin Fowler, Kent Beck, et al., 1999
WHEN TO REFACTORING?
9
重構的好時機
• 一樣的事做到第三次時
• 按下「貼上」前
• 要新增功能時
• 開始修 Bug 前
• Code Review 時
10
If it stinks,
change it.
—Grandma Beck, discussing child-rearing philosophy
11 “Refactoring: Improving the Design of Existing Code”, Martin Fowler, Kent Beck, et al., 1999
重構標的 — Code Smells
Within Classes
• Comments
• Long Method
• Long Parameter List
• Duplicated Code
• Conditional Complexity
• Large Class
• Uncommunicative Name
• Dead Code
• …
Between Classes
• Primitive Obsession
• Data Clumps
• Refused Bequest
• Indecent Exposure
• Feature Envy
• Lazy Class
• Divergent Change
• Shotgun Surgery
• …
12 http://www.codinghorror.com/blog/2006/05/code-smells.html, Coding Horror: Code Smells, May 18. 2006
怎麼跟老闆講?
• 不用講,做就對了
• 重視品質的老闆
–他會懂你的
• 嘴巴說重視品質的老闆
–說了也是白說
–你真的是在幫他
– The fastest way is to refactor; therefore I refactor. – Martin Fowler
13
什麼時候該停手
• 程式該砍掉重練時 // When I wrote this, only God and I understood what I was doing
// Now, God only knows
• Deadline 前夕
• 夠好了,對你自己、客戶、還有下個_____
–明天會更好
– Striving to better, oft we mar what’s well. – “King Lear” 1.4, William Shakespeare
– Good-Enough Software, “The Pragmatic Programmer”, Andy Hunt, David Thomas
14 http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered
REFACTORING USING ECLIPSE
15
Coding Style
• 確定團隊整體的 Code Style Formatter
–養成常 [Ctrl] + [Shift] + [F] 的習慣
• 輔助確認格式
–以 eclipse-cs 輔助確認
• 同樣要先定義好 Checkstyle 的 Rule
–統一使用 AnyEdit Tools 外掛程式
–在版本管理系統上面掛 pre-commit hook
16
移除 Dead Code
• // Don’t do this! // There was a time, back in the sixties, when // commenting-out code might have been useful.
• // Nowadays, just delete the code // We won’t lose it. Promise.
// Revision control system will remember it.
17 “Clean Code: A Handbook of Agile Software Craftsmanship”, Robert C. Martin, August 2008
移除 Dead Code
• Visibility 要盡可能低
– public > protected > package private > private
18
public void whyNoOneCallsMe() { // Why am I so useless, how can I not be? }
private void whyNoOneCallsMe() { // Why am I so useless, how can I not be? }
http://sourcemaking.com/implementation-patterns/method-visibility, Method Visibility
Dead Code 移除小技巧
• 注意 Reduce Visibility 可能的風險
–介面已經昭告天下時只能 @Deprecated
• Dead Code 不見得都那麼好發現
–不可能跑到的 if else 或 switch case 區塊
–請 PMD, FindBugs 幫忙
• 開始用其他重構技巧吧!
–讓原本的程式更好懂、好修改。
19
Eclipse 1.0 (Nov 2001)
20 圖片提供: https://twitter.com/jiayun
Eclipse 2.0 (Jun 2002)
21 圖片提供: https://twitter.com/jiayun
Eclipse 2.1 (Mar 2003)
22 圖片提供: https://twitter.com/jiayun
Eclipse 3.7 (Jun 2011)
23 圖片提供: https://twitter.com/jiayun
Rename
• 使用時機
–看到不順眼或是無法會意的名字
–有病治病,沒病強身
• 命名原則
–簡單明瞭
–符合 Naming Convention (由 Coding Style 規範)
• 例如: getRgbHex(Colors.SNOW_WHITE)
24
Rename 注意事項
• 要保留住檔案修訂歷程
–裝好 Eclipse Team Provider 再改名
–否則請用 SCM Client 提供的改名功能
25
Rename 小技巧
• 開 Mark Occurrences 功能
• Method 改名可用 Change Method Signature
–如果介面已經公開,請勾 “Keep original method
as delegate to changed method” 選項
26
OutputStream os = new FileOutputStream("test.txt"); try { os.write("test".getBytes()); } finally { os.close(); }
27
改名
維護 相容性
參數名稱、 順序也能改
Extract Local Variable
• 使用時機
–一行程式串太長
–發現對同一個資料物件重複取值
28
new BufferedOutputStream( new FileOutputStream("test.txt"));
authorties = repository.queryAuthorities(user.getName()); LOGGER.debug("User '{}' authenticated.", user.getName());
29
重構 結果
Eclipse 會幫你做的事
Extract Local Variable 注意事項
• Variable 的 Scope 一樣是越小越好
–一般就是 Local Variable 被 Extract 出來的位置
–使用 [Alt] + [↑]/[↓] 可以調整
• Extract 過頭怎麼辦?
– Inline 是 Extract Local Variable 的 inverse。
30 http://www.refactoring.com/catalog/reduceScopeOfVariable.html, Reduce Scope of Variable
int value = getTheAnswerToTheUltimateQuestion(); Result result = new Result(); // <= 要用到再宣告
result.setValue(value); return result;
Extract Local Variable 偷吃步
• 宣告變數並給值少打字
–直接寫右邊的內容
–讓 Eclipse 幫你把左邊的宣告補起來
31
encrypt(data, certificate);
EncyptionResult result = encrypt(data, certificate);
[Alt] + [Shift] + [L]
Extract Method
• 使用時機
– Method 內容過長,超過螢幕能顯示的範圍
–很想幫 Method 裡某個區塊加註解時
• Method 設計原則
–名稱符合 Coding Style
–參數數量不要太多或是型別重複
32
33
// 取憑證 X509Certificate certificate = retrieveCertificates(user); // 資料加密 EncyptionResult result = encrypt(data, certificate);
// 取憑證 X509Certificate certificate; try { String base64Cert = certificateRepository.queryMoicaCertificate user.getUserId(), user.getName(), user.getCounty()); certificate = CertificateUtils.generateCertificate(base64Cert); } catch (CmsException e) { throw new CmsEncryptionException(e.getMessage(), e); } // 資料加密 EncyptionResult result = encrypt(data, certificate);
Method 參數長相是關鍵
• 先 Extract Local Variable,讓 Method 更精確
• 往前多選到 Variable,讓新 Method 更簡單
34
String userId = user.getId(); notifyUser(String userId);
notifyUser(User user);
String userId = user.getId(); notifyUser(String userId);
notifyUser(User user);
Extract Method 偷吃步
• Method 規畫方式
1. 能先想清楚最好
2. 不然先定義參數物件,再慢慢修改其 Property
3. 如果剛好今天沒帶腦,就先寫成一坨,再
Extract Method 出來
• 使用大忌: 不要為了 Extract 而 Extract
–雖然犯錯了一樣可以 Inline 回去
35
Extract Interface
• 使用時機
–發現兩個物件的行為有點像時
–很謙虛,不想暴露太多面向的資訊給使用端時
–有特別的情感因素時
36 http://sourcemaking.com/refactoring/extract-interface, Extract Interface
Extract Interface 注意事項
• 使用 Interface 好處多,不過也是有代價的
–現在 Spring Framework, Mockito…
都能簡單處理 Class,不是非 Interface 不可
• 不用先定義好 Interface
–除非你正在設計要公開的 API
–用到再做都還不遲
37
繼承結構調整
• Extract Superclass
–跟 Extract Interface 有點像,但是包含 Filed 及
Method 實作
• Pull Up
–將 Member 往上層提 (Generalization)
• Push Down
–跟 Pull Up 相反 (Specialization)
38
繼承結構調整 注意事項
• 不是什麼都該繼承來
–有時候用別人家的更划算! (改用 Composite)
–想清楚到底是 Is-A 或是 Has-A
39
Introduce Parameter Object
• 使用時機
– Method 參數過多 (4, 5 個就算不少了)
– Method 參數中有相同的型別
• 範例:
40
getColorName(int red, int green, int blue);
getColorName(Color color);
color.getName()
Extract Class
• 跟 Introduce Parameter Object 異曲同工
• Extract Class 的對象是 Class 裡的 Field
41
public class Employee { private String name; private String officeAreaCode; private String officeNumber; }
public class Employee { private String name; private PhoneNumber officeTel; }
public class PhoneNumber { private String areaCode; private String number; }
Extract Class 小技巧
• 同時選取多個 Class 可以提出共用的 Field
42
public class Employee { private String name; private String officeAreaCode; private String officeNumber; }
public class Employee { private String name; private PhoneNumber officeTel; }
public class Outsourcer { private String contractId; private String officeAreaCode; private String officeNumber; }
public class PhoneNumber { private String areaCode; private String number; }
public class Outsourcer { private String contractId; private PhoneNumber officeTel; }
Try to
leave this world
a little better than
you found it. –Baden-Powell
43
REFERENCES
44
參考資料
• “Refactoring: Improving The Design of Existing code”, Martin Fowler, Kent Beck, John Brant, William Opdyke, and Don Roberts, 1999
• Code Smells - Jeff Atwood
– http://www.codinghorror.com/blog/2006/05/code-smells.html
• Web 程式重構 – Jace Ju
– http://www.slideshare.net/jaceju/web-1494836
45
延伸閱讀
• 如何成為更好的 PHP 開發者 – Jace Ju
– https://speakerdeck.com/jaceju/how-to-be-a-better-
php-developer
• 27 inspiring top notch programming quotes
– http://www.marcofolio.net/tips/27_inspiring_top_n
otch_programming_quotes.html
46
可參考的書籍
• “Refactoring: Improving The Design of Existing code”, Martin Fowler, Kent Beck, John Brant, William Opdyke, and Don Roberts, 1999
– 《重構 – 改善既有程式的設計 第二版》 侯捷、熊節 譯
– http://sourcemaking.com/refactoring
• “Refactoring to Pattterns”, Joshua Kerievsky, 2004
– 《重構 – 向範式前進》侯捷、陳裕城 譯
• “Java言語で学ぶ リファクタリング入門”, 結城 浩, 2007
– 《Java 重構》江珮齡、王元綱、博碩文化 譯
47