Re: [討論] 主管不認同書本的知識,說我沒學好程設

看板Soft_Job作者 (寵物狼音樹)時間9年前 (2016/05/08 18:32), 編輯推噓1(101)
留言2則, 2人參與, 最新討論串10/14 (看更多)
繼續占版面分享少許心得。 在Python中也有類似直接指定參數的寫法,如: book_preservation = BookPreservation(user_name="Jack",...) 如果這些參數只是單純指定進去當作fields的話, 的確這樣的寫法就夠用了:) 下面分享一下這個重構手法的第3個好處: 3. 容易因此將相關功能移入新造的class中,改善程式碼分工 假設在我們的租書店程式中,在caller端有以下程式碼: class PreservationChecker{ void checkPreservation( String userName, String userId, String startTime, String endTime){ BookPreservation bookPreservation = new BookPreservation( "Jack", "1433717", "2016/5/8", "2016/8/8"); if(!isInTime( bookPreservation.getStartTime(), bookPreservation.getEndTime())){ return; } // 其他動作 } boolean isInTime(String startTime, String endTime){ Calendar calendar = Calendar.getInstance(); // 檢查過程 return result; } // 其他 methods } 透過上一篇文章中提到的重構手法,我們可以得到以下程式碼: class PreservationChecker{ void checkPreservation( String userName, String userId, String startTime, String endTime){ TimePeriod timePeriod = new TimePeriod("2016/5/8", "2016/8/8"); BookPreservation bookPreservation = new BookPreservation( new User("Jack", "1433717"), timePeriod); if(!isInTime( timePeriod.getStartTime(), timePeriod.getEndTime())){ return; } // 其他動作 } boolean isInTime(String startTime, String endTime){ Calendar calendar = Calendar.getInstance(); // 檢查過程 return result; } // 其他methods } 以及2個根據參數關係所分離出來的class: User與TimePeriod。 接下來,因為caller端的程式碼可能已經太多了, 或是在其他地方也有使用到TimePeriod的時間檢查, 好比說、可能另外有個租書店用來舉辦活動的程式碼, 用來檢查今天是不是應該給客人30元優惠: class FesCoupon{ private String startTime; private String endTime; double getCouponAmount(){ if(!isInTime( this.getStartTime(), this.getEndTime())){ return 0; } return 30; } // 以下是重複碼 boolean isInTime(String startTime, String endTime){ Calendar calendar = Calendar.getInstance(); // 檢查過程 return result; } } 因為我們先前把BookPreservation的2個時間相關參數, 透過Extract Class,得到了TimePeriod這個class, 我們現在就可以把重複碼isInTime()放進去,得到: class TimePeriod{ private String startTime; private String endTIme; boolean isInTime(){ Calendar calendar = Calendar.getInstance(); // 檢查過程 return result; } } 然後、上述兩個引用點就可以精簡為: class PreservationChecker{ void checkPreservation( String userName, String userId, String startTime, String endTime){ TimePeriod timePeriod = new TimePeriod("2016/5/8", "2016/8/8"); BookPreservation bookPreservation = new BookPreservation( new User("Jack", "1433717"), timePeriod); if(!timePeriod.isInTime()){ return; } // 其他動作 } // 其他methods } class FesCoupon{ private TimePeriod timePeriod; double getCouponAmount(){ if(!timePeriod.isInTime()){ return 0; } return 30; } } 如此, ① 不僅消除了2個caller class當中的重複碼, ② 也將isInTime()這個methods放到了與最相關的class當中(也就是TimePeriod)。 即使在支援直接指定參數寫法的語言,如Python中, 也能因為這個重構手法,而獲得以上2個改善的好處。 ※ 引述《leicheong (睡魔)》之銘言: : ※ 引述《ADYex (寵物狼音樹)》之銘言: : : 例如,假設在一個租書店的程式中有以下程式碼: : : BookPreservation bookPreservation = new BookPreservation( : : "Jack", "1433717", "2016/5/8", "2016/8/8"); : : 其中4個參數分別為 userName, userId, startTime, endTime, : : 比較好的作法是將各自相關聯的參數各自包裝,變成: : : BookPreservation bookPreservation = new BookPreservation( : : new User("Jack", "1433717"), new TimePeriod("2016/5/8", "2016/8/8")); : : 這個重構手法能帶來的好處如下: : : 1. 提升可讀性 : : 2. 未來維護簡單 : : 3. 容易因此將相關功能移入新造的class中,改善程式碼分工 : : 試著像這樣將原作法的壞處與新作法的好處跟主管說看看吧。或是塊陶。 : 這個的話還需要看在用甚麼程式語言吧. : 像在VB和C# v4+上也可以這樣寫: : BookPreservation bookPreservation = new BookPreservation( : userName: "Jack", : userId: "1433717", : startTime: "2016/05/08", : endTime: "2016/08/08"); : 這樣寫比分拆成用property設定更好. 也是你之前說的「在初始化時設定」 : 和「先全部初始化成null, 在建構完成後再設定」的差別. -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.231.166.119 ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1462703532.A.A73.html

05/08 18:35, , 1F
雖然是用Java舉例,希望這樣看得懂在其他語言中的適用性 :P
05/08 18:35, 1F

05/09 00:49, , 2F
05/09 00:49, 2F
文章代碼(AID): #1NBnMifp (Soft_Job)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 10 之 14 篇):
文章代碼(AID): #1NBnMifp (Soft_Job)