Java Programming Hygiene - for DIDC 廖峻鋒 June 2,2004 NCCU Computer Center
Introduction Following figures are selected from the book “Anti-Patterns” by William J. Brown et al.
權威式管理
主管過份簡化問題
不相信也不願意「Reuse」
太驕傲
喜歡把簡單的事情弄複雜
Programming Hygiene Programming Hygiene was proposed by Bruce Tate in Bitter Java.(Chapter 9) Establishing a good coding style standard in a company helps to prevent anti-patterns.
Bad smells 當我們發現程式碼中有「不好」的寫法時,我們會說這段程式碼很臭(bad smell)。 資深的程式設計師可以很容易地察覺Bad Smell,Peer Review也可以幫助我們找出Bad Smell Bad Smell就是重構下手的主要對象。
什麼是品質好的程式碼 ? (by Kent Beck) 容易閱讀 大部份的變異可以在同一個地方改動 新的改動不易讓程式爛掉 條件邏輯應儘可能簡單
建立共同的編程風格標準 在XP中採用共同的Code Convention名列十二項核心務實作法之一。 After Gold Rush : 現在的軟體界是團隊作戰的時代,團隊中一位功力很強但作風特立獨行的軟體工程師可能反而對軟體開發造成傷害。 透過Peer Review,工程師間互相討論良好的設計方式。
A code compiled without error Class Product {int price = 50;public void setPrice(int price) { …(50行code) int i = price; …(50行code)}}
Class Product { int price = 50; public void setPrice(int price) { } // …(50行code) int i = price; // which price ? // 案蠀ق0行code) }
class Product { int defaultPrice = 50; public void setPrice(int price) { // …(50行code) int i = price; // which price ? // …(50行code) }
Another Example
不要忽視Coding Style 程式、註解風格及變數命名方式若能一致,對開發團隊的效率有很大幫助。 程式設計師仍有很大的自由創造空間。 Code Style嚴重影響程式碼的品質。
Java 的程式慣例 Java早有官方版本的程式慣例 Java的程式慣例已廣泛被採用 Java Language: J2EE: JSP: http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html J2EE: http://java.sun.com/blueprints/code/namingconventions.html JSP: http://developer.java.sun.com/developer/technicalArticles/javaserverpages/code_convention/ Java的程式慣例已廣泛被採用 從JDK的source code開始,到所有範例程式碼,都完全配合這個convention。連OpenSource 的Java程式也幾乎都是按照這裏所規定的Style來寫程式
.NET的程式慣例 .NET目前沒有官方版本的程式慣例。 目前已有社群參考Java的程式慣例規格書格式開始制定Coding Style。 在開發社群中最廣泛被採用及認同的版本http://www.icsharpcode.net/TechNotes/
Deprecated Naming Conventions The following naming convention are considered as bad practice (include Microsoft)! Hungarian 傳統windows程式及win32 API大量採用。 把型別加在變數的最前面。 例如sName表示string 型別。 Under score 若變數超過一個字,用“_”分隔。 在c語言中常用。 stu_num、 reg_sts。
目前通用的命名慣例 Pascal Notation Camel Notation 首字大寫 例如:EventHandler、XmlDocument等等。 Camel Notation 首字小寫,後續大寫。 例如:userId、dayOfWeek、studentName等等。 Visual Studio.NET所產生的程式碼不符合Naming Convention。 事件處理函式仍有under score 介面仍用Hungarian,例如IEnumberable
命名範例 一個功能是「取消」的Button。 有顏色的多邊形 儲存分享資料的地方 縮寫 btnCancel -> cancelButton 有顏色的多邊形 ColoredPolygon 儲存分享資料的地方 ServletContext、BCSSContext 縮寫 HttpServlet、URLConnection
Comments
相關文件 C# Coding Style Guide The fine Art of Commenting Technical Writing made easier
Refactoring 重構是什麼? 改善程式碼的一種方法論。 對軟體內部結構的一種調整,在不改變「外部可觀察到的行為」的前提下,提高軟體的可理解性,降低修改成本。 如何確保「外部可觀察到的行為」不變Unit Testing!
重構時不會影響到程式之外顯行為 外部使用的類別對其變化沒有感覺
重構幫助設計師看到 設計層面的問題 M.Fowler : “隨著程式碼漸趨簡潔,我發現自己可以看到一些以前看不到的設計層面的東西。如果不對程式碼做這些修改,也許我永遠看不到他們,因為我的聰明才智不足以在腦子裏把這一切都想像出來。” Ralph Johnson : 擦掉窗戶上的污垢,使你看得更遠。
為何要重構? 不重構軟體很快就會爛掉 增進可重用性 [Gof95]Design Patterns為重構提供了目標。 有機會做抽象化並找出Framework。 Lets you worry about generality tomorrow; (可以不需要在一開始就寫出漂亮的程式,可以先開發再重構)
何時要進行重構? The rule of three 功能增加時。 修補Bug時。 Code Review之後。 完成一個功能之後,又察覺bad smell時。
如何重構 一次一小步:Make changes as small as possible. Many small changes are easier than one big change. 每次改變都要測試:Test after each change.
二種不同型式的重構 Visible refactoring Invisible refactoring
Visible refactoring 重構的改變在UML圖上看得到
Invisible refactoring 使用Collection取代多重if敘述 String foundPerson(String[] people){ for (int i = 0; i < people.length; i++) { if (people[i].equals ("Don")){ return "Don"; } if (people[i].equals ("John")){ return "John"; } if (people[i].equals ("Kent")){ return "Kent"; } } return ""; } String foundPerson(String[] people){ List candidates = Arrays.asList(new String[] {"Don", "John", "Kent"}); for (int i=0; i<people.length; i++) if (candidates.contains(people[i])) return people[i]; return ""; } 重構的改變在UML圖上看不到
Bad Smell Examples Duplicate Code Long Methods Large Classes Long Parameter Lists Too Many Case Statements 程式變數命名不良。 程式沒有根據Code Standard。 過多的註解。
Duplicate code 重複的程式碼出現在不同的地方多次。 如何解決 ? making new methods making new objects moving methods to common superclass
Long methods 一個Method應該只負責一項任務 Method should fit on the screen. Method should be in right class.
Large classes More than 7 variables More than 15 methods You probably need to break up the class 可使用一些Design Patterns手法解決 (Strategy, Composite, Decorator)
Long parameter lists 參數數目若超過4個就太多了! If you see the same set of parameters repeated in several methods, bundle them into a new object. (將相關的參數化成新類別)
Case Statements 使用多型加上Collection取代多重if或switch敘述。 使用Strategy Pattern。
重構:An Example 客戶類別 IfxDB 客戶類別 IfxDB ConnectionManager (詳見下頁) DB1 DB2
ConnectionManager
大型重構
Q & A Slides and documents available at http://java.cc.nccu.edu.tw