南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

苏礼顺-23201608發表於2024-06-02

一、前言

——總結三次題目集的知識點、題量、難度等情況

  • 關於知識點

  這次的三次題目集更加進一步體現了物件導向程式設計的思想方法。主要是之前的三次題目集就只是利用了物件導向三大基礎特性中的封裝特性,而這三次的題目集增加了繼承與多型,這正是物件導向設計的精髓所在,這三次的題目集大大增加了我對繼承與多型這兩個特性的理解與運用。除此之外,對於題目集四多種輸入方法的正規表示式的匹配與分割的運用,以及Comparable介面的運用。題目集五六更加熟悉了抽象類的使用,以及容器類的使用。

  • 關於題量

  這三次程式設計練習中,第一次是對前三次答題判斷程式程式設計作業的最終的迭代版本,需要考慮多種輸入的題目型別以及答案型別,以及對他們的分割處理得到有效資訊與各自的判斷方法。後面兩次是對家居電路的模擬。題量適中,同時題目的背景也貼合生活實際,便於理解。

  • 關於難度

  這三次的第一次作業練習,是在前三次的基礎上迭代完成,只要深入理解題目,增加繼承與多型,就可以完成題目。而後面兩次,是關於對電路的簡單模擬,只有串聯主線路,或者在其基礎上加上一個並聯電路,主要是對程式碼中繼承的設定,題目難度適中。

二、設計與分析

——主要是對題目以及自己提交的原始碼進行分析,加上自己淺淺的解釋和心得

(一)題目集一

“答題判斷程式四”

1.類圖設計

南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

2.原始碼分析

南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

1.根據資料與雷達圖分析:

  • 分支語句佔比總語句數的百分比為18.5%,此比例較低,說明此程式碼中分支邏輯較少,更易於理解與維護
  • 在雷達圖中註釋語句佔總語句數的百分比佔比不高,說明我的程式碼可讀性較差,可能也難以理解和維護,因此要增加程式碼的註釋比例
  • 最大複雜度這太高了主要原因是在controller中judgeAnswer()這個判斷答卷對錯的函式太複雜了,高達183行數,

    而且裡面還有二重巢狀迴圈,時間複雜度和空間複雜度較高。老師曾經說,一個函式的方法最多不超過50行為宜,因此這段程式碼質量不高,      

    後續自己寫類似的程式碼的時候,需要對其進行適量的拆分,減小複雜度,增強可讀性和維護性。

2.原始碼思路以及問題

(1)思路:

1)首先是讀取資訊,透過controller裡面的input函式對讀取的資訊進行分流,對應到不同的函式進行資訊處理工作,然後再組裝試卷,組裝試卷錢需要先遍歷題庫,將刪除的題目設為刪除,為後續做準備。組裝試卷就是遍歷題庫與試卷,將其組裝,輸出試卷不足100分警示資訊。考慮到題目對輸出資訊的順序也有要求因此在判斷答卷錢前,將答卷重新排序,為後續輸出做準備。在這裡排序有兩種方式,一種是直接比較排序,另一種是寫cmparable介面,我覺得後者構思更加巧妙,因此原始碼在此奉上:
@Override
public int compareTo(Answer t) {
if (this.getId().compareTo(t.getId()) > 0) {
return 1;
} else if (this.getId().compareTo(t.getId()) < 0) {
return -1;
} else {
if (this.getNumber() > t.getNumber()) {
return 1;
} else if (this.getNumber() < t.getNumber()) {
return -1;
} else {
return 0;
}
}
}


2)對於繼承與多型在本題的體現,主要是建立的question問題父類,多選題目,填空題目等均繼承於它,後續有其他種類的題目也可進行擴充套件。

(2)問題
這段程式碼的最大的問題就是在judgeAnswer函式里面,函式過於長,十分冗餘,裡面實現了找到答卷對應的試卷,判斷題目對錯(所有型別的題目判斷對錯都在裡面了,明顯可以出拆分成多個函式),以及構建分數,輸出分數都在裡面了。明顯可以拆分成多個函式,降低函式複雜度與提高程式碼可讀性以及可維護性。


(二)題目集二

家居強電電路模擬程式一

1.類圖設計:

南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

2.原始碼分析:

南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

1.根據資料與雷達圖分析:

  • 這一段程式碼註釋語句偏少,平均複雜度偏低,平均方法數偏低。
  • 方法呼叫語句數為222,這次和上次都比第一到三次題目集增加頗多,說明自己的程式碼模組化程度進一步變高,的程式碼的複用性變得更高。

2.原始碼思路以及問題:

1)原始碼思路:

  這次的是新的程式設計,具體思路和之前的答題順序模擬思路不太一樣。接下來說明。總體的思路是資訊讀入與資訊處理—>資訊讀入的同時建立電路(這次模擬就只是模擬一個主線路,裡面沒有串並聯具體電路的實現,較為簡單)—>接著對組裝好的電路進行電壓賦值—>建立輸出順序按照特定格式輸出。
所有的用電器與控制開關均繼承自Device類,在Controller中建立Device類的Arraylist陣列,用於模擬這條主線路。其中Device設為抽象類,內部包含getU得到電壓的方法與view輸出的方法這兩個不能具體實現的方法。因為不同的用電器需要的電壓不一樣,輸出形式也不一樣。其實這樣的只構建一個Device類並不好,因為完全沒有考慮到後續迭代的增加的電路問題,這一點我會在下一題的分析中指出。

2)相關問題

  首先是對於引腳的處理問題,因為很明顯根據實際,你一個用電器前面是輸入引腳,後面是輸出引腳,中間只有用電器這一個東西,是不會再夾層其他東西的,但是我在讀取的時候考慮到了這個,不僅麻煩,在讀取的時候要一遍遍遍歷,大大增加了複雜度,佔用空間資源。更關鍵的是,讀取它之後並沒有一點用處,這就是效益十分不高。
  同時在做這一題時,最後有兩個測試點一直過不了,直到我把電路里面的開關設定為斷開時,發現用電器依然顯示是有電狀態,這就是問題所在,根據實際電路情況,當電路斷開的時候,電路是不可能有電的,所以我在構建用電器電壓時應當先對電路判斷他是不是有電狀態。


(三)題目集三

“家居強電電路模擬程式一”

1.類圖設計:

南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

2.原始碼分析
南昌航空大學大一下學期java題目集4-6總結性Blog-蘇禮順23201608

1.根據資料與雷達圖分析:

  • 這一段程式碼註釋語句偏少,平均複雜度偏低。
  • 方法呼叫語句數為388,為歷史新高說明自己的程式碼模組化程度進一步變高
  • 行數達到了1117行,這是我第一次java程式設計破千行的程式碼

2.原始碼思路以及問題:

(1)原始碼分析

  這一次的迭代主要是增加了不同的電路,包括串聯電路以及並聯電路。但是大體的思路和上面一題是一樣的,這一點從我這未改動的main程式碼就可以看出來。但是最大的不同的是我這一次增加了abstaractCharge類,他是所有用電裝置Device以及所有電路abstractCircuit的父類,因為考慮到一個主電路有串聯電路,有並聯電路,還有用電器。同時這一個並聯電路也有串聯電路,等等。因此在controller類裡面可以定義一個abstaractCharge型別的Arraylist來當做電路儲存資訊,並透過instaneof判斷類的型別,向下轉型進行資料處理。

  在最後的資訊輸出的時候,我定義了多個ArrayList儲存開關,用電器等,遍歷所有的電路,儲存其對應的資訊,再在最後依次輸出。

(2)相關問題

  這一題最大的坑在於當主電路只包含一個並聯電路時的情況。按照物理知識我們知道,這時由於開關等控制電器沒有電阻,因此並聯電路兩段的電壓就是220。但是,凡事就在於這個但是,假如我們並聯電路里面有兩個串聯電路,這兩個串聯電路的電阻是10歐姆和20歐姆,根據並聯電路計算公式1/R = 1/R1+1/R2,因此我們的並聯電路的電阻就為6.6666666666666667歐姆,沒錯就是這麼精確,即便這麼精確,也還是會出問題。我計算用電器兩端的電壓方式是:先算出一個電路兩段的總電壓和總電阻,再拿總電壓除以總電阻,可以得到單位電阻對應的電壓,然後用電器兩端的電壓就是單位電阻對應的電壓乘以這個用電器對應的電阻。那麼我們依據這個計算220/6.6666667,然後乘以6.66666667得到的並不是準確的220電壓,就在於這個不能整除,最終在計算白熾燈的電燈亮度的時候:
if (Math.abs(this.outputU - this.inputU) <= 9) {
lamplight = 0;
}
if (Math.abs(this.outputU - this.inputU) == 10) {
lamplight = 50;
}
if (Math.abs(this.outputU - this.inputU) > 10 && Math.abs(this.outputU - this.inputU) < 220) {
lamplight = (Math.abs(this.outputU - this.inputU) - 10) * 1.0 / 210 * 150 + 50;
}
else if (Math.abs(this.outputU - this.inputU) >= 220) {
lamplight = 200;
}
他不會進入到>=220的分支語句中去,而是進入到<220的分支語句中去,因此計算的lamplight是199.9999999998可能,再根據截尾規則,直接捨去小數部分,這樣算的lamplight就是199,而不是200,導致出錯。因此我們在計算的時候要類似於比較大小的樣子,<0.00001就認為二者相等,然後賦值成整數,這樣就可以消除這方面的差錯了。

三、踩坑心得

1.遵循單一職責做的還不夠好
  主要體現在第四次題目集也就是答題判斷程式的最後一次迭代的題目裡。某個函式長度很長,函式實現的功能也很複雜,包括了判斷不同題目的對錯,分數的計算等等。哪怕是自己看,也一時半會不能很好理解自己的思路,更不要說別人看自己的程式碼,則就更加難懂。
  而且單一職責不僅體現在程式碼的可讀性方面,還有程式碼的覆用性上。老師曾經在上課上的時候說過,一段程式碼的實現的功能越強,那麼它被覆用的可能性就越低。
2.理論聯絡實際很重要
  在軟體這一領域,我們編寫程式碼總是要立足於某些東西,實現某些功能,並不是說是空穴來風,沒有立足點。因此我們編寫程式碼的時候,要明白給誰編寫,編寫什麼,這個編寫的是什麼,他這一個領域有哪些知識需要你學習,因為你編寫程式碼可能會用到那些領域的知識。例如在家庭電路簡單模擬中,我因為忽略了電路斷電就用用電器不能工作這一事實,導致沒有實現這一功能。當然,我考慮欠缺也是一部分原因,自己也是要更加考慮周全。
3.時刻明白程式設計和實際計算中的不同之處
  例如我在第三次題集的問題分析中指出的,因為計算的精度的問題,計算的電壓不是完整的220V,導致的錯誤,這完全是自己在寫程式碼的時候自己想當然的結果導致的錯誤。

四、改進建議

程式碼最佳化:

1.對於部分函式進行精簡,使其結構單一,提高覆用性,與可讀性

2.程式碼中變數的命名,函式名字的命名不太規範,也需要之後改進

3.降低巢狀迴圈層數,減少空間與時間複雜度

結構最佳化:

1.對於串聯中有串聯電路,並聯中有並聯電路,等複雜電路的情況自己沒有考慮,需要在日後的迭代中加入這些功能

2.減少if-else等的情況判斷

五、總結

  這三次題目集大大增強了我對繼承與多型這兩大特性,抽象類,向下轉型,泛型,常用介面等基礎知識的理解與運用。尤其是最後一題,大大增加了我對繼承的理解,如果不是讓讓電路和用電器都繼承自同一個類,那麼我在構建電路的時候就會要麻煩很多。充分體現了面嚮物件語言的方便性。

  然後在開閉原則上我也有了更加深刻的領悟。在上一部分的pta中,我很清楚地記得每一次的程式碼我都是新建一個專案工程,從主函式一個一個開始敲,自己完全沒有是在之前程式碼的基礎上進行修改,而是不斷重構。不僅費時費力,也完全沒有深刻理解面向分物件語言的方便性。但是在最近兩次的pta練習,引入了繼承之後,自己的每次程式碼則是從上一次的程式碼的基礎上進項修改,擴充套件。當然這個進步離不開老師的辛勤教導與線上課,線下課,實驗,pta多個合一的結果,感謝老師的教導!!

  最後希望下一階段給自己的目標是一是可以預測之後Pta會向哪方面的迭代,提高自己程式碼的質量,爭取一次比一次程式碼改動的方面更少。二是將老師上課講到的設計模式用到一二,學以致用,提高自己程式碼編寫水平。

  謝謝!!

相關文章