BUAA2022面向物件第一單元個人總結
BUAA2022面向物件第一單元個人總結
本單元作業主要為表示式拆括號化簡,並在此基礎上可以進行進一步優化縮短表示式長度。
一、程式結構分析
1、第一次作業
(1)經典OO度量
類度量
方法度量
(2)類圖
本次作業首先將輸入的字串進行pre預處理,去除空格符與連續的加減號,將-x拆分為-1*x,便利之後的資料處理。使用Ipt模組將輸入的StringBuilder型別的表示式字串逐字元地識別輸出,而Run模組利用Ipt模組的輸出構建樹狀表示式,大的Expr下轄多個用加號連線的Item,Item下轄多個用乘號連線的Factor,由於Expr繼承自Factor,因此可以實現無限巢狀。之後使用MainClass中的多個優化方法對錶達式樹進行優化化簡。
delTop分解表示式的指數,delBask拆分指數為1的表示式的括號,再結合hasBask判斷是否仍然存在Item內的表示式,使用while函式去除全部表示式指數與括號;cal實現Item內部的數字相乘與未知數x的相乘;easy實現去除合併表示式內的乘0、0次方、乘1、乘-1;mix負責合併同類項;addNum將僅包含數字的Item相加;delDark將剩餘的-1*x合併為-x;最終將處理後的表示式樹利用toString逐層輸出。
(3)自我點評
我的Factor模組下屬的Expr模組、Num模組、Alp模組與Item模組主要負責以樹狀圖的形式儲存表示式、項、數字、未知數的資料並負責列印;Ipt模組與Run模組共同負責將StringBuilder型別的表示式讀取為樹狀圖;MainClass模組負責對於字串表示式的預處理,樹狀表示式的去括號、優化化簡。因此,MainClass內包含了多個優化方法,使得該模組的長度遠長於其他模組,造成MainClass內聚度過高,不過好在我將優化分成多步依次進行,因此對於程式各步的讀取較為清晰。在各模組的耦合度方面,由於優化功能內聚在MainClass模組,讀取功能內聚在Run模組,因此其他模組基本只負責資料的儲存,使得程式間僅保持基本的耦合,整體耦合度較低。
2、第二次作業
(1)經典OO度量
類度量
方法度量
(2)類圖
本次作業添加了三角函式、自定義函式、求和函式,在Run中構建表示式樹時,就已經使用字串替換將求和函式與自定義函式替換為表示式,所以得到的表示式樹僅僅添加了三角函式。
新增gather方法單獨實現未知數相乘與三角函式相乘;新增simCos方法實現三角函式內部表示式的化簡;將原先的mix方法分解為mixCos與mixNum,mixCos將僅存在sin**2與cos**2不同的項進行合併,mixNum將僅存在數字項不同的Item進行合併同類項。
(3)自我點評
本次作業相較於第一次作業,增加了繼承自Factor模組的Cos模組、Sum模組、Fgh模組,負責儲存三角函式、求和表示式、自定義函式的資料;並在MainClass模組中以第一次作業為模板,增補了對於三角函式的化簡方法。而Sum模組其實並未使用,只是作為整體結構的象徵性表示;Fgh僅儲存了先行定義的自定義函式。之所以在表示式中未使用Fgh模組與Sum模組,是由於在Run模組讀取表示式時,直接將自定義函式與求和函式替換為了表示式。在增補後,MainClass模組達到400+行,Run模組也由第一次的70+行增加到了200+行。各個方法的獨立性較強,使得模組的內聚性較強,耦合度較低,優點在於讀取各步過程時較為清晰,缺點在於會使得MainClass這種內聚度較高的模組的長度過長,在需要聯絡整體進行讀取定位某個方法時需要花稍許時間進行尋找。
3、第三次作業
(1)經典OO度量
類度量
方法度量
(2)類圖
本次作業相較於第二次作業,由於發現了當經過化簡後,Item內可能存在多個三角函式造成同類項判定錯誤的bug,因此直接刪去了合併同類項的操作;同時為了滿足新新增的三角函式內部表示式要求,在每個三角函式輸出時都額外新增一層括號;為了避免淺複製帶來的連帶變化問題,在Expr中新增toStrbak方法用來在輸出Item內的Expr時新增一層括號,以通過將表示式輸出並重新讀取消除淺複製影響。
(3)自我點評
本次作業在第三次作業的基礎上並未進行過多修改,僅在MainClass模組中刪除了合併同類項方法並增補了三角函式的進一步化簡方法,因此,整體結構上的分析與第二次作業保持一致。
二、程式bug分析
1、第一次作業兩處bug
(1)去除連續加減號時,誤將)後面的+去除。原因為考慮不夠全面,未使用科學的情況便利方法。
(2)輸入BigInteger時,將String轉化為Long再轉化為BigInteger,造成資料溢位,應直接使用new BigInteger。原因為對於java的方法使用瞭解不足,需多加練習。
2、第二次作業三處bug
(1)合併cos**2與sin**2時,未對括號內表示式進行比較。原因為為了儘快完成目標,發生了缺漏,思維嚴謹度不夠。
(2)讀取sum函式內的上下限時,未處理負數的負號,造成執行錯誤。原因為對於程式碼實際使用的考慮不夠全面,需多加自主測試。
(3)拆分表示式的指數時,誤將三角函式的指數一起拆分,造成淺複製的連帶錯誤。要隨時意識到淺複製可能帶來的變化影響,使用clone或其他方法提前預防。
3、第三次作業一處bug
(1)化簡三角函式內部為0時,將cos(0)也直接返回0。對於數學嘗試不夠敏感沒出現生疏,應加強相關學科的重溫。
4、互測bug
(1)在處理三角函式巢狀的化簡過程中產生的三角函式內部的-sin(x)誤讀取為sin(x)。
(2)在合併同類相時,誤以為三角函式化簡後和未知數一樣在Item內僅有一個,僅比較第一個三角函式就判斷所有三角函式相等。
(3)化簡0次方時,將0**0判斷為0,應為1。
(4)sum函式中的表示式為i**2時,將i替換為負數時未新增括號,導致負號不進行指數運算。
(5)sum函式內的上下限使用int讀取,當數字過大時產生資料溢位。
(6)sum函式直接使用指數運算數時,sum函式被取代為表示式後未新增括號,導致部分項不參與指數運算。
三、互測策略分析
由於每一次強測的測試點資料會在debug階段進行展示,因此我在每一次互測時都是不考慮前次作業可能出現的bug,僅考慮本次作業新增特性可能出現的bug。對於測試資料的構造,主要是以我自己的程式碼與遇到的困難為基礎,針對於程式碼優化部分的新增方法進行測試,針對數字的溢位,符號的讀取,冪函式、自定義函式、求和函式是否使用括號進行分隔。同時由於化簡後一項內可能存在多個三角函式,使得三角函式不同於數字與未知數的唯一性,因此也對與三角函式相關的同類項合併、平方合併進行了測試。最後,對於困惑了我很久的淺複製問題也進行了測試。
四、架構設計體驗
我的整體架構主要參考了本單元的訓練部分的邏輯結構,以樹狀圖的形式儲存並處理表示式,不同的是我使用了ArrayList取代了雜湊序列,原因在於相較於雜湊序列,我更加熟悉運用ArrayList。
將表示式整體處理為Expr,內部使用加號連線多個項Item,在項內部使用乘連線多個因子Factor,由於Expr繼承自Factor,因此整個表示式樹具有向下無限延拓的性質。
本來我考慮將Fgh模組與Sum模組也納入表示式樹,之後在優化表示式時再替換為Expr,但經過考慮後,我發現可以在將字串表示式讀取為表示式樹的時候直接用字串替換的方式將Fgh與Sum直接替換為Expr字串,並在兩側新增括號避免外部符號的影響,再讀取為Expr樹,同時由於Expr具有可擴充套件性因此在讀取為樹的同時便可以自動讀取巢狀部分。
在完成基本任務,拆分括號時,我使用while函式進行處理,當檢測到Item記憶體在Expr時,則說明存在內部多餘括號,此時使用優化函式將Expr內部Item與外部的Factor分別合併,當不存在內部多餘括號,即不存在Item內Expr時,while函式結束,基本任務完成。
五、心得體會
在本單元作業中,我充分體會到了在一開始經過考慮選擇一個合適的、可拓展的架構的便利性,在後續拓展時僅需要增添幾個方法與因子模組即可,有時由於之前的提前考慮,自甚至不必進行增補即可完成拓展任務。
在拓展專案時,也要注意不要盲目模仿之前已有的因子,要特別注意新的因子有沒有獨有的特性。例如本單元的數字因子在化簡至合併同類項時每個Item內僅有一個Num,但三角函式因子在化簡至合併同類項時每個Item內可能存在多個Cos。
在debug時,我也用慘痛的經驗教訓銘記了細心的重要性,有時候程式中的多處複雜bug也許只是由於一次不合適的強制轉換,或是寫程式碼時偶然出現的思考冗餘,亦或是問題存在兩個對立情況時僅考慮了其中一種情況,這種簡單的bug最容易修復,但是往往最難被發現,可能會因此耗費大量的精力與代價。