1. 程式人生 > 其它 >BUAA_OO_2022 第一單元總結

BUAA_OO_2022 第一單元總結

面向物件 第一單元總結

第一次作業

總體架構

​  顯然由於假期美賽的衝突導致了我預習的匆忙,事實上作業開始後我的Pre3還沒有用過,因此在思考了三天以後,我放棄了一般讀入選擇了預解析模式,在半小時後完成了程式碼架構的設計,核心的在於使用hashmap進行多項式的儲存,利用預解析的每一步進行運算不斷更新這個單獨的hashmap,最後得到的就是表示式的數學儲存結果,最後優化輸出即可。因此,本次作業的整體結構分為四個部分:MainClass 類為程式主控類,負責輸入輸出等主要流程的控制;Parser 類負責根據字串返回指定的hashmap,五種運算類負責對讀入的運算進行處理,最後兩類進行輸出的字串表達以及簡化。

類圖分析

  • MainClass
    • 負責讀入字串,對預解析處理分類並輸出最後結果的流程控制。
  • Parser
    • 利用mainclass的輸入返回對應的hashmap。
  • Neg,Add,Sub,Mul,Pow
    • 根據輸入的hashmap進行運算。
    • 返回hashmap作為fi(label)的結果。
  • Express
    • 表示式類,實現了標籤和對應表示式的字串儲存以及資料儲存。由於最終結果一定是一個多項式因此一個hashmap就可以完美解決。
  • Tiaozheng,Toanswer
    • 這兩類是負責對最後的express進行字串轉化以及字串簡化。
  • 優點
    • 整體上解耦設計,將程式碼分成流程控制、表示式計算和表示式簡化三個部分。這樣可以在完成程式碼時分步進行實現與測試,保證前一部分沒有 bug 時再完成下一部分,減小了 debug 難度。(當然也是因為使用了預解析使得本體的核心難度下降)
    • 將hashmap作為統一的儲存,這樣使得可以在計算時直接數學簡化,有利於後續表示式輸出。
  • 缺點
    • 部分類的沒有必要單獨存在,比如計算類的其實可以就放在一個類當中,並且最後輸出優化其實可以和基本輸出放在一起。
    • 使用了預解析。
    • 沒有充分體現面向物件的程式設計。

度量分析

 

上表為各方法的度量分析,從中可以看出方法整體複雜度與類的耦合度都較低,但是存在個別方法的複雜度過高。如 Mainclass 的main作為分流控制以及 Toanswer類中的 end 方法作為表示式字串轉化的主要部分,其中包含了多個 if-else 判斷語句,導致其程式碼行數、複雜度與耦合度,控制流複雜度都較高。

 

上表為每一個類的度量分析,同樣可以看出複雜度最高的三個類是 Mainclass 、 ToanswerParser , 這是因為 MainClass 類作為計算分流控制導致複雜度上升此外Toanswer由於優化條件多較為複雜,因此內容也較多,而其他類相對簡單除了乘法的計算是hashmap遍歷導致複雜度上升。

程式bug分析

本次作業由於使用了預解析設計整體架構,因此在公測時出現了2個bug。一個問題是結果為0的時候沒有輸出,另一個問題是對於較大的常數或者係數會越界需要使用BigInteger,導致runtime error,此類錯誤就只能通過仔細閱讀指導書和單元測試來debug。

互測和強測時,由於我在將正項提前以減小輸出長度時出現疏忽,沒有正確設定分割的index,而產生了錯誤的輸出,導致在強測失分互測被hack。因此,也提醒自己在修改以後一定要針對測試。

測試策略

  • 由於第一次作業複雜度不高加之我使用了預解析,主要用使用手動構造樣例以及利用指導書的樣例對程式碼進行測試。在互測時我沒有 hack 到存在問題的程式碼

第二次作業

總體架構

​本次作業新增了三角函式、自定義函式和求和函式三個新的因子,然而沒有想到的是由於預解析的代價從9折變成了8.5折因此我被迫放棄第一單元的架構,直接進入第二次作業的全部重新設計,所以要在第一次作業結構的基礎上全部重新設計。由於不少同學已經有了設計的基礎,加之在研討課上同組的同學分享了hashmap的儲存結構,另外在第一週週末我完成了Pre3,對於正則表示式的使用完成了掌握,因此在重新設計的過程中很快找到了門路,實現了遞迴下降的儲存以及自底端向上的數學計算和最終的表示式輸出。

類圖分析

 

 

 

  • MainClass
    • 負責資料讀入,整體流程控制以及資料輸出。
  • Pre
    • 包括對空白符刪去,符號化簡,三角函式的符號替換,sum的展開,自定義函式的替換與展開
    • 對於自定義函式,先將其定義的表示式進行解析並儲存。當遇到函式呼叫時,進行實參替換以及展開。
    • 對於求和函式,直接展開並替換。
  • Self
    • 自定義函式類用於儲存自定義函式的函式名、變數名、表示式等性質。
  • FactorExpr
    • 因子類。
    • 用 ArrayList<Term> 來儲存解析出來的項。
  • Term
    • 用 ArrayList<Factor> 來儲存解析出來的因子
  • Tri 
    • 三角函式因子,存貯型別,自變數和指數
  • Pow
    • 冪函式因子有符號和指數。
  • ExperFactor
    • 與Expr類似,但是有指數和符號
  • Index
    • 指數類
  • NumStd
    • 常數因子
    • 標準項類,用於數學轉化儲存所有的因子
  • Mul
    • 計算Arraylist<Std>的乘法並返回對應的Arraylist<Std>
  • Sp
    • 提供Arraylist<Std>的化簡方法,本質是合併同類項目
  • Hseq
    • 提供hashmap的深度比較,確認兩者資料是否為同一儲存資料
  • 優點
    • 本次作業對於括號巢狀的處理比較完美實現了統一的運算方式和因子的統一生成和儲存。
    • 建立了表示式樹的結構,對於自定義函式及求和函式的因子代入很早就進行了處理有利於debug觀察和解耦。
  • 缺點
    • 表示式化簡僅僅實現了同類項合併,對於 cos(0) 和 sin(0) 之類的因子沒有考慮化簡,導致部分測試點效能分數過低,有幾個點效能分為0。
    • 將大部分替換工作放在了 main 類中,導致開頭越來越複雜,雖然有利於debug但是不美觀。

度量分析

 

 

 

 

 

 

 

​ 上表為各方法的度量分析,和第一次作業相比因為實現功能複雜性以及沒有使用預解析導致程式碼量起飛,大部分方法的耦合程度以及複雜度以及最後的平均值都很低,這說明程式碼整體的架構設計還是比較合理的。

 

​ 上表為每一個類的度量分析,同樣可以看出複雜度最高的兩個類是pre、Sp。這是pre承擔的替換展開任務以及方法都比較複雜,而Sp過程同樣有hashmap迴圈遍歷但是整體的 OC 與第一次作業相比卻有所下降,說明了第二次設計(其實叫第一次設計)的合理性,這說明各類分工明確,符合高內聚低耦合的原則。

程式bug分析

  • 本次作業由於內容複雜度限制提升,以及第一週使用了預解析導致在一些細節地方出了不該出現的 bug,在公測中因為sum中的一個數組沒有重新整理中掛了兩天。最終在和同學們的討論下和自己不懈的測試下最終在距離提交4小時前得以解決
  • 而在互測時,沒有被hack到反而由於自己順手構造了資料hack了別人。

測試策略

  • 本次互測我由於自己測試的過程一直有所記錄,因此我把自己走過的彎路讓別人的程式碼也走走,其中使用sin(-1)成功hack到三人。

第三次作業

總體架構

​ 第三次作業減少了上一次作業中因子的限制,因此需要修改的部分較少,又因為第二次作業中實現了無限括號巢狀,因此幾乎沒有大的改動就完成了本次的程式碼。

類圖分析

 

 

 

 

 

 

 

  • Pre
    • 由於自己在第二次作業中使用了括號巢狀(結合棧的使用)因此只需多次呼叫處理函式就可以實現多層括號巢狀的處理,因此只在其呼叫處設定迴圈即可。
  • Std
    • 由於三角函式內部因子也可以為表示式因子,因此需要新增將三角函式內部Zbl的視為表示式因子,這可以通過已有的方法實現。
  • 優點
    • 體現出了良好的擴充套件性。
  • 缺點
    • 仍然沒有將 sin(0)之類的 替換成 0並且沒有將sin((1))化為sin(1) 等。
    • main函式過於長

度量分析

 

 

 

 

 

 

​ 上表為各方法的度量分析,可以看到基本與第二次作業一致。

 

 

​ 上表為每一個類的度量分析,其中 Pre 的複雜度進一步增加,mainclass複雜度起飛,但邏輯上其實沒有太大的變化(只是加了迴圈),std由於改了tri型別的轉化因此也少量上浮。

程式bug分析

  • 由於本次作業的增量較少,所以在公測時出現的 bug 也比較集中。一個發現的 bug 在修改自定義函式展開時候忽略了h型別的自定義函式,另一個就是巢狀計算Tri.Zbl時候需要對其進行表示式簡化防止出現重複儲存的bug
  • 互測和強測出現了兩型別的bug,一個是自定義函式中‘,’不再作為當前自定義函式的自變數劃分的充分條件,因此要使用棧去判定,二是sum函式中對於上下限int無法滿足,要替換成大整數。

測試策略

  • 由於自認為架構比較完善延續性好沒有做過多測試,在測了簡單的巢狀(形參只調用了一個)以後,沒有繼續測試,結果出現了上述的問題。

架構設計體驗

​ 通過第一單元的作業,讓我領悟到了架構設計的重要性,以及何為層次化設計。雖然最早沒有使用一般解析,但在壓力的驅動下自己成功構造了設計,並且在第三次作業中體現出良好的延續性。同時第一次作業啟發了我將字串的加減乘轉化為資料型別的加減乘,其中標準項的思想對於我第二次作業的設計有很大的幫助。把問題轉化為抽象的數學問題往往可以簡化程式,而將大問題轉化為小問題有利於提升程式碼編寫的信心,提高編碼和debug的效率。

層次化設計方面,由於遞迴下降的引入以及pre2中的指導,在第二次作業中很快體現了其強大的組織建設資料的能力,我也邁入了面向物件的程式設計,使得編寫的內容非常有針對性,降低了編碼的盲目性。

心得體會

最早預習的不充分在第一週深深折磨了自己,然後在第二週直接讓我爆肝一週,也算是明白了預習設定的目的以及重要性。好在同學們都很積極樂於幫助他人解決問題,遇到坑點難點大家相互幫助,掛同一個測試點的同學相互討論,研討課上的熱烈討論和方法的提案都讓我受益匪淺,多交流多學習是我目前覺得OO帶給我很不一樣的體驗。同時助教學長學姐的及時答疑以及bug修復時申請反饋讓我感受到課程組處理事務的高效。當然很重要的一點就是oo很苦,但是完成以後的成就感確實無與倫比的,使用一週的時間就會讓你能感受到蛻變和進步。同時staruml,git等工具的使用也是oo交給我很重要的一課。總之,第一單元結束了,但是我們的路還在繼續。

第一次作業

總體架構

​  顯然由於假期美賽的衝突導致了我預習的匆忙,事實上作業開始後我的Pre3還沒有用過,因此在思考了三天以後,我放棄了一般讀入選擇了預解析模式,在半小時後完成了程式碼架構的設計,核心的在於使用hashmap進行多項式的儲存,利用預解析的每一步進行運算不斷更新這個單獨的hashmap,最後得到的就是表示式的數學儲存結果,最後優化輸出即可。因此,本次作業的整體結構分為四個部分:MainClass 類為程式主控類,負責輸入輸出等主要流程的控制;Parser 類負責根據字串返回指定的hashmap,五種運算類負責對讀入的運算進行處理,最後兩類進行輸出的字串表達以及簡化。

類圖分析

  • MainClass
    • 負責讀入字串,對預解析處理分類並輸出最後結果的流程控制。
  • Parser
    • 利用mainclass的輸入返回對應的hashmap。
  • Neg,Add,Sub,Mul,Pow
    • 根據輸入的hashmap進行運算。
    • 返回hashmap作為fi(label)的結果。
  • Express
    • 表示式類,實現了標籤和對應表示式的字串儲存以及資料儲存。由於最終結果一定是一個多項式因此一個hashmap就可以完美解決。
  • Tiaozheng,Toanswer
    • 這兩類是負責對最後的express進行字串轉化以及字串簡化。
  • 優點
    • 整體上解耦設計,將程式碼分成流程控制、表示式計算和表示式簡化三個部分。這樣可以在完成程式碼時分步進行實現與測試,保證前一部分沒有 bug 時再完成下一部分,減小了 debug 難度。(當然也是因為使用了預解析使得本體的核心難度下降)
    • 將hashmap作為統一的儲存,這樣使得可以在計算時直接數學簡化,有利於後續表示式輸出。
  • 缺點
    • 部分類的沒有必要單獨存在,比如計算類的其實可以就放在一個類當中,並且最後輸出優化其實可以和基本輸出放在一起。
    • 使用了預解析。
    • 沒有充分體現面向物件的程式設計。

度量分析

 

上表為各方法的度量分析,從中可以看出方法整體複雜度與類的耦合度都較低,但是存在個別方法的複雜度過高。如 Mainclass 的main作為分流控制以及 Toanswer類中的 end 方法作為表示式字串轉化的主要部分,其中包含了多個 if-else 判斷語句,導致其程式碼行數、複雜度與耦合度,控制流複雜度都較高。

 

上表為每一個類的度量分析,同樣可以看出複雜度最高的三個類是 Mainclass 、 ToanswerParser , 這是因為 MainClass 類作為計算分流控制導致複雜度上升此外Toanswer由於優化條件多較為複雜,因此內容也較多,而其他類相對簡單除了乘法的計算是hashmap遍歷導致複雜度上升。

程式bug分析

本次作業由於使用了預解析設計整體架構,因此在公測時出現了2個bug。一個問題是結果為0的時候沒有輸出,另一個問題是對於較大的常數或者係數會越界需要使用BigInteger,導致runtime error,此類錯誤就只能通過仔細閱讀指導書和單元測試來debug。

互測和強測時,由於我在將正項提前以減小輸出長度時出現疏忽,沒有正確設定分割的index,而產生了錯誤的輸出,導致在強測失分互測被hack。因此,也提醒自己在修改以後一定要針對測試。

測試策略

  • 由於第一次作業複雜度不高加之我使用了預解析,主要用使用手動構造樣例以及利用指導書的樣例對程式碼進行測試。在互測時我沒有 hack 到存在問題的程式碼

第二次作業

總體架構

​本次作業新增了三角函式、自定義函式和求和函式三個新的因子,然而沒有想到的是由於預解析的代價從9折變成了8.5折因此我被迫放棄第一單元的架構,直接進入第二次作業的全部重新設計,所以要在第一次作業結構的基礎上全部重新設計。由於不少同學已經有了設計的基礎,加之在研討課上同組的同學分享了hashmap的儲存結構,另外在第一週週末我完成了Pre3,對於正則表示式的使用完成了掌握,因此在重新設計的過程中很快找到了門路,實現了遞迴下降的儲存以及自底端向上的數學計算和最終的表示式輸出。

類圖分析

 

 

 

  • MainClass
    • 負責資料讀入,整體流程控制以及資料輸出。
  • Pre
    • 包括對空白符刪去,符號化簡,三角函式的符號替換,sum的展開,自定義函式的替換與展開
    • 對於自定義函式,先將其定義的表示式進行解析並儲存。當遇到函式呼叫時,進行實參替換以及展開。
    • 對於求和函式,直接展開並替換。
  • Self
    • 自定義函式類用於儲存自定義函式的函式名、變數名、表示式等性質。
  • FactorExpr
    • 因子類。
    • 用 ArrayList<Term> 來儲存解析出來的項。
  • Term
    • 用 ArrayList<Factor> 來儲存解析出來的因子
  • Tri 
    • 三角函式因子,存貯型別,自變數和指數
  • Pow
    • 冪函式因子有符號和指數。
  • ExperFactor
    • 與Expr類似,但是有指數和符號
  • Index
    • 指數類
  • NumStd
    • 常數因子
    • 標準項類,用於數學轉化儲存所有的因子
  • Mul
    • 計算Arraylist<Std>的乘法並返回對應的Arraylist<Std>
  • Sp
    • 提供Arraylist<Std>的化簡方法,本質是合併同類項目
  • Hseq
    • 提供hashmap的深度比較,確認兩者資料是否為同一儲存資料
  • 優點
    • 本次作業對於括號巢狀的處理比較完美實現了統一的運算方式和因子的統一生成和儲存。
    • 建立了表示式樹的結構,對於自定義函式及求和函式的因子代入很早就進行了處理有利於debug觀察和解耦。
  • 缺點
    • 表示式化簡僅僅實現了同類項合併,對於 cos(0) 和 sin(0) 之類的因子沒有考慮化簡,導致部分測試點效能分數過低,有幾個點效能分為0。
    • 將大部分替換工作放在了 main 類中,導致開頭越來越複雜,雖然有利於debug但是不美觀。

度量分析

 

 

 

 

 

 

 

​ 上表為各方法的度量分析,和第一次作業相比因為實現功能複雜性以及沒有使用預解析導致程式碼量起飛,大部分方法的耦合程度以及複雜度以及最後的平均值都很低,這說明程式碼整體的架構設計還是比較合理的。

 

​ 上表為每一個類的度量分析,同樣可以看出複雜度最高的兩個類是pre、Sp。這是pre承擔的替換展開任務以及方法都比較複雜,而Sp過程同樣有hashmap迴圈遍歷但是整體的 OC 與第一次作業相比卻有所下降,說明了第二次設計(其實叫第一次設計)的合理性,這說明各類分工明確,符合高內聚低耦合的原則。

程式bug分析

  • 本次作業由於內容複雜度限制提升,以及第一週使用了預解析導致在一些細節地方出了不該出現的 bug,在公測中因為sum中的一個數組沒有重新整理中掛了兩天。最終在和同學們的討論下和自己不懈的測試下最終在距離提交4小時前得以解決
  • 而在互測時,沒有被hack到反而由於自己順手構造了資料hack了別人。

測試策略

  • 本次互測我由於自己測試的過程一直有所記錄,因此我把自己走過的彎路讓別人的程式碼也走走,其中使用sin(-1)成功hack到三人。

第三次作業

總體架構

​ 第三次作業減少了上一次作業中因子的限制,因此需要修改的部分較少,又因為第二次作業中實現了無限括號巢狀,因此幾乎沒有大的改動就完成了本次的程式碼。

類圖分析

 

 

 

 

 

 

 

  • Pre
    • 由於自己在第二次作業中使用了括號巢狀(結合棧的使用)因此只需多次呼叫處理函式就可以實現多層括號巢狀的處理,因此只在其呼叫處設定迴圈即可。
  • Std
    • 由於三角函式內部因子也可以為表示式因子,因此需要新增將三角函式內部Zbl的視為表示式因子,這可以通過已有的方法實現。
  • 優點
    • 體現出了良好的擴充套件性。
  • 缺點
    • 仍然沒有將 sin(0)之類的 替換成 0並且沒有將sin((1))化為sin(1) 等。
    • main函式過於長

度量分析

 

 

 

 

 

 

​ 上表為各方法的度量分析,可以看到基本與第二次作業一致。

 

 

​ 上表為每一個類的度量分析,其中 Pre 的複雜度進一步增加,mainclass複雜度起飛,但邏輯上其實沒有太大的變化(只是加了迴圈),std由於改了tri型別的轉化因此也少量上浮。

程式bug分析

  • 由於本次作業的增量較少,所以在公測時出現的 bug 也比較集中。一個發現的 bug 在修改自定義函式展開時候忽略了h型別的自定義函式,另一個就是巢狀計算Tri.Zbl時候需要對其進行表示式簡化防止出現重複儲存的bug
  • 互測和強測出現了兩型別的bug,一個是自定義函式中‘,’不再作為當前自定義函式的自變數劃分的充分條件,因此要使用棧去判定,二是sum函式中對於上下限int無法滿足,要替換成大整數。

測試策略

  • 由於自認為架構比較完善延續性好沒有做過多測試,在測了簡單的巢狀(形參只調用了一個)以後,沒有繼續測試,結果出現了上述的問題。

架構設計體驗

​ 通過第一單元的作業,讓我領悟到了架構設計的重要性,以及何為層次化設計。雖然最早沒有使用一般解析,但在壓力的驅動下自己成功構造了設計,並且在第三次作業中體現出良好的延續性。同時第一次作業啟發了我將字串的加減乘轉化為資料型別的加減乘,其中標準項的思想對於我第二次作業的設計有很大的幫助。把問題轉化為抽象的數學問題往往可以簡化程式,而將大問題轉化為小問題有利於提升程式碼編寫的信心,提高編碼和debug的效率。

層次化設計方面,由於遞迴下降的引入以及pre2中的指導,在第二次作業中很快體現了其強大的組織建設資料的能力,我也邁入了面向物件的程式設計,使得編寫的內容非常有針對性,降低了編碼的盲目性。

心得體會

最早預習的不充分在第一週深深折磨了自己,然後在第二週直接讓我爆肝一週,也算是明白了預習設定的目的以及重要性。好在同學們都很積極樂於幫助他人解決問題,遇到坑點難點大家相互幫助,掛同一個測試點的同學相互討論,研討課上的熱烈討論和方法的提案都讓我受益匪淺,多交流多學習是我目前覺得OO帶給我很不一樣的體驗。同時助教學長學姐的及時答疑以及bug修復時申請反饋讓我感受到課程組處理事務的高效。當然很重要的一點就是oo很苦,但是完成以後的成就感確實無與倫比的,使用一週的時間就會讓你能感受到蛻變和進步。同時staruml,git等工具的使用也是oo交給我很重要的一課。總之,第一單元結束了,但是我們的路還在繼續。