天天看點

重構一個功能塊的總結

因為Leader不建議占用上班時間搞這個,基本上都是加班搞的

在做這個事的過程中,對IntelliJ idea更加熟悉,回顧下Mocikitto中spy,mock,verify,when的使用,這次重構基本上是小步快走,層層分離

IntelliiJ idea:

重構手法:如果想把一個方法移動到另一個class中,可以通過method增加一個Class類型的參數,然後将光标放在方法名的任何字元上【若選中方法名,則F6會失效】,按F6,在彈出的對話框中選擇預期的Class【因為這個方法的參數是其它類型的對象】

更改方法的參數個數時,可以會調用處更改,從上往下進行,或按Ctrl+F6在調用的GUI界面操作。IntelliJ Idea的自動操作往往留一些尾巴,譬如,删除一個構造函數的一個參數,參數指派的字段和構造中指派語句不會自動删除。

如果方法參數有多個,且參數類型差别不大,IntelliJ idea alt+Enter提供的修改可能是錯誤的,譬如你删除了第5個參數,Idea可能會把第4個參數删除了,然後更改實際函數中的參數名,造成參數錯位,就會編譯報錯,這種情況建議使用Ctrl+F6的GUi界面來操作。

把一個方法通過F6移動到另一個Class時,Move操作成功後,移過去的方法如果使用了原來Class中的字段,就會編譯不過。這種情況不用擔心,一般的步驟是先移動,然後解決編譯報錯。

移動方法時,方法增加的Class一般不選擇抽象方法,這樣會把方法移動到抽象方法中,正确的做法是,增加的類型參數是預期的抽象類的子類,這樣就可以了

在建工廠類或接口時,可以先寫Class Name,然後使用Idea的快捷鍵來建立Class,Interface,Method,Field

去除if else 的常用方法是每個分支就是一個對象,然後實作相同的接口;把if else分支的判斷邏輯放到Factory類,這樣代碼就清淨了。

擴充性和可維護性都增加了,擴充性:如果增加或減少一種場景,隻修改工廠類或增加或删除新類即可,與此不相關的場景不會影響 ,不用知道其它情景的實作,也不用重新測試這些沒有涉及的場景。

并且 業務邏輯和每個場景都可以獨立寫測試用例。如果有重複代碼,不僅看得見,更能去得掉。重複代碼抽取到父類中即可。也可以定義一個接口,抽象類來實作,業務類再繼承抽象類。重複的字段或方法放在抽象類中。

Idea中的快捷鍵:

Ctrl+Alt+F12:打開某個package;

Ctrl+F12:打開File Structure

Ctrl+Alt+B:接口的實作類,抽象類的子類

Alt+F7:查找使用字段,方法

Ctrl+E:最近使用的檔案,在F6移動操作時很有用

Ctrl+Alt+LeftArrow鍵:上一個操作代碼位置。很遺憾,遠端桌面中無法使用,隻能使用滑鼠點選工具欄上的按鈕

Ctrl+Shift:移動方法或字段或語句

在equals方法的左或右邊的對象上按Alt+Enter,會出現Flip,來互換

Ctrl+B轉到定義處,再按Ctrl+B,傳回

Alt+insert:構造函數,get,set,overrider

Ctrl+Alt+T:surround with try catch

在方法或類上按Ctrl+shift+T,用來建立測試用例

Ctrl+P:檢視方法參數

Ctrl+Q:檢視API

Shift+F6:重命名

Ctrl+Alt+n:内聯,即獨立的方法整合到調用中,被内聯的方法就去掉了

在進行重構操作的Class代碼中按Ctrl+Z,即可undo剛才的操作

compare with clipboard:先複制一段文本,然後在idea中選中一段文字,在選中文字上右鍵,選“Compare with clipboard”即可比較,identical:相同的,一緻的

Ctrl+Shift+F9:compile,要做中Module或Project,光标在一個Class檔案中,就會隻編譯這個檔案,如果引用其它非APIclass,則編譯不過

Idea中有在跑測試用例,編譯Module或Project時,才會發現哪些Class中沒有編譯過。送出代碼前一定要先編譯下或先跑下測試用例

git:

git fetch//擷取origin上的更新

git merge//和本地代碼合并,如果有clifict,還要resolve才能送出

git add <some files>//暫存資料(辨別要commit的本地所有檔案),.代表所有本地檔案(除了ignore檔案中辨別的)。也可以add指定檔案名的單個檔案

git status -s//檢視本地倉庫的修改狀态,如果沒有輸出,說明沒有需要送出的。

git commit -m "注釋"//送出到本地倉庫

git push origin master//送出到git伺服器origin的master分支

git branch//檢視

git log --oneline -5

測試用例中mock使用的回顧:

spy,如果不想執行spy的方法,就使用doReturn,不然,被spy的方法還會被執行

直接貼個例子吧,

累并充實着吧。

就想起這麼多了  

再總結一下,上面去除if else的重構過程,是LSP的一個展現,即父類出來的地方,都可以用子類替代

測試用例的書寫原則,對象完成一個行為後,肯定要改變什麼,通過IO操作改變了外設上的資料、改變了對象的狀态,測試用例隻需要覆寫變化即可。

被測對象中的行為在執行時,使用了其它對象A,對象A中有些API的使用,導緻無法正常寫測試用例,這種場景,需要将對象A注入到被測對象,即給被測對象增加一個協作者,因為被測對象的行為不能單獨完成。

多用組合,少用繼承。組合時,注入需要協作的對象,即可友善寫測試用例。

新增對象時,一般會采用set方法而不在constructor中新增一個入參,這樣改動最小,對已有對象影響最小。

LSP:

1.概述: 派生類(子類)對象能夠替換其基類(父類)對象被調用

2.概念:

裡氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 裡氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。 LSP是繼承複用的基石,隻有當衍生類可以替換掉基類,軟體機關的功能不受到影響時,基類才能真正被複用,而衍生類也能夠在基類的基礎上增加新的行為。裡氏代換原則是對“開-閉”原則的補充。實作“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實作,是以裡氏代換原則是對實作抽象化的具體步驟的規範。(源自百度百科)

3.子類為什麼可以替換父類的位置?:

當滿足繼承的時候,父類肯定存在非私有成員,子類肯定是得到了父類的這些非私有成員(假設,父類的的成員全部是私有的,那麼子類沒辦法從父類繼承任何成員,也就不存在繼承的概念了)。既然子類繼承了父類的這些非私有成員,那麼父類對象也就可以在子類對象中調用這些非私有成員。是以,子類對象可以替換父類對象的位置。

4.裡氏代換原則優點:

需求變化時,隻須繼承,而别的東西不會改變。由于裡氏代換原則才使得開放封閉成為可能。這樣使得子類在父類無需修改的話就可以擴充。