面向對象程序設計第一單元總結


面向對象程序設計第一單元總結

一、程序結構

  • 第一次作業

圖1:第一次作業UML圖
第一次作業結構較為簡單,工程中有6個類,其中:Poly為多項式類,Term為項類,Point為因子類,PolyCompute為求導類,Format為將輸入的字符串標准化的類。我認為自己在第一次作業中已經能夠使用面向對象的思想進行代碼的編寫。思路為首先由Format類讀取處理字符串並形成一個Term類的ArrayList,再由PolyCompute類進行合並同類項以及求導。

“方法和類的復雜度分析圖片中ev(G),iv(G),v(G),OCavg,WMC含義如下:

ev(G)即Essentail Complexity,用來表示一個方法的結構化程度,范圍在[1,v(G)]之間,值越大則程序的結構越“病態”,其計算過程和圖的“縮點”有關。

iv(G)即Design Complexity,用來表示一個方法和他所調用的其他方法的緊密程度,范圍也在[1,v(G)]之間,值越大聯系越緊密。

v(G)即循環復雜度,可以理解為窮盡程序流程每一條路徑所需要的試驗次數。

OCavg代表類的方法的平均循環復雜度。

WMC代表類的總循環復雜度。”

(粘貼自https://blog.csdn.net/weixin_30588827/article/details/96159607)

圖2:第一次作業類復雜度圖

圖3:第一次作業方法復雜度圖
從Metric中可以看到,Point類中的toString方法復雜度比較高。
  • 第二次作業

ps:由於方法復雜度分析圖過於冗雜,因此在第二次作業和第三次作業的博客中,僅展示類復雜度分析,而不展示方法復雜度分析。

圖4:第二次作業UML圖
相較於第一次作業,第二次作業我采取了比較面向過程的方式進行代碼編寫(據說方法叫做遞歸下降),也就是按照任務指導書的定義,首先對文本進行一些標准化,再進行分析,主要建立了因子接口,接口下有多項式、項、正弦函數因子、余弦函數因子、冪函數因子幾個類,並對每一個類寫了求導方法和toString方法,將因子類分為了ConstFactor、CosFactor、SinFactor、PowerFactor四種類,同時增加了一個接口類Factor,以上四個類以及Term、Poly兩個類都是Factor的實例類。此外,還添加TermKey類,作為優化時合並同類項HashMap的Key。將Format類更名為PolySimplify類,並且進行了重構。

圖5:第二次作業類復雜度圖
第二次作業中有一半類的OCavg參數比較大(第三次也是),並不是很清楚是什么原因造成的,可能是因為遞歸下降的過程中,要不斷采取遞歸方式進行字符串處理吧,不知道有沒有什么可以避免的方法。(ps:如果有助教看到孩子的疑惑希望能幫孩子解答一下)
  • 第三次作業

相較於第二次作業,增加了一個Format類和FormatException異常類用於進行輸入格式檢測,同時重構了三角因子類以及與其線管的類,由於第三次作業與第二次作業相比增加的部分幾乎不需要改變架構,因此大體上架構與第二次無異。

圖6:第三次作業UML圖
第三次作業,主要變化有兩點,一是需要增加格式檢測,格式錯誤的輸入需要輸出`WRONG FORMAT!`,二是三角函數括號的內部由一定是$x$變為了可能是任意類型的因子。第二個變化比較簡單,只需要重寫一下兩個三角函數的因子以及遞歸下降讀取的類即可。而由於我之前沒有做格式檢測,而是直接對輸入進行了標准化處理,因此需要額外寫一個類對輸入進行格式化檢測,否則需要對之前寫的代碼進行大范圍改動,很容易出現新的bug,因此我采取的策略是先對輸入進行形式化檢測, 如果由形式錯誤,直接拋出異常,否則按照第二次作業進行求導操作。

圖7:第三次作業類復雜度圖

二、bug分析

  • 己方bug分析

筆者在三次作業的強測和互測中均未出現bug。但是在自己調試的過程中,在代碼行數比較長和引用其他類的代碼的地方更容易出現bug,也更難分析bug產生的原因。因此希望自己以后在代碼的編寫中能夠做到讓代碼各司其職,不要糾纏在一起。

  • 對方bug分析

對方三次作業中出現的bug原因如下:

1、為了追求一些優化在化簡多項式時出現錯誤,導致輸出結果時錯誤的;

2、使用Long類型變量讀取BigInteger導致程序崩潰;

3、Format檢驗時考慮不全面出現的bug;

4、雖然輸出的求導結果是對的,但是輸出的形式並不符合任務書的形式化定義,例如,在輸出中出現了x*-sin(x),正確輸出應該為-sin(x)*x或者x*-1*sin(x)

三、hack策略

1、在讀完任務書要求分析可能出現bug的地方,構造數據。
2、寫測評機,在互測代碼下發后使用測評機對構造的數據進行測評,從而找出他人的bug。
3、閱讀他人的代碼,定位具體產生bug的地方以及bug產生的原因。(同時可以學習他人的代碼風格或一些小細節)

四、重構經歷總結

由於第一次作業只含有普通多項式,即所有的因子都可以統一化為\(a\times x^c\)(其中\(a\)\(c\)為常數)的形式,因此采取HashMap的形式保存\(a\)\(c\),方便合並同類項,最后求導的時候直接遍歷求導即可,當然輸出時有兩個優化點,一是有正項因子時先輸出一項正項因子,可以減少一個+的長度,二是x**2輸出為x*x,可以減少一個符號的長度。

第二次作業增加了\(sin\)\(cos\)因子,並且出現了表達式因子,我第一次作業的方法不再適用於第二次(本來以為只需要擴展成四元組就可以了,沒想到多了表達式因子),因此第二次作業我采取了比較面向過程的方式進行代碼編寫(據說方法叫做遞歸下降),也就是按照任務指導書的定義,首先對文本進行一些標准化,再進行分析,主要建立了因子接口,接口下有多項式、項、正弦函數因子、余弦函數因子、冪函數因子幾個類,並對每一個類寫了求導方法和toString方法,最后只需要輸出Poly.diff().toString()就是最后需要的求導結果,當然具體實現過程中還需要進行一些化簡。

第三次作業,主要變化有兩點,一是需要增加格式檢測,格式錯誤的輸入需要輸出WRONG FORMAT!,二是三角函數括號的內部由一定是\(x\)變為了可能是任意類型的因子。第二個變化比較簡單,只需要重寫一下兩個三角函數的因子以及遞歸下降讀取的類即可。而由於我之前沒有做格式檢測,而是直接對輸入進行了標准化處理,因此需要額外寫一個類對輸入進行格式化檢測,否則需要對之前寫的代碼進行大范圍改動,很容易出現新的bug,因此我采取的策略是先對輸入進行形式化檢測, 如果由形式錯誤,直接拋出異常,否則按照第二次作業進行求導操作。形式化檢測的類也成為了程序中最長的一個類,並且筆者感覺形式化檢測其實也是一個按照過程的思想去解決的問題,因此在這個類中也是按照遞歸下降的策略按照面向過程的思想進行編寫的。

五、心得體會

由於本人比較佛系,所以除了第一次作業強測得了100分外,剩余兩次作業均有部分測試點得分較低。我認為經過本次單元的練習,我能夠更加了解面向過程編程與面向對象編程的區別,同時掌握JAVA中一些自帶的類和方法,並且更加擅長使用正則表達式進行文本處理(當然,我現在感覺正則表達式對我來說還是比較難的東西,可能未來還需要更加多的練習)。此外,我個人感覺比起性能,更重要的還是程序的正確性。雖然有人說bug是程序的固有屬性,但是個人覺得為了一點性能犧牲掉程序的正確性這種事情是很不值當的(也有可能是我比較懶),所以個人還是偏向於正確性的前提下做一些比較小的優化。

對自己比較不滿足的一點就是我的優化和我的讀取因子的過程雜糅在了一起,雖然效果還是不錯的,但是想要進一步優化的時候需要重新對字符串進行很多很多處理,個人感覺比較麻煩,所以沒有去做,這是這兩次作業中有點遺憾的地方叭。

總之,希望未來自己可以再接再厲(注意身體。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM