由於java正則表達式在實現時利用的NFA(不肯定有窮自動機),而NFA會佔用大量的計算能力,稍有不慎就會爆棧(特別是遇到".*")。因此本單元做業捨棄了使用java自帶的正則表達式,而是利用編譯原理的設計思想,手動寫DFA(肯定有窮自動機)。可是,在使用編譯原理的設計思想:自頂向下分析時,要注意消除左遞歸。所以,我每次做業都改寫了文法,使之可以使用DFA。StringParser類經過解析字符串,逐步產生各類各樣的Poly,Term,Factor對象,達到將字符串轉化爲一個表達式結構的目的。java
在分析結果中能夠看到ev, iv, v這幾欄,分別代指基本複雜度(Essential Complexity (ev(G))、模塊設計複雜度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G))圈複雜度。正則表達式
ev(G)基本複雜度是用來衡量程序非結構化程度的,非結構成分下降了程序的質量,增長了代碼的維護難度,使程序難於理解。所以,基本複雜度高意味着非結構化程度高,難以模塊化和維護。實際上,消除了一個錯誤有時會引發其餘的錯誤。設計模式
Iv(G)模塊設計複雜度是用來衡量模塊斷定結構,即模塊和其餘模塊的調用關係。軟件模塊設計複雜度高意味模塊耦合度高,這將致使模塊難於隔離、維護和複用。模塊設計複雜度是從模塊流程圖中移去那些不包含調用子模塊的斷定和循環結構後得出的圈複雜度,所以模塊設計複雜度不能大於圈複雜度,一般是遠小於圈複雜度。模塊化
v(G)是用來衡量一個模塊斷定結構的複雜程度,數量上表現爲獨立路徑的條數,即合理的預防錯誤所需測試的最少路徑條數,圈複雜度大說明程序代碼可能質量低且難於測試和維護,經驗代表,程序的可能錯誤和高的圈複雜度有着很大關係。函數
未發現bug測試
測試數據生成器爲使用Python語言編寫的dataMaker.py,經過導入的exrex包,就能夠隨機生成符合某正則表達式的字符串。優化
具體使用方法爲:spa
import exrex設計
dataString = exrexx.getone(rexString)3d
在bat腳本中寫入如下語句:
type input.txt | java -classpath %class_path% MainClass > output.txt
在bat腳本中寫入如下語句:
fc correct.txt myOutput.txt
StringParser類
Poly類
Term類
因而可知,代碼的複雜度主要出如今優化和轉化字符串方面。其實,能夠單獨爲優化和字符串轉化單獨創建一個類,這樣能夠減小這個類的複雜度。
bug在於在進行優化時,因爲採起的是四元組的存儲方式,hashmap的存儲結構。以a*x^b*sin(x)^c*cos(x)^d中的係數<a,b,c,d>爲四元組,<b,c,d>三元組爲鍵值。在合併某兩項時,直接把這兩項從hashmap中刪去便可,可是他們的和不能直接放入hashmap中,而是要先判斷是否已有和的鍵值,若是有就必須將已有的項與這個和相加再放入hashmap中。我沒有判斷直接放進去了,致使了bug。
自動化測試與上次一致
StringParser類
Poly類
Term類
本身程序的bug在於誤認爲在執行了某個方法後,已經不會出現空的項(也就是不含任何因子),但實際上沒有徹底消除。
(1)自動化測試與上次一致
(2)針對邊界數據手動寫測試樣例
(2)加上對被測試代碼的觀察,針對性hack
若是重構,會使用工廠模式來實現生成對象的邏輯與字符串解析的邏輯相分離。
通過了第一單元的三次做業的磨練,我明白了一個可擴展性的設計是很是重要的。第一次做業時,沒有想到要爲之後進行迭代,增長設計,因此程序寫的比較過程化,不利於擴展。所以,第二次做業不得不重構,這樣大大浪費了時間。第二次做業就比較注意結構化設計了,注重程序的高內聚低耦合。所以第三次做業在直接能夠在第二次做業的基礎上進行改進而無需重構。
在我看來,工廠模式是面向對象的設計方法裏比較能體現出OO特性的設計模式了。由於工廠模式會使得代碼更加模塊化,各司其職,每一個模塊都無需關心其餘模塊是如何工做的,只需利用其接口就能夠很好的完成任務。這能使代碼具備高內聚、低耦合的特性。關於在課上提出的若是工廠類的構造函數的參數不定數目,不定類型時,我以爲能夠將全部參數轉化爲一個字符串,經過對傳入的字符串進行解析便可。