[toc]架構
第一次做業結構很是簡單,除了MainCLass外,只用PolyComputer類負責解析表達式生成Poly類的實例。函數
對於類,有OCavg和WMC兩個項目,分別表明類的方法的平均循環複雜度和總循環複雜度。測試
能夠見得:第一次做業主要是PolyComputer類的複雜度比較高,由於筆者第一次做業是直接在parsePoly方法裏直接使用一個大正則來解析表達式。在printPoly方法裏直接使用了多個邏輯關係複雜的if分支來輸出表達式。spa
由上圖可見,第二次做業比第一次做業複雜了不少不少。這是由於筆者在第二次做業中進行了重構,併爲第三次做業的括號嵌套留下全部未來須要用到的接口。設計
筆者知道有一些同窗是把判斷表達式是否合法和解析表達式放在一塊兒的;將表達式求導和輸出表達式放在一塊兒。3d
但筆者並不贊同這樣的設計思路,這樣容易致使:對象
筆者堅持不由於效率而犧牲程序可讀性的設計思想,將整個複雜過程分解爲四個部分。blog
實際上筆者的類設計邏輯自認爲仍是很是清晰的,筆者並無採用同窗們經常使用的二叉樹。而是使用多叉樹。多叉樹只有三層,第一層是一個根結點Exp類,第二層是n個Term類,每一個Term類下面又有m個Factor類。繼承
另外第二次做業爲了簡化合並的過程,採用了Triple類表示一個Term類中常數項以及sin和cos的指數。遞歸
採用多叉樹而不是二叉樹的緣由以下:
因而可知,雖然第二次做業的代碼量雖然是第一次做業的四五倍,可是因爲合理的分層和解耦合的類設計,方法的複雜度反而大大下降了。
第三次做業相對於第二次做業幾乎沒有架構上的修改,仍然採用三層的多叉樹結構。只是將Term類中的Triple類換爲更通常的ArrayList<Factor>;以及在sin和cos中增長了Factor域表示內嵌的因子。
雖然第三次做業比第二次做業的難度更大,實現更復雜。可是因爲筆者良好的分層設計和第二次留下的充足的擴展接口,第三次做業的方法複雜度相較於第二次做業幾乎沒有變化,甚至下降了一點。
三次做業中,我只在第三次做業中存在bug,bug出現的緣由是我爲了縮短輸出長度,將輸出中全部的x**2換成了x*x,而當冪函數因子x**2做爲三角函數的內嵌因子時,將其換爲表達式x*x後獲得的表達式是非法的。
仔細分析此次出錯的緣由:
設計結構方面:正如文章第一部分所說,個人第二三次做業的架構是十分清晰的,將整個過程解耦合爲判斷表達式的合法性、解析表達式生成Exp|Item|Factor類、表達式求導、表達式輸出四部分。bug只與第四部分表達式輸出有關,具體問題出在了Pow類的String方法。只需註釋掉將x**2換成x*x的那一行代碼便可。
測試方面:三次做業中本人都寫了自動對拍機。但爲什麼自動對拍機沒能監測出第三次做業的bug呢?由於個人對拍機直接使用Sympy求導覈對數值,並無檢驗輸出的表達式的合法性。這是一個教訓,仔細閱讀指導書時我本應該讀到「輸出表達式也要求符合形式化表述」,就應該對輸出表達式也進行形式化檢驗。
我發現別人bug的策略是以本身構造的有針對性的測試數據和自動測試機二者並行。
本身構造的測試數據筆者留待第五部分再詳述。自動測試機一開始是隨機生成表達式;以後也會經過對正則的調整生成不少有針對性的數據。
第一次做業十分簡單,筆者爲了省事沒用採用任何模式。而後第二次做業筆者設計了三層多叉樹,在第三層中全是Factor類,所以筆者也採用工廠方法模式來建立和管理Factor類。定義了Factory接口,各個因子的工廠類並實現接口。但在處理Factor類時,筆者並未採用接口而是採用抽象類Factor,子類Sin、Pow等繼承抽象類。
正如在第一部分分析的,筆者經過對合理的類設計實現對過程的分層和分解。這就是做者目前理解到的面向對象程序設計(可能還過於淺薄)。筆者感受經過類設計實現過程分層和分解的思路十分好用,很容易設計出邏輯清晰,可讀性強,便於維護的代碼。
分爲如下步驟:
在動手寫代碼前先依照指導書構造有針對性的測試數據集;在coding前就構造數據集有助於理解程序易出錯的地方,減小寫代碼時的bug。
在寫代碼時可能還會額外想到其餘針對性數據,增長到數據集裏面。
白盒測試。筆者每寫完一個功能獨立的模塊,都會對此模塊進行白盒測試。
經過Python實現自動測試。
其實還能夠採用小黃鴨測試法等等......
本次做業極大地加深了筆者對遞歸的理解...特別是筆者這次設計了一個相互遞歸調用的邏輯:解析表達式時調用三角函數的因子的解析方法,解析三角函數的因子時調用表達式的解析方法。具體以下圖。
求導過程亦是如上所述的相互遞歸調用;甚至化簡過程也是相互遞歸調用。
本次對遞歸的理解:
1.遞歸須要造成一個調用環:本身調用本身,或者本身調用別人,別人再調用本身。
2.遞歸須要有一個出口,如上圖的圓圈。
之後使用遞歸時,只須要畫出如上所示的遞歸調用圖,就能夠思路清晰地完成。