重構:仔細檢視 改進程式碼
我建議你進行一個練習:當你第二天早晨開始工作的時候,重新審視你的專案原始碼,嘗試發現進行重構的機會。就算你的領導沒有要求,仍然去做。因為在工作中,你希望有一些激動人心的時候。
重構是一門改變已經正常的工作的藝術。但是重構是需要理由的。可能是設計改進,效能問題,安全形色或者很多其他的原因。改程式序的技術缺點是要冒風險的,儘管能夠使其更穩定,並且可能能夠提高你自己今後的生產力。
這不是為了公司或者領導好,而是為了自己。為什麼?因為問題都是逐漸累積的,到達一個程度之後,你會失去對程式碼的控制。你將會面對苦於交付結果的境地,最終可能毀掉你的職業生涯。
好吧,讓我們從一個更加積極的角度來看這個問題。在重構過程中你會學習到很多,並且很快意識到你產出了比之前更好的程式碼。重構越多,你就越聰明,慢慢累積直到你達到創新的級別。但是這意味著什麼,你又如何知道你達到了呢?
當你發現一個明顯的機會來對你當前的工作進行改進,並且你意識到至今為止還沒有別人做過這樣的事情(至少你找不到)。這不容易,這不容易,但這常發生在你不斷重複做一件事情,並且你能夠發現你如何能夠使得同樣的事情做得又快又好。讓我用一個真實的故事來說明。
例子是在Java中進行字串連線:一個經典問題,曾經在過去數年困擾了大量專家,但在今天可能已經被忽略了。在JDK1.5之前,儘管可讀性高而且簡單,但使用“+”來進行字串連線可能產生效率極低的程式碼。之後,“+”操作符被換成了StringBuffer,從而真正改進了連線。使用“+”越多,則在記憶體中的String和StringBuffer例項越多,為了管理所有的物件花費的時間也越多。因此,開發者們被推動使用StringBuffer而忽略“+”。看下面的例子:
String title = "Mr."; String name = "John"; String familyName = "Smith"; String message = "Dear " + title + " " + name + " " + familyName + ",";
開發者習慣於這樣寫程式碼,但是現在被推動這麼做:
StringBuffer sb = new StringBuffer(); sb.append("Dear "); sb.append(title); sb.append(" "); sb.append(name); sb.append(" "); sb.append(familyName); sb.append(",");
你可能同意第一個例子可讀性高於第二個。開發者使用“+”進行字串連線時很自然的,所以丟棄這樣的形式不合適。好訊息是,編譯人員做了一些事情來維護這樣的習慣,確保了JDK1.5會優化連線方法。代替執行緒安全的StringBuffer,他們建立了一個叫做StringBuilder(非執行緒安全,但更快)的類,並且他們確保能夠像第一個例子中那樣,使用一個例項就能處理所有的連線。這是一個很重要的進步,因為他們兼顧了簡潔而不單純是技術性。第一個例子在編譯時會自動轉換成如下情況:
StringBuilder sb = new StringBuilder(); sb.append("Dear ").append(title).append(" ") .append(name).append(" ").append(familyName) .append(",");
但是,在一些複雜邏輯程式碼中的字串連線還是需要使用StringBuilder,因為編譯器還沒有那麼智慧,例如:
List<Student> students = studentBean.findStudents(); String intro = "The following students were approved:\n"; String listedNames = ""; String separator = ""; for(Student student: students) { if(student.approved()) { if(!listedNames.isEmpty()) { separator = ", "; } listedNames += separator + student.getName(); } } String msg = intro + listedNames; messengerBean.sendMessage(msg);
如下寫法會更有效率:
List<Student> students = studentBean.findStudents(); String intro = "The following students were approved:\n"; StringBuilder listedNames = new StringBuilder(); String separator = ""; for(Student student: students) { if(student.approved()) { if(!listedNames.length() > 0) { separator = ", "; } listedNames.append(separator) .append(student.getName()); } } String msg = intro + listedNames.toString(); messengerBean.sendMessage(msg);
呃!你注意到有什麼奇怪的東西了麼?可能一眼看起來不是很明顯,但是看看他們是如何在定義分隔符之前檢查listedNames是否為空的。String類在JDK1.6中有一個可讀性很好的方法isEmpty(),但是StringBuilder仍然使用相對比較老的方式。為什麼他們不將StringBuilder 和 StringBuffer改為同樣的方式呢?
在核心庫開發的郵件列表中討論了這個問題,沒有發現什麼明顯原因導致他們之前沒有這麼做。可能只是忘記了。要感謝大規模的重構,試圖改進效率低下的字串連線方法,才能發現這樣的不一致。我相信在明年推出的Java8中會有時間修復這個問題。只要在介面CharSequence加入isEmpty()方法,這樣就能使得所有實現都變得同樣優雅。
這可能是一件簡單的事情,但是Java是一個嚴格審查下的複雜的語言,所以每個細節都會帶來很大的影響。所以,做一些重構,發現一些改進程式碼的機會,同樣也能夠改進你使用的程式語言。讓我們一起推動Java進步吧!
英文原文:Java Code Geeks
相關文章
- 【轉】改變檢視頁面原始碼的程式原始碼
- 程式碼重構--大話重構
- 程式碼重構
- 程式碼重構之法——方法重構分析
- “硬核”程式碼重構
- 重構 PHP 程式碼PHP
- PHP程式碼重構PHP
- 程式碼重構(四)
- 將預設檢視改為“文件結構圖”
- 程式碼重構與單元測試——對方法的引數進行重構(五)
- 在SQL Server中對檢視進行增刪改SQLServer
- 重構遺留程式碼(6):進攻複雜的方法
- 程式碼重構技巧(二)
- 談談程式碼重構
- 【讀程式碼重構有感】
- 重構:程式碼異味
- Java程式設計細節-重構-為什麼 if-else 不是好程式碼Java程式設計
- 如何改進你的指令碼程式指令碼
- [譯] 重寫 loadView() 方法使 Swift 檢視程式碼更加簡潔ViewSwift
- 程式碼重構:類重構的 8 個小技巧
- .NET重構—單元測試的程式碼重構
- 實際業務中使用策略模式對程式碼進行重構模式
- 程式碼重構那些事兒
- 重構你的javascript程式碼JavaScript
- 重構 - 程式碼優化技巧優化
- 日記9(程式碼重構)
- 重構 - 程式碼整潔之道
- 重構之提煉程式碼
- 重構改善既有的程式碼設計(重構原則)
- 程式碼重構:函式重構的 7 個小技巧函式
- 一個利用正規表示式進行程式碼重構,去除冗餘程式碼的例子行程
- 整合多種YOLO改進點,面向小白科研的YOLO檢測程式碼庫YOLOAirYOLOAI
- 程式碼重構與單元測試——“提取方法”重構(三)
- 程式碼維護:改進程式碼的一些方法 (轉)
- Oracle 物化檢視 詳細錯誤描述 檢視方法Oracle
- 重構程式碼(應如寫詩)
- 程式碼的壞味道和重構
- 記一次程式碼重構