OO第一次博客做業

OO第一次博客做業

前言

本次博客做業,本人將以三次做業爲單元進行分析,再借着講查bug的方式說說本身的搭評測姬的方式,最後總結一些面向對象相關的經驗。java

第一次做業

UML結構圖

結構分析

第一次OO做業的功能需求相對簡單,本人把整個構造、簡化輸出以及它們用到的一些private方法所有丟到Polynomial類中實現,同時爲了避免讓文件數量太少顯得尷尬我專門寫了個求導類,用於求導功能的實現。因爲第一次做業的業務邏輯以及優化邏輯相對簡單,故這種「大鍋菜」式的設計並無帶來什麼困擾,反而寫的很快(霧正則表達式

耦合度分析

如前文所言,本次做業,我寫的比較面向過程,整個parse的過程所有丟在polynomial的一兩個方法中完成,使得方法以及類的複雜度太高。多線程

這種設計在面對第一次這種較爲簡單的設計尚有生存的餘地,當工程的複雜度持續走高的時候,仍然用這種方法基本上是自掘墳墓。less

難點分析

第一次做業的主要難點在於正則表達式解析字符串,基本上用小正則不斷分解字符串便可,大正則的朋友是真的狼。500行狀態機的狼滅們,求求您們住手函數

BUG分析

本人的BUG

第一次做業除了輸入部分沒啥坑點,因此很不巧,本人強測、互測都沒被找出bug(攤手手學習

同屋的BUG(高能預警)

第一次做業的強測有一點點小尷尬,100分的門檻過低,致使一個屋內的水平差別有丶大,因此就出現了5錘3到4錘4的慘烈場面。測試

第一次做業中的BUG基本沒有在計算上的問題,~~除了那些被不知道怎麼混進來的,被捅了20多刀的朋友,~~問題主要在於輸入處理上,好比先trim了一下再去判\v\f的狀況,以及神奇的大正則爆棧。優化

這裏要說個小插曲,在第一次討論課分享後,本人竟然被人找上門婊了,對方的理由是「你不以爲大家這種找別人\v\f的bug的行爲很鑽營麼?spa

這位同窗當時的意思(個人理解)是官方指導書說能夠有「空白字符」,因此咱們用\v\f是鑽營的。操作系統

exm??????

首先,WF問題原本就是官方規定的BUG之一,第一次做業並無取消這一hack方式,因此,hack這種數據徹底合乎規矩。

第二,互測自己就包括測試程序的魯棒性,天然要測試程序在處理各類玄學輸入狀況的表現,輸入\f\v有何不合理?

第三,官方給的「空白字符」有着明確的定義,橫向製表符和空格符,咱們輸入\v\f不屬於此類。既然您喜歡先入爲主,代入本身的主觀理解,同時不去認真理解指導書的語義,那您被\v\f數據hack又豈是他人之過?

第四,水羣裏,討論區裏對於\v\f是否屬於空白字符的討論還少麼?既然您喜歡自我封閉地處理本身不明確的定義,那麼就請作好被hack的準備。

第五,本人對於那位同窗的水平也稍有認識,我不認爲 ta 會跟我分到一個組,因此,冤有頭,債有主,你找我幹嗎?

好了,平靜一下心情,看看下一個做業。

第二次做業

UML結構圖

結構分析

此次設計我用了常見的三級層次,最頂層爲Poly,Poly由Term組成,Term由Factor組成。

此次的設計中,我仍然把Poly的構造與字符串檢查與解析放在了Poly的構造函數中實現,同時把各類優化方法,是否包含Term的檢查放在Poly類內部實現,使得這個類過於臃腫。

此外,此次的Term類內部也包含了各類計算方法,使得這個類有點臃腫。

耦合度分析

Method ev(G) iv(G) v(G)
CosFactor.CosFactor(BigInteger) 1 1 1
CosFactor.derivation() 2 2 2
CosFactor.toString() 3 3 3
Factor.Factor(FactorType,BigInteger) 1 1 1
Factor.getDegree() 1 1 1
Factor.getType() 1 1 1
FactorFactory.produce(FactorType,BigInteger) 5 2 5
FactorFactory.produce(FactorType,String) 2 2 2
Poly.Poly() 1 1 1
Poly.Poly(ArrayList<Term>) 1 2 2
Poly.Poly(String) 3 2 5
Poly.add(Poly) 1 4 4
Poly.betterSolution(ArrayList<Term>,Term,Term) 3 4 9
Poly.canCos2ToOneSubSin2(Term,Term) 1 3 5
Poly.canSin2AddCos2(Term,Term) 1 2 3
Poly.canSin2ToOneSubCos2(Term,Term) 1 3 5
Poly.cleanUp() 1 3 3
Poly.derivation() 1 2 2
Poly.getArrayList() 1 1 1
Poly.getTerm(TermKey) 1 1 1
Poly.hasTerm(Term) 1 1 1
Poly.lengthBetter(Poly,Poly) 1 1 1
Poly.main(String[]) 1 3 3
Poly.mergeSin2AddCos2(Term,Term) 1 4 4
Poly.mult(Poly) 1 3 3
Poly.optimization() 1 6 9
Poly.parsePoly(String,Pattern[]) 2 5 6
Poly.parseTerm(Pattern[],Matcher,BigInteger) 5 11 11
Poly.simplifyCos2ToOneSubSin2(ArrayList<Term>,Term) 1 1 1
Poly.simplifySin2AddCos2(ArrayList<Term>,Term,Term) 1 1 1
Poly.simplifySin2ToOneSubCos2(ArrayList<Term>,Term) 1 1 1
Poly.sub(Poly) 1 2 2
Poly.toString() 3 3 4
PowerFactor.PowerFactor(BigInteger) 1 1 1
PowerFactor.derivation() 3 3 3
PowerFactor.toString() 3 3 3
SinFactor.SinFactor(BigInteger) 1 1 1
SinFactor.derivation() 2 2 2
SinFactor.toString() 3 3 3
Term.Term() 1 1 1
Term.Term(ArrayList<Factor>) 1 1 1
Term.Term(BigInteger) 1 1 1
Term.Term(BigInteger,ArrayList<Factor>) 1 1 1
Term.TermKey.equals(Object) 4 1 6
Term.TermKey.getFactor(FactorType) 1 1 1
Term.TermKey.hashCode() 1 1 1
Term.add(Term) 2 2 2
Term.contains(FactorType) 4 3 4
Term.copy() 1 1 1
Term.derivate() 1 4 4
Term.getCoe() 1 1 1
Term.getDegree(FactorType) 2 2 2
Term.getFactor(FactorType) 4 4 4
Term.getTermKey() 1 1 1
Term.mult(BigInteger) 1 1 1
Term.mult(Factor) 1 1 1
Term.mult(Term) 1 1 1
Term.put(Factor) 3 3 3
Term.toString() 7 7 9
Term.upToPoly() 1 1 1
Class OCavg WMC
CosFactor 2 6
Factor 1 3
FactorFactory 3.5 7
FactorType n/a 0
Poly 2.92 76
PowerFactor 2.33 7
SinFactor 2 6
Term 2.17 39
Term.TermKey 2 6

可見,因爲上文所述的設計結構上的欠考慮,此次的耦合度與複雜度是太高了。

主要體如今字符串解析,與各類Term,Poly的計算所有放在內部實現,所致使的臃腫。通過此次教訓,本人在第三次做業對結構作出了必定的調整。

難點分析

此次一部分同窗已經採用了多態的操做,這也就意味着,他們的Term內部極可能包含着幾個Factor對象。

求導工做就是基於這幾個對象的,這也就帶來了一個問題,你的對象應該是可變的仍是不可變的,你的求導是直接改變對象自身屬性仍是新建一個對象。

個人建議是對象不可變,任何運算都獲得一個新的對象。這樣能夠有效防止本身時不時出現寫着寫着修改了一些共享的對象,從而致使一些本身一時看來匪夷所思的bug。

除了這個小難點之外就是優化了,本人數學不太好,因此此次涉及到各類數學公式的無聊的優化,我就隨便搞了兩三個就摸了。

BUG分析

本身的BUG

本人此次沒被查出bug,可是後來發現本身的hashcode彷佛寫錯了,但又好像沒錯,果真姿式水平不高,語言特性不熟悉。

此外此次強測有一些小插曲,致使了互測的神奇狀況

本次公測中,我成功反向hack了公測數據(霧)

同屋BUG

本次互測中我測出來的的BUG主要集中在輸入處理部分,此次的正則表達式比上次難度提高了一些,可是並無本質區別,測出的bug更像是對指導書理解有誤差。

計算的BUG主要在於合併同類項的時候在係數和指數的處理上出了些小BUG,以及在求導時忘了把那一項的係數乘上(霧

總而言之,此次的BUG中,WF的比率相對下降,計算、求導、優化的BUG更多。

第三次做業

UML結構圖

結構分析

本次做業我大致沿用了第二次做業的設計思路,多項式的結構分爲三個層次 Poly,Term,Factor

稍有不一樣的幾點,

  1. 本次的設計中,我把常數項由原來的做爲Term的屬性改變爲Term的成員,這麼作的緣由有以下幾點
    • 嵌套因子求導會產生大量的新的常數,原有的方式處理起來很不優雅。
    • 常數因子從數學上來看確實應該算是因子的一種,支持求導等操做。
    • Term求導後的結果是一堆Factor,Term自己就是一個actor的管理者身份,正好能夠生成一個全新的Term。
  2. 把字符串解析,Term,Poly,Factor的計算提取出來,變成Parser類與Calculator類,下降單個類的複雜度。
  3. 使用了自定義的異常。

耦合度分析

Method ev(G) iv(G) v(G)
code.Calculator.add(Term,Term) 5 5 5
code.Calculator.mult(Factor,BigInteger) 1 1 1
code.Calculator.mult(Factor,Factor) 1 1 1
code.Calculator.mult(Poly,BigInteger) 1 2 2
code.Calculator.mult(Poly,Poly) 1 3 3
code.Calculator.mult(Poly,Term) 1 2 2
code.Calculator.mult(Term,BigInteger) 1 1 1
code.Calculator.mult(Term,Factor) 3 3 3
code.Calculator.mult(Term,Term) 1 1 1
code.ConstantFactor.ConstantFactor() 1 1 1
code.ConstantFactor.ConstantFactor(BigInteger) 1 1 1
code.ConstantFactor.canExtract(Factor) 5 3 6
code.ConstantFactor.canMerge(Factor) 2 1 2
code.ConstantFactor.differential() 1 1 1
code.ConstantFactor.equals(Object) 3 1 3
code.ConstantFactor.extract(Factor) 2 1 2
code.ConstantFactor.getValue() 1 1 1
code.ConstantFactor.merge(Factor) 1 1 1
code.ConstantFactor.optimization() 1 1 1
code.ConstantFactor.toString() 1 1 1
code.CosFactor.CosFactor(BigInteger) 1 1 1
code.CosFactor.CosFactor(BigInteger,Factor) 1 1 1
code.CosFactor.canExtract(Factor) 5 4 7
code.CosFactor.canMerge(Factor) 4 4 6
code.CosFactor.differential() 3 2 3
code.CosFactor.equals(Object) 5 4 7
code.CosFactor.extract(Factor) 1 2 2
code.CosFactor.getInnerFactor() 1 1 1
code.CosFactor.merge(Factor) 1 1 1
code.CosFactor.optimization() 2 2 3
code.CosFactor.toString() 4 4 4
code.Extracter.extractForPoly(Poly) 1 8 9
code.Extracter.extractTerm(Term,Term) 5 6 8
code.Extracter.getSimplified(Term,Term) 4 8 10
code.Extracter.getTheDeltaFactors(Factor,Factor) 6 6 6
code.Factor.Factor(BigInteger) 1 1 1
code.Factor.getDegree() 1 1 1
code.Factor.upToTerm() 1 1 1
code.Parser.Parser(String) 3 1 3
code.Parser.checkBigDegree(BigInteger) 1 1 1
code.Parser.clearBlank() 1 2 2
code.Parser.getChar(int) 2 2 3
code.Parser.getCosFactor() 3 1 3
code.Parser.getDegree() 2 2 2
code.Parser.getFactor() 6 6 6
code.Parser.getInnerFactor() 5 2 5
code.Parser.getPoly() 2 6 7
code.Parser.getPolyFactor() 1 1 1
code.Parser.getPowerFactor() 4 3 4
code.Parser.getSinFactor() 3 1 3
code.Parser.getTerm() 4 6 8
code.Parser.staticCheck(String) 3 3 5
code.Poly.Poly(ArrayList<Term>) 1 1 1
code.Poly.canDownToTerm() 1 1 1
code.Poly.cpTerms() 1 1 1
code.Poly.deleteUseless() 1 4 4
code.Poly.differential() 1 2 2
code.Poly.downToTerm() 3 2 3
code.Poly.equals(Object) 9 3 10
code.Poly.getTerms() 1 1 1
code.Poly.mergeSameTerm() 1 4 4
code.Poly.optimization() 1 2 2
code.Poly.toString() 3 3 4
code.PolyException.PolyException() 1 1 1
code.PolyFactor.PolyFactor(Poly) 1 1 1
code.PolyFactor.canExtract(Factor) 1 1 1
code.PolyFactor.canMerge(Factor) 1 1 1
code.PolyFactor.cpInnerPoly() 1 1 1
code.PolyFactor.differential() 1 1 1
code.PolyFactor.equals(Object) 4 4 6
code.PolyFactor.extract(Factor) 1 1 1
code.PolyFactor.getInnerPoly() 1 1 1
code.PolyFactor.merge(Factor) 1 1 1
code.PolyFactor.optimization() 3 3 3
code.PolyFactor.toString() 1 1 1
code.PowerFactor.PowerFactor(BigInteger) 1 1 1
code.PowerFactor.canExtract(Factor) 3 2 4
code.PowerFactor.canMerge(Factor) 2 1 2
code.PowerFactor.differential() 1 1 1
code.PowerFactor.equals(Object) 2 1 2
code.PowerFactor.extract(Factor) 2 2 2
code.PowerFactor.merge(Factor) 1 1 1
code.PowerFactor.optimization() 1 1 1
code.PowerFactor.toString() 2 2 2
code.SinFactor.SinFactor(BigInteger) 1 1 1
code.SinFactor.SinFactor(BigInteger,Factor) 1 1 1
code.SinFactor.canExtract(Factor) 5 4 7
code.SinFactor.canMerge(Factor) 4 4 6
code.SinFactor.differential() 3 2 3
code.SinFactor.equals(Object) 5 4 7
code.SinFactor.extract(Factor) 1 2 2
code.SinFactor.getInnerFactor() 1 1 1
code.SinFactor.merge(Factor) 1 1 1
code.SinFactor.optimization() 2 2 3
code.SinFactor.toString() 4 4 4
code.Term.Term(ArrayList<Factor>) 1 1 1
code.Term.Term(BigInteger) 1 1 1
code.Term.Term(BigInteger,ArrayList<Factor>) 1 1 1
code.Term.Term(Factor) 1 1 1
code.Term.canDownToFactor() 4 2 5
code.Term.canMerge(Term) 11 7 12
code.Term.compareTo(Object) 1 1 1
code.Term.containOnlyPolyFactor() 6 3 6
code.Term.cpFactors() 1 1 1
code.Term.cpSelf() 1 1 1
code.Term.deleteUseless() 1 3 3
code.Term.differential() 1 4 4
code.Term.downToFactor() 6 3 7
code.Term.getCoe() 3 1 3
code.Term.getFactors() 1 1 1
code.Term.getFactorsSize() 1 1 1
code.Term.merge(Term) 1 1 1
code.Term.mergeConstant() 1 4 5
code.Term.mergeSameFactor() 1 4 4
code.Term.mult(BigInteger) 1 1 1
code.Term.mult(Factor) 1 1 1
code.Term.mult(Term) 1 1 1
code.Term.optimization() 5 7 7
code.Term.toString() 9 9 11
code.Term.upToPoly() 1 1 1
code.Test.main(String[]) 1 3 3
code.Test.outputLogic(Poly) 1 2 2
Class OCavg WMC
code.BigDegreeException n/a 0
code.BracketException n/a 0
code.Calculator 2.11 19
code.ConstantFactor 1.73 19
code.CosFactor 2.73 30
code.Extracter 7 28
code.Factor 1 3
code.FactorException n/a 0
code.FormatException n/a 0
code.Parser 3.5 49
code.Poly 3 33
code.PolyException 1 1
code.PolyFactor 1.45 16
code.PowerFactor 1.67 15
code.SinFactor 2.73 30
code.Term 3.12 78
code.Test 2 4

此次的複雜度主要在於Parser,Extracter,Term這三個類。

Parser中,我用了遞歸降低的操做,第一次使用這個方法,寫得比較面向過程,也比較醜。

Extracter這個類是我週二晚上得知延時的消息後,連夜趕工的一個提公因式的類,時間緊促,就沒有作太多的設計,致使比較醜。

Term類的設計中,我欠考慮了。本次個人主要優化操做是經過把Term轉換成Poly或者轉換成Factor來完成的,這須要不少的斷定條件,我雖然把計算等方法提取出來了,可是這些斷定方法我仍留在Term中,致使了較大的複雜度,這是設計上的敗筆。

難點分析

輸入處理

當加入了嵌套這一輸入格式以後,單用正則表達式已經難以實現輸入處理了。受同窗啓發,我此次採用了遞歸降低的方法並結合正則表達式進行輸入處理,利用正則表達式的group()來輔助遞歸降低的偏移量計算。效果相對較好。

因爲第一次使用遞歸降低,在實現階段,bug不斷,常常出現漏加偏移量等BUG,並致使我在中測中浪費了大量提交機會。

優化輸出

這一次優化的重點在於去掉那些層次太深,且毫無心義的括號,本人此次的優化還算能夠,可以去除掉多數狀況的無心義括號。

BUG分析

本人的BUG

此次本人測試本身代碼的時候沒有像之前那樣先把數據生成器寫好再進行測試,而是上來就手動測試並提交,致使BUG不斷。

不過這些BUG都在於輸入處理的遞歸降低之中,其餘部分倒尚未找到bug。

不過,得益於那幾天的血淚,公測、互測仍是滿血過關。

此外,此次個人自動化測試還出了些小插曲,留到後頭再說。

總得看來,此次課下測試真的把我打怕了,直到強測結果出來的時候才鬆了口氣。

本人之後爭取保證每次都作到「測試先行

同屋BUG

此次遇到的BUG又回到了輸入處理上,這個也就沒啥好說的了,遞歸降低處理這種多項式要注意的點仍是挺多的,沒有自動化測試的狀況下出現輸入處理上的bug也很常見,雖然本不該該(

別人說起的BUG

在本次做業的深夜爆肝中,我也時不時地和一些同窗交流問題。

其中一位同窗就說起了我以前說的共享對象的可變性致使的BUG。如今咱們面對共享對象出現的BUG的根源主要在於「對象」,「引用」沒有分清,「深拷貝」,「淺拷貝」沒分清,我我的的建議是,用不可變對象,每次計算或求導以後返回一個新的對象,而不在原有對象上修改,並利用JAVA的垃圾回收處理不被引用的對象。(想一想BIgInteger的計算,相似)

目前,咱們對於共享對象的問題主要在因而否可變,下一單元的多線程中共享對象怕是更加麻煩。(哭遼

狼滅

狼屋友

今年和往年不同,再也不是一對一的solo,而是八人聖盃戰爭。

若是還像往年那樣,逐字逐句地挑,顯然有點太耗時間,且不太值得。

測試方法很簡單,評測姬先每人掃上50份隨機數據,若是有比較naive的bug的話,此時基本上就已經倒了。

以後對那些能頂50次的代碼再進行千份級別的掃射,同時,本身打開代碼看看有沒有一些常見的BUG,並把本身曾出過問題的數據放進去測試。

若是這樣子還沒找到BUG,那大機率是沒啥BUG了,不過總有例外,好比,我在自我測試的時候就掃出來過本身的一個BUG,是一個括號匹配問題的BUG,BUG很naive,可是我沒注意到,通常狀況下也不會生成那樣的數據(好比") 1 ("識別不出來錯誤),掃射了幾萬份數據後終於查出。

因此對於那些足夠「硬」的代碼,我通常是睡覺的時候掃上個幾萬份,若是再沒有BUG,就根據時間安排,決定是否要逐字逐句地找BUG。

搭個評測姬

結構

  1. 數據生成器
  2. 待測程序
  3. 標準程序
  4. Judge
  5. 結果存儲

這其中,每次做業均可以複用的是待測程序,標準程序的調用方法,結果存儲的文件結構。

那麼,爲了代碼複用,簡化開發流程(留下了每次用C++從頭rush評測姬的血淚)我利用java的繼承和多態機制

實現了快速改裝的評測姬。

下面簡要介紹一下一些可能不那麼醜的設計思路

1.文件結構

評測姬具備初始化文件夾與評測日誌的方法。

每一個從者對應一個文件夾,Ruler做爲標程。

每一個文件夾下存放對應從者的代碼文件夾,以及各類測試數據的文件夾

各類測試數據的文件夾內存放着對應數據的測試結果以及統計信息。

2.測試數據生成器

測試數據生成器實現一個統一的「供彈」接口,使得咱們的評測姬能夠選擇不一樣類型的測試數據。

這麼作至少有一個好處,好比說,一我的的程序會在冪的整數帶有正號的狀況下崩潰,可是你又想找到他運算的BUG。那麼,就能夠爲他設計一個冪不帶正號的測試數據,從而便於區分非同質BUG。

強調一點

利用評測姬進行掃射的基礎是你的生成器足夠強大,可以生成出命中對方思惟漏洞的數據(爲何不說實現時的手殘呢? 由於,這年頭誰還沒個評測姬了?)這也就要求,對方的思惟並無達到基本正確性的要求,而且你達到了。那麼,你的數據生成器纔是具備效力的。

此外,評測姬毫不僅僅是用來狼人的,不少時候是用來狼本身的,能夠檢查出本身思惟或者實現的錯誤。

面向對象的一些學習經驗

這部分我將以我回答一些我思考過的問題的方式來呈現。

爲何要面向對象

把問題用一個個點(對象)之間的聯繫方式來體現,從模型的構建上來看,比較方便且直觀。

對此,我就想到了寒假摸得一個叫ROS的東西,那個機器人操做系統就是基於各個點之間的通訊來實現一個完整的功能,比方說,我如今想寫一個自動駕駛(差速驅動轉向)的程序,用java來寫,我得有個輪子類,一個引擎類,一個地圖類,一個雷達類,一個調度類,這些類組合成了一個新的類——小車,叫他小車有點low,那就叫他Pusher叭~,這個Pusher內部包含着上述幾個類。在Ros中,體現爲,引擎節點,雷達節點,調度節點等等。

在JAVA中,對象之間的聯繫由傳參,返回值,共享對象之類的方式,ROS中也有請求服務方式(傳參,返回值),話題方式(共享對象)。

說了這麼多看似沒啥關係的東西,我主要想說明一件事,我認爲面向對象的做用主要體如今便於咱們把現實中的問題抽象出一個更貼近現實的模型,從而在思惟上解決起來更加容易。

關於建立模式

前三次做業中,對象的複雜度愈來愈高,若是仍然把對象的建立經過一個簡簡單單的 new() 來實現,會致使,功能與建立過分耦合,代碼複雜度驟然提升。因而我在第三次做業中把整個多項式最複雜的建立方式——字符串解析方式交由Parser實現。從而下降了複雜度。

此外,對於那些具備衆多同類型屬性、類似的不一樣類咱們能夠採用工廠的方式來建立新的對象,從而,進一步將對象的構造與功能分離,下降耦合度。

相關文章
相關標籤/搜索