首先,基於類的屬性個數,方法個數,每一個方法的規模,每一個方法的控制分支數目,類總代碼規模等特徵對本次做業的結構進行分析。java
我使用了MetricsReloaded插件來對代碼的複雜度進行了分析。正則表達式
還有對於方法的複雜度分析因爲篇幅緣由沒有貼出來,主要的指標爲ev,iv,v三個指標,分別表明基本複雜度、模塊設計複雜度以及模塊斷定結構複雜度,ev大表明代碼非結構化程度高,難以模塊化和維護。iv大表明模塊間耦合度高,模塊間難以隔離與複用,v大表示代碼獨立路徑條數多,難於測試和維護。在作面向對象度量時,咱們常常採用ck度量(Chidamber Kemerer)來度量耦合,內聚,封裝等等特徵。上表中wmc表明的是類的方法權重,表示一個類中全部方法的複雜度之和。顯然越大說明越複雜。編程
因爲是第一次做業,所以對於面向對象的思想還不是特別熟悉,我此次將main類與Poly類寫到了一塊兒,其實應該分離,一個多項式的類,一個項的類,一個main入口類。總體來說結構不是很好,並且有兩個比較長的方法同時分支較多,同時也就形成了它們的獨立路徑數較多,模塊複雜度較高。設計模式
個人高複雜度方法體如今輸入處理,輸出處理以及化簡上,此次做業如何有效的化簡是一個難點。數組
本次做業的設計較爲體現了面向對象的思想,設計了一個main入口類,多項式類,項類,因子類,以及其中因爲因子是由底數和指數組成的,而指數又有多種形式,故設計了一個底數的抽象類base,將常數類const,冪函數類power,三角函數類triangle做爲了base的子類,這樣就能夠將一個多項式一點點解析成項,因子,底數,指數等等。同時,因爲每個類都有共同的特色就是可求導,所以我設計了一個求導的接口Derivable,全部的類都實現了這個接口,這符合了java面向接口編程的思想,同時也提高了代碼的規範性。多線程
發現個人高複雜度的方法所有都是對於輸入處理上,因而可知個人輸入處理的不太好,寫的十分面向過程且十分容易出錯。架構
本次做業的架構和上一次做業是徹底一致的,由於上次做業時我就考慮到了程序可擴展性的特色。然而本次做業在加了表達式因子和嵌套因子後顯得這個架構有一些問題。求導部分利用遞歸向下求導的方式卻是不難實現,這次做業最難的輸入部分我處理的不是很好。此次輸入的難點主要是出現了表達式因子和嵌套,咱們如何用正則表達式來正確的識別和解析。個人想法是先找到全部非三角函數括號中最內層的括號,將其解析爲一個多項式,這時再解析出該多項式內部的三角函數,把三角函數括號中嵌套的多項式因子解析到三角函數的屬性中去,重複這個步驟直到沒有括號爲止。整個過程雖然能夠實現可是十分複雜,十分面向過程且會有多分支,行數很是多的方法,複雜的正則表達式的存在。後來在討論課上據說的用工廠模式或一個parser的類能夠更好的實現該輸入解析過程,parser類裏面分別有對poly,item,factor的解析方法,高內聚低耦合避免了一大串if-else的出現。模塊化
第一次做業個人強測沒有出現WA的狀況,可是被hack了12次(2同質),分別是\\s+匹配到\t和空格外的字符的狀況、以及直接輸入空格程序crash的狀況,程序crash的緣由是我在獲得字符串以後直接進行了input.trim()操做,致使輸入input變爲空串程序crash,有兩種更改方式,一種是直接把main方法裏面的全部內容用try-catch保住,確保程序不會出現crash(這也是我後面兩次做業的寫法),另外一種方法是在trim()後面再判斷一次串是否爲空。對於另一個bug,個人正則裏面寫的是[ \\t]*然而仍是出現了bug,這與我程序的設計結構密切相關,由於我再剛剛讀入input的時候就用trim()去掉了兩邊的空白符,這樣致使輸入字符串兩邊的\v和\f沒法有效的識別WF,形成了bug的出現。個人修改方式是先看全部的輸入字符是否有非法字符,若是有的話直接輸出WF便可。函數
第一次做業個人強測沒有出現WA的狀況,可是也被hack了3次(2同質),分別是在輸入符號處理中的if表達式中的||手誤寫成了&&,和對於輸入錯誤的匹配沒有識別出WF。仔細想一想,這與個人設計結構也有着千絲萬縷的聯繫。我對於輸入的處理是在去掉了輸入兩邊的空白字符後依據此時input.CharAt(0)來肯定在前面添加"+"或者"+0",然而我沒考慮到*x若在前面"+0"會形成原本是WF的數據變成合法,所以致使了bug。另一個bug就是典型的一大段if-else形成的鍵盤誤操做,這也體現了減小分支數量下降代碼複雜度的必要性。單元測試
第三次做業個人強測WA兩個點,被hack了10次(強互測加起來2同質),分別是輸入匹配時正則表達式少了一個[ \\t]*形成的有空格致使不匹配以及一個符號出現了問題。這兩個問題的產生就與個人設計很是密切的相關了。我寫了4個正則,其中最大的正則有6行,如此長的正則不免會不當心失誤,寫小正則把問題分開分析是避免這類錯誤的一個很好的方式。而另一個符號錯誤則徹底是因爲個人輸入寫得太過複雜,括號來回匹配的邏輯,好比解析一個item,會返回一個poly.解析一個factor也會返回poly,而每一個item都有其固定的符號,此次Bug的出現就是由於在解析item返回poly的時候沒有考慮原來item的符號,而默認"+"形成了錯誤。因而可知,面向對象的設計模式,封裝的好處就是減小耦合,減小出錯點。
前兩次做業錯誤主要集中在WF上,這時候就能夠手動設計測試樣例,好比全空格,空串,只輸入常數,輸入x^0,0*x,si n(x),sin ( x ),+++1,++ 1,\f\v,BigInteger,爆棧,......等等,由於前兩次做業正確性的實現上並不難,主要你們的出錯點在對WF的處理上,所以個人這種策略有效性也很高,前兩次做業共提交7個測試樣例hack18人次。
第三次做業強調正確性的問題,我也從正確性的問題入手,具體方法就是對於指導書上對本次實驗要求的全部功能,先分別構造測試數據,在將各類模式組合起來,好比sin()裏面有表達式,裏面還有嵌套的sin(),再加一些項乘起來之類的。覆蓋全部的狀況覆蓋全部的功能就能找出bug。因爲第三次做業你們基本都沒怎麼優化,因此直接看輸出結果很難看出正誤,所以能夠把每位被測者的輸出結果賦上一個x值(好比x=1.1)比較不一樣被測者輸出結果的值是否相等,若不相等顯然是出現了問題。
這種方法難度較大,主要緣由是部分代碼可讀性較差,結構不清晰,等等。固然若是能看懂對方程序的話確定是更容易從根源處找到bug。經過白盒測試,對複雜的類進行單元測試來尋找bug。
工廠模式(Factory Pattern)是Java中最經常使用的設計模式之一,這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用一個共同的接口來指向新建立的對象。所以,對於本次做業可使用工廠模式來建立表達式,項,因子,咱們只需定義一個建立對象的接口,讓實現了該接口的子類本身決定實例化哪個工廠類。在咱們明確地計劃不一樣條件下建立不一樣實例時,工廠模式將十分管用。
抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠建立其餘工廠。超級工廠又稱爲其餘工廠的工廠,在抽象工廠模式中,接口是負責建立一個相關對象的工廠,不須要顯式指定它們的類。每一個生成的工廠都能按照工廠模式提供對象。系統的產品有多於一個的產品族,而系統只消費其中某一族的產品時,可使用抽象工廠做爲全部工廠的抽象父類,這樣咱們就不用花費時間在選擇接口上了。
4周時間過去了,OO也過去了第一單元,早就據說了OO的恐怖,現在也確實是體驗了一番。整體來說第一單元的學習還算滿意,測試方面仍需增強,另外就是面向對象的思想還需不斷的培養。第一單元其實主要仍是java的入門,幫助咱們更加熟悉java的使用。還有就是感受今年的OO確實感受要比往屆好了很多,公測分佔主要的狀況下大致上保證了課程的公平,分ABC組互測也避免了一些悲慘的狀況,整體來說OO課在不斷變好,在此感謝助教和老師的付出!
前路漫漫,道阻且長。後面還有多線程等等很難的知識和做業在等着咱們,但願咱們能繼續努力,在本學期結束時能真正有很大的收穫。