1、前言html
通過一個月來的學習,我從對面向對象一無所知到逐漸入門,圍繞着「多項式求導」,對面向對象的特性進行了探索。java
我對面向對象印象最深的兩句話就是「萬物皆對象」和「高內聚、低耦合」,這三次做業也是儘可能貫徹了這兩句話。正則表達式
咱們的做業從第一次的僅含冪函數的求導,到第二次包含正餘弦函數,再到最後函數能夠嵌套。一步步走來,面向對象的優勢也逐漸浮現出來。框架
2、分析工具模塊化
本次做業咱們用複雜度分析和UML類圖對代碼進行度量,首先介紹複雜度分析:函數
複雜度分析是對方法的圈複雜度進行分析,有三個衡量指標:ev(G), iv(G), v(G)工具
模塊設計複雜度是用來衡量模塊斷定結構,即模塊和其餘模塊的調用關係。軟件模塊設計複雜度高意味模塊耦合度高,這將致使模塊難於隔離、維護和複用。學習
模塊設計複雜度是從模塊流程圖中移去那些不包含調用子模塊的斷定和循環結構後得出的圈複雜度,所以模塊設計複雜度不能大於圈複雜度,一般是遠小於圈複雜度。測試
下面咱們結合代碼對其進行說明:spa
這是第一次做業打印多項式的一部分,能夠看到它的複雜度是
首先咱們來看v(G)的計算,畫出流程框圖,能夠看出這個圖共有10個點,14條邊,則v(G) = 14+2-10 = 6
而後咱們來計算iv(G),把沒有調用子方法的模塊簡化成一個點,這段代碼中只有for循環裏if內部沒有調用子方法,所以只有這個if被簡化,簡化後的圖以下
其中有點9個,邊12條,iv(G) = 12 + 2 - 9 = 5
最後計算ev(G),咱們要把原來流程圖結構化的部分簡化,這裏的結構化的部分指的是隻有if/for只有一個入口點,咱們代碼中的for循環就有兩個入口點,所以不能簡化(若把原代碼的break去掉就能夠簡化了),具體能夠查看Essential complexity - Wikipedia
所做流程圖以下,ev(G) = 8 + 2 - 7 = 3
UML類圖則是描述類與類之間關係的圖,其關係共有繼承、實現、依賴、關聯、聚合、組合六種,而這三次做業我僅用到了三種依賴,聚合與包含,其餘的之後用到了再作總結。
依賴關係是一個類使用了另一個類。
聚合關係是一個類內部有另一個類,即has-a關係。
繼承關係是一個類繼承了另一個類。
圖示:
依賴:
聚合:
繼承:
3、代碼分析
1. 第一次做業
第一次做業的思路挺清晰的,只知道「萬物皆對象」,就把表達式分紅一個個項,把表達式抽象成一個對象,把每一個項抽象成一個對象,而後用正則表達式去匹配每一項,提取x的指數和係數,而後對對每一項求導並加在表達式對象上,輸出就完事了。化簡也須要合併同類項,把正項放在第一位,係數爲1或-1不輸出,指數爲1不輸出。
圈複雜度:
能夠看出有幾個方法的圈複雜度挺高的,計算指數和係數,打印多項式,由於這幾個方法都有不少須要判斷係數爲不爲1,指數爲不爲1,致使有許多if-else結構。
UML類圖:第一次做業仍是挺簡潔的。
第一次做業算是入門了面向對象了,我努力的運用OO的思想去作此次做業,避免了一main到底的狀況,我還學到了正則表達式的使用,java語法結構等。
可是此次做業我出了好幾個BUG,1. 沒想到他們會用\f來hack,2.合併完同類項忘記刪除係數爲0的項。
這兩個BUG分別出在分析表達式和計算表達式上,都是由於沒考慮清楚才致使錯誤的。
在找BUG階段,我也使出渾身解數,第一次做業基本就是找WrongFormat大賽,畢竟此次求導太簡單了。用各類多符號,少數字的表達式去測試他們,還有合併同類項爲0、爆棧的數據,好比:
1231323 + 3131321++32131++661656161
2132*x+- 13213213++2313132*x^3213132
q123213+31321*x
x+x+x+x+x+x+x+x++x++x+-x+- x
313132x^100+x^100+x^99--x^99
3*x^-1+2*x^2
+ + x + + x ++ 2131 * x ^ 2236
321321*x^x
+
-
x^
500個+x
1000個1
x+x-x-x
此次做業相對簡單,能夠經過閱讀代碼來構造相應的數據來hack,有一位同窗就是用「 | 」做爲項與項之間的分隔,而後我構造了一個「|x」的數據他就錯了。
2.第二次做業
第二次做業和第一次做業特別類似,僅僅在因子中加入了sin(x),cos(x),其餘和第一次做業是同樣的,每一項均可以用「a*x^b*sin(x)^c*cos(x)^d」來表示,所以我用了和第一次做業同樣的結構而沒有去爲了兼容第三次而重構代碼(主要是懶)。
圈複雜度:
能夠看到此次的圈複雜度仍是在打印表達式和判斷表達式的方法比較高,依舊是那個問題須要判斷係數爲不爲1,指數爲不爲1,致使有許多if-else結構。
UML類圖:和第一次做業差很少
此次的化簡主要是運用cos(x)^2+sin(x)^2 = 1這個式子及變式進行化簡,用循環找出能夠化簡的項而後合併就OK。此次做業主要是鞏固了一下面向對象的知識點,鞏固一下正則表達式的使用,爲下一次做業作準備。
此次由於和上次的題目比較像,因此寫的挺完善的也沒被找出BUG。
找BUG階段則是閱讀別人的代碼,而後構造出相應的測試點。
3. 第三次做業
第三次做業的難度陡增,它從表達式的加減乘變成了能夠嵌套的模式,這就只能重構代碼了,這也揭示了一個問題:前兩次做業的代碼耦合度太高,難以修改。此次做業的思想主要是把表達式按加減號拆開,獲得各個項,再把項按乘號拆開,獲得因子,因子有括號,數字,x,sin,cos五種,其中sin,cos,括號能夠嵌套表達式,而後遞歸。
圈複雜度:
圈複雜度高的依舊是識別函數的方法,此次BUG就出在了識別上。
UML類圖:結構比前兩次做業複雜了許多
此次做業用到了繼承的思想,因子有5種,就用5個子類去繼承因子這個父類,這樣作的好處也很明顯,項是由因子構成的,能夠用一個ArrayList<Factor>去存儲五種因子,而不要分開存,求導也能夠直接調用重寫的求導方法Factor.derivation()。本次做業讓我對面向對象的理解又深了許多,也複習了一下遞歸的使用,遞歸真的好用。
找BUG此次也沒什麼很好的方法找,只能構建嵌套多層的因子,加各類指數去測試他們的遞歸會不會有問題,輸出會不會有問題。
此次我被找到了一個BUG,就是識別因子的時候,在不少判斷中漏了一個條件,致使有些因子識別不出來,會報WF,圈複雜度高果真容易出錯。
4、心得體會
幾回做業下來對面向對象有必定的瞭解,知道面向過程與面向對象的區別,明白了「高內聚,低耦合」的道理。在編寫代碼時,必定先用清晰的思惟去構思好程序的設計框架,這樣在寫代碼的時候就不容易由於思緒混亂而寫出帶BUG的程序。寫完程序後要編寫完備的測試樣例,不管是測試本身的程序仍是hack他人的程序都是極好的。
話很少說,繼續努力,面向對象,從我作起。
願諸君共勉!
原文出處:https://www.cnblogs.com/cherishlove/p/10606884.html