本文是BUAA OO課程Unit1在課程講授、三次做業完成、自測和互測時發現的問題,以及傾聽別人的思路分享所引發我的的一些思考的總結性博客。本文第二部分介紹三次做業的設計思路,主要以類圖的形式展示,並有簡單的優劣分析;第三部分爲程序代碼複雜度的分析(2、三兩部分爲基於度量的對本身程序結構的分析);第四部分爲對本身、對他人程序的測試、DEBUG、Hack的思考;第五部分是分析做業中能夠應用對象建立模式的可能性,和重構的思考。正則表達式
這三次做業我基本上採用了徹底不一樣的方法,感受到其實很是有趣而且頗有收穫。express
第一次做業的時候個人全部代碼都在一個.class文件內,設計了一個沒有什麼意義的主類Derivation,包含了一個多項式類和一個單項式類。這種設計除了在文件管理上不容易丟失文件之外基本沒有什麼好處。第二次和第三次做業中代碼才愈來愈面向對象。第三次中有一些體現抽象工廠的設計,使用了Factor接口和Item抽象類,顯然第三次做業的程序更具備可擴展性。實際上我在第二次做業中就有意識地在下降模塊的耦合以方便單元測試。數組
第二次和第三次的做業實際上採用了不一樣的設計思路,主要在於第二次是爲了提升對輸出優化處理的可擴展性,第三次是爲了提升支持輸入的項的類型的可擴展性。第二次中的對象保存的是對一個多項式的各類處理方法,而第三次的對象保存的是多項式的各類組成成分。這兩個程序一個在怎麼處理產品的方法上有較好擴展性,一個在能處理的產品種類上有較好擴展性。此外,第三次做業我嘗試直接使用字符串來保存數據,無心中使用了Creative Pattern。前兩次做業中,會牽涉到對象的拷貝等,容易發生錯誤,某些對象的方法可能不具備可再現性,引入不安全性而且不利於單元測試;第三次做業中,因爲沒有計劃作詳細的優化,使用了直接進行字符串操做的簡化設計,但很是不利於優化。此外,前兩次做業使用的容器還較爲傳統(定長數組),不利於利用現有的包進行合併同類項優化而本身寫了優化的方法,雖然實現簡單,可是也浪費了空間資源。安全
從三次做業來看,代碼結構的基本複雜度、模塊複雜度和圈複雜度呈現明顯的逐次降低趨,體現出個人程序更加結構化、模塊化,這有利於代碼的理解和結構化、模塊化的維護、測試和功能擴展;各模塊之間耦合度下降,有利於模塊的隔離、維護和複用;程序獨立路徑的數量也在減小,則出現錯誤的概率會下降,亦有利於測試和維護。模塊化
123 "|\\d+)[ \t]*)*[ \t]*";
123 "|\\d+)[ \t]*)*+[ \t]*";
47 boolean canOptimizeWith(Monomial m) { 48 return ((this.power.equals(m.power) && 49 (this.sinPower.equals( 50 m.sinPower.add(new BigInteger("2"))) 51 && m.cosPower.equals( 52 this.cosPower.add(new BigInteger("2")))) 53 || (this.cosPower.equals( 54 m.cosPower.add(new BigInteger("2"))) 55 && m.sinPower.equals(this.sinPower.add(new BigInteger("2"))))))); 56 }
48 return (this.power.equals(m.power) && 55 this.cosPower.add(new BigInteger("2")))
47 public void optimize() { 48 if (super.getData().matches(".*\\^0*1")) { 49 setData(getData().replaceAll("\\^0*1", "")); 50 } else if (super.getData().matches(".*\\^0*")) { 51 setData("1"); 52 } 53 }
47 public void optimize() { 48 if (super.getData().matches(".*\\^0*1")) { 49 setData(super.getData().replaceAll("\\^0*1", "")); 50 } else if (super.getData().matches(".*\\^0*")) { 51 setData("1"); 52 } 53 }
我互測中遇到的BUG主要是對數據的輸入處理的問題,例如未判斷正負號使用是否正確就先去除了重複的正負號,或者在正則表達式中使用「\s」從而引入了不容許的特殊字符的可能性,或者某些位置應該容許輸入多個空格只容許了單個。還有對不完整的輸入,好比「+x+」,"45*"等沒有進行判斷。第三次做業中,還有同窗沒有使用BigInteger處理數據,或者對指數爲000000000000000000001的輸入進行了報錯,說明這方面沒有處理得當。還有對於如「x*+1」的乘法內含有帶符號整數因子處理錯誤的狀況。函數
主要經過閱讀代碼針對性測試和構造測試數據盲測結合進行測試。JUnit的Series可以排列組合生成一些數據,同窗分享的隨機生成字符串也能生成數據,但主要仍是人工設計的邊界條件數據或者特殊狀況數據更容易測出錯誤。在時間容許的狀況下,閱讀代碼是最有效的找到別人BUG的方法。固然,本身設計時積攢或出錯過的測試數據也有使用的價值。單元測試
What Information測試 |
More Information | Less Information |
Trail優化 |
Step by stepthis |
Conditional Breakpoints |
Code |
The whole code |
Coverage |
Value of variables |
Variables |
Watches/Evaluation |
Exception |
Throw an exception |
... |
Anything |
Hiearchy + |
Hiearchy - |
我認爲DEBUG也是值得思考的事情。DEBUG是根據提供的信息尋找所寫代碼中錯誤並改正的過程。經過IDEA和Eclipse所支持的豐富的功能,咱們能夠輕易的得到包括代碼覆蓋、變量值、代碼軌跡等信息,經過增長和減小信息結合本身程序的設計結構,能夠大大減小鎖定bug的時間。利用條件斷點實現分級的DEBUG信息輸出也是有價值的DEBUG方法。
第一次做業中,我沒有實現多項式類,將多項式當作多個單項式存儲在數組中進行處理,並編寫相應的各類方法。能夠重構,設計多項式類,僅包含HashMap類,並且因爲多項式求導後仍是多項式,求導方法可使用new的方法返回一個多項式。
第二次做業中,也沒有實現多項式類。仍可設計多項式類,各類多項式處理器與主函數的數據交流也能夠重構爲對象建立的方法,每次返回一個new多項式,可使得各類求導、優化、合併同類項、根據三角函數公式優化等方法能夠獨立地開發和測試。
第三次做業我已經有使用工廠模式的影子,仍有不少能夠改進的地方。能夠完成部分優化工做,這裏就須要注意equals方法的重寫以支持合併同類項。此外,在我設計中使用了替換字符以屏蔽括號內正負號和乘號的處理方法來應對多層嵌套,分割後再將字符換回,這個有很大的不安全性,也能夠重構,將這種乘積和單項式匹配方法(即遞歸地根據+、*分割輸入)改成expression tree對象的處理,改成工廠模式,能夠減小正則表達式的使用和避免對輸入數據的改動引發的不安全性。