code refactoring using eclipse

47
用 Eclipse 重構程式碼 Code Refactoring Using Eclipse 中華電信 黃培棠 [email protected] 2013/02/26

Upload: pei-tang-huang

Post on 13-May-2015

1.651 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Code refactoring using eclipse

用 Eclipse 重構程式碼 Code Refactoring Using Eclipse

中華電信 黃培棠

[email protected]

2013/02/26

Page 2: Code refactoring using eclipse

WHAT IS REFACTORING?

2

Page 4: Code refactoring using eclipse

𝑥2 − 1 = 𝑥2 − 𝑥 + 𝑥 − 1= 𝑥 𝑥 − 1 + 𝑥 − 1= 𝑥 + 1 (𝑥 − 1)

4

循序漸進, Re-

不影響外部行為

Page 5: Code refactoring using eclipse

怎麼證明?

• 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!

Page 6: Code refactoring using eclipse

重構前… 重構後…

6

重構是 Programmer 自爽的事?

Page 8: Code refactoring using eclipse

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

Page 9: Code refactoring using eclipse

WHEN TO REFACTORING?

9

Page 10: Code refactoring using eclipse

重構的好時機

• 一樣的事做到第三次時

• 按下「貼上」前

• 要新增功能時

• 開始修 Bug 前

• Code Review 時

10

Page 11: Code refactoring using eclipse

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

Page 12: Code refactoring using eclipse

重構標的 — 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

Page 13: Code refactoring using eclipse

怎麼跟老闆講?

• 不用講,做就對了

• 重視品質的老闆

–他會懂你的

• 嘴巴說重視品質的老闆

–說了也是白說

–你真的是在幫他

– The fastest way is to refactor; therefore I refactor. – Martin Fowler

13

Page 14: Code refactoring using eclipse

什麼時候該停手

• 程式該砍掉重練時 // 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

Page 15: Code refactoring using eclipse

REFACTORING USING ECLIPSE

15

Page 16: Code refactoring using eclipse

Coding Style

• 確定團隊整體的 Code Style Formatter

–養成常 [Ctrl] + [Shift] + [F] 的習慣

• 輔助確認格式

–以 eclipse-cs 輔助確認

• 同樣要先定義好 Checkstyle 的 Rule

–統一使用 AnyEdit Tools 外掛程式

–在版本管理系統上面掛 pre-commit hook

16

Page 17: Code refactoring using eclipse

移除 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

Page 18: Code refactoring using eclipse

移除 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

Page 19: Code refactoring using eclipse

Dead Code 移除小技巧

• 注意 Reduce Visibility 可能的風險

–介面已經昭告天下時只能 @Deprecated

• Dead Code 不見得都那麼好發現

–不可能跑到的 if else 或 switch case 區塊

–請 PMD, FindBugs 幫忙

• 開始用其他重構技巧吧!

–讓原本的程式更好懂、好修改。

19

Page 20: Code refactoring using eclipse

Eclipse 1.0 (Nov 2001)

20 圖片提供: https://twitter.com/jiayun

Page 21: Code refactoring using eclipse

Eclipse 2.0 (Jun 2002)

21 圖片提供: https://twitter.com/jiayun

Page 22: Code refactoring using eclipse

Eclipse 2.1 (Mar 2003)

22 圖片提供: https://twitter.com/jiayun

Page 23: Code refactoring using eclipse

Eclipse 3.7 (Jun 2011)

23 圖片提供: https://twitter.com/jiayun

Page 24: Code refactoring using eclipse

Rename

• 使用時機

–看到不順眼或是無法會意的名字

–有病治病,沒病強身

• 命名原則

–簡單明瞭

–符合 Naming Convention (由 Coding Style 規範)

• 例如: getRgbHex(Colors.SNOW_WHITE)

24

Page 25: Code refactoring using eclipse

Rename 注意事項

• 要保留住檔案修訂歷程

–裝好 Eclipse Team Provider 再改名

–否則請用 SCM Client 提供的改名功能

25

Page 26: Code refactoring using eclipse

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(); }

Page 27: Code refactoring using eclipse

27

改名

維護 相容性

參數名稱、 順序也能改

Page 28: Code refactoring using eclipse

Extract Local Variable

• 使用時機

–一行程式串太長

–發現對同一個資料物件重複取值

28

new BufferedOutputStream( new FileOutputStream("test.txt"));

authorties = repository.queryAuthorities(user.getName()); LOGGER.debug("User '{}' authenticated.", user.getName());

Page 29: Code refactoring using eclipse

29

重構 結果

Eclipse 會幫你做的事

Page 30: Code refactoring using 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;

Page 31: Code refactoring using eclipse

Extract Local Variable 偷吃步

• 宣告變數並給值少打字

–直接寫右邊的內容

–讓 Eclipse 幫你把左邊的宣告補起來

31

encrypt(data, certificate);

EncyptionResult result = encrypt(data, certificate);

[Alt] + [Shift] + [L]

Page 32: Code refactoring using eclipse

Extract Method

• 使用時機

– Method 內容過長,超過螢幕能顯示的範圍

–很想幫 Method 裡某個區塊加註解時

• Method 設計原則

–名稱符合 Coding Style

–參數數量不要太多或是型別重複

32

Page 33: Code refactoring using eclipse

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);

Page 34: Code refactoring using eclipse

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);

Page 35: Code refactoring using eclipse

Extract Method 偷吃步

• Method 規畫方式

1. 能先想清楚最好

2. 不然先定義參數物件,再慢慢修改其 Property

3. 如果剛好今天沒帶腦,就先寫成一坨,再

Extract Method 出來

• 使用大忌: 不要為了 Extract 而 Extract

–雖然犯錯了一樣可以 Inline 回去

35

Page 36: Code refactoring using eclipse

Extract Interface

• 使用時機

–發現兩個物件的行為有點像時

–很謙虛,不想暴露太多面向的資訊給使用端時

–有特別的情感因素時

36 http://sourcemaking.com/refactoring/extract-interface, Extract Interface

Page 37: Code refactoring using eclipse

Extract Interface 注意事項

• 使用 Interface 好處多,不過也是有代價的

–現在 Spring Framework, Mockito…

都能簡單處理 Class,不是非 Interface 不可

• 不用先定義好 Interface

–除非你正在設計要公開的 API

–用到再做都還不遲

37

Page 38: Code refactoring using eclipse

繼承結構調整

• Extract Superclass

–跟 Extract Interface 有點像,但是包含 Filed 及

Method 實作

• Pull Up

–將 Member 往上層提 (Generalization)

• Push Down

–跟 Pull Up 相反 (Specialization)

38

Page 39: Code refactoring using eclipse

繼承結構調整 注意事項

• 不是什麼都該繼承來

–有時候用別人家的更划算! (改用 Composite)

–想清楚到底是 Is-A 或是 Has-A

39

Page 40: Code refactoring using eclipse

Introduce Parameter Object

• 使用時機

– Method 參數過多 (4, 5 個就算不少了)

– Method 參數中有相同的型別

• 範例:

40

getColorName(int red, int green, int blue);

getColorName(Color color);

color.getName()

Page 41: Code refactoring using eclipse

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; }

Page 42: Code refactoring using eclipse

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; }

Page 43: Code refactoring using eclipse

Try to

leave this world

a little better than

you found it. –Baden-Powell

43

Page 44: Code refactoring using eclipse

REFERENCES

44

Page 45: Code refactoring using eclipse

參考資料

• “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

Page 47: Code refactoring using eclipse

可參考的書籍

• “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