第一单元总结
一、作業(yè)分析
第一次作業(yè)
與后兩次作業(yè)相比,第一次作業(yè)非常簡單,僅要求對由常數(shù)項和冪函數(shù)組成的多項式求導。但由于缺少面向對象編程經(jīng)驗,我在這次作業(yè)中栽了不少跟頭。
(1)度量分析
在第一次作業(yè)中,我還沒有適應JAVA語言面向對象的coding風格。可以看到,我的第一次作業(yè)只有一個主類One,所有方法都堆在一個類中。這也導致了我的程序的各類復雜度都相當爆炸,總之是一次慘痛的教訓。
(2)bug分析
首先,最重要的一點:
不要特判!!
不要特判!!
不要特判!!
由于寒假摸魚的緣故,我對JAVA的很多功能都不甚了解,這個問題在這次作業(yè)中充分暴露出來了。
String matchB =str.replaceAll("[\\t ]*[\\+-][\\t ]*[\\+-][\\t ]+\\d", "w");matchB = matchB.replaceAll("[\\+-][\\t ]*[\\+-][\\t ]*[\\+-]", "w");matchB = matchB.replaceAll("\\d[\\t ]*x", "w");matchB = matchB.replaceAll("x[\\t ]*\\d", "w");matchB = matchB.replaceAll("\\^[\\t ]*[\\+-][\\t ]*[\\+-]", "w");matchB = matchB.replaceAll("\\d[\\t ]+\\d", "w");matchB = matchB.replaceAll("[\\+-][\\t ]*\\*", "w");matchB = matchB.replaceAll("x[\\t ]*\\*", "w");matchB = matchB.replaceAll("(xx)|(\\^[ \\t]*x)", "w");matchB = matchB.replaceAll("\\^[ \\t]*[\\+-][ \\t]+\\d", "w");matchB = matchB.replaceAll("\\^[ \\t]*[+-]*[ \\t]*\\d*\\*", "w");matchB = matchB.replaceAll("[\\t ]", "");if (matchB.length() == 0) {matchB = "w";}String matchC = matchB.replaceAll("\\*x\\^", "");String matchD = matchC.replaceAll("\\d\\*x", "1");String matchE = matchD.replaceAll("[\\+-][\\+-]?(\\d|(x\\^?))", "");matchE = matchE.replaceAll("x\\^?", "");
這是我第一次作業(yè)checkstyle部分的代碼,當時我還不能熟練使用正則表達式來檢查代碼格式。
特判最大的弊端就是對編程者提取錯誤信息的能力提出了很高要求,一旦編程者考慮的錯誤情況不全,就極易在檢查格式這一步上栽跟頭。?
此外,由于第一次作業(yè)中采用了樸素的特判處理作為checkstyle的方法,我的這一次作業(yè)程序的擴展性極差,第二次作業(yè)只能推倒重來,這也需要引以為戒。
? 第二次作業(yè)
第二次作業(yè)的內(nèi)容是對包含簡單冪函數(shù)和簡單正余弦函數(shù)的導函數(shù)的求解,在這次作業(yè)中,我將上一次作業(yè)的代碼推倒重建,代碼風格開始逐漸偏向面向對象而不是面向過程。
(1)度量分析
在第二次作業(yè)中,我開始嘗試使用多個類處理不同任務,但是有部分類依舊顯得過于臃腫。這是我還沒有面向對象化的體現(xiàn)。
我的整體思路是在CheckStyle類中完成格式檢查,在Poly類中完成求導計算和輸出,Main類的功能則是整體調度。可以發(fā)現(xiàn),我的思路依舊是將類作為一個大型函數(shù)來使用,其本質還是面向過程而非面向對象。各個部分也沒有做到高度分工,尤其是Poly類,同時需要完成求導計算、化簡和輸出這三個任務。這也導致了Poly類的復雜度特別大。
(2)bug分析
我吸取了第一次作業(yè)的教訓,采用了正則表達式作為checkstyle的工具,在提取項的過程中也將正則表達式作為搜索關鍵詞使用。
Pattern p = Pattern.compile("^[ \\t]*[+-]?[ \\t]*[+-]?[ \\t]*" +"((([+-]?\\d+)|(x([ \\t]*+\\^[ \\t]*[+-]?\\d+)?)" +"|(sin[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|(cos[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?))" +"([ \\t]*\\*[ \\t]*(([+-]?\\d+)" +"|([ \\t]*x([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|([ \\t]*sin[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|([ \\t]*cos[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?)))*)" +"([ \\t]*[+-][ \\t]*[+-]?[ \\t]*" +"((([+-]?\\d+)|(x([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|(sin[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|(cos[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?))" +"([ \\t]*\\*[ \\t]*(([+-]?\\d+)" +"|([ \\t]*x([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|([ \\t]*sin[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?)" +"|([ \\t]*cos[ \\t]*\\([ \\t]*x[ \\t]*\\)" +"([ \\t]*\\^[ \\t]*[+-]?\\d+)?)))*))*+[ \\t]*$");這是我checkstyle時使用的超大正則,經(jīng)過實際檢驗并不會爆棧。大正則的好處是比較直觀,缺點則是編寫和debug時會比較痛苦,只能說要慎用。
?
private String strin;private Map<String,String> match = new HashMap<String,String>();private Map<String,String> result = new HashMap<String,String>();我新建了兩個hashmap變量用來保存項的內(nèi)容,第一個保存求導前的內(nèi)容,第二個保存求導結果。這樣做的好處是便于合并同類項,可以把項的內(nèi)容作為保存的關鍵詞,項的系數(shù)作為保存的內(nèi)容。
我的這次作業(yè)中并沒有出現(xiàn)bug,但由于我未考慮諸如sin(x)^2+cos(x)^2這類情況的化簡,導致我的性能分比較低。
第三次作業(yè)
第三次作業(yè)在前兩次作業(yè)的基礎上加入了嵌套函數(shù)的定義,盡管這類嵌套僅限定在正余弦函數(shù)中,但這仍給編程帶來了相當大的挑戰(zhàn)。
(1)度量分析
在這次作業(yè)中,我使用CheckStyle類檢查代碼格式,Calculator類完成求導計算,Print類完成化簡和輸出,Poly類作為存儲,Main類整體調度。可以看到,代碼復雜度相較前兩次有了明顯降低。部分類的復雜度較高的原因可能是我定義了比較多的正則表達式變量的原因。
(2)bug分析
我這次作業(yè)的bug主要來自于正則表達式的編寫錯誤。由于本次作業(yè)的結構與之前有較大差異,我重構了之前的正則表達式,不慎有一處括號寫錯了地方,導致在checkstyle部分產(chǎn)生了很嚴重的誤判。
二、debug經(jīng)驗
我debug的主要方法還是人工查bug(不會寫評測機的淚),效率很低,但對我個人編程能力有很大的提升。尤其是在閱讀代碼風格很好的代碼時,會讓人有眼前一亮的感覺。
我習慣先順著別人的思路將他的程序按流程過一遍,從而分析他的程序在哪一步可能會出問題。這種方法對于找bug而言效率很低,但是在閱讀學習他人程序時可以排上用場,靠人眼評測機來理解作者想要表達的意圖,并將其1轉化為自己的知識。
三、反思
第一單元的三次作業(yè),主要目的是給我們“練手”,逐漸培養(yǎng)面向對象的編程風格。因此,模塊化編程就十分重要了,我現(xiàn)在習慣在coding前先理一遍整體思路,將各個部分需要實現(xiàn)的功能規(guī)劃清楚,在一步步完善各個部分,最后將這些部件“組裝”成一個完整的程序。
轉載于:https://www.cnblogs.com/DoubleRider/p/10609120.html
總結
- 上一篇: 解决设置了display:none的元素
- 下一篇: Koa 中间件的执行