软件工程启程篇章:C#和四则运算生成与运算
0x01 :序言
I leave uncultivated today,
was precisely yestoday perishes tomorrow
which the person of the body implored
?
“看不清楚的時光印痕,像是泛黃的底片,明明還記得那個故事,卻忘了故事里的風月”,不知如今因為生成規(guī)則、詞法排序或效率而爭執(zhí)地面紅耳赤的少年們,多少歲月走過重新翻閱看著七零八落的注釋和代碼段,是否只得慨嘆歲月這把最鋒利的殺豬刀,然而,即便最終能停留在代碼段的注釋行不過寥寥數(shù)語,然而乏善可陳卻又萬分鄭重的寫下每一字,想讓她聽起來特別,我聽到她說謝謝我,就像從List<String>.contains()到Hashtable.Add(string.getHashCode(),string)的變化,就像從Number.Created()到CreatedList.Created()的變化,正確性,結(jié)構(gòu)化,效率。
謹以此文致以軟件工程的啟程,你好,舊時光
?
0x02 :軟件工程和PSP表格記錄
I am a slow walker,
but I never walk backwards.
Although with hippopotomonstrosesquippedaliophobia and bugphobia
?
| PSP 2.1 | Persinal Software Process Stages | Time(Estimated) | Time(Real) |
| Planning | 計劃 | ? | ? |
| Estimate | 估計這個任務(wù)需要多少時間 | 8h | 17h |
| Development | 開發(fā) | ? | ? |
| Analysis | 需求分析(包括學習新技術(shù)) | 1~2h | 2~3h |
| Design Spec | 生成設(shè)計文檔 | 20~40min | 20min |
| Design Review | 設(shè)計復審 | 5~10min | 1min |
| Coding Standard | 代碼規(guī)范 | 20~40min | 20min+2h(*) |
| Design | 具體設(shè)計 | 1~2h | 15min+2h(*) |
| Coding | 具體編碼 | 2~3h | 6~7h |
| Code Review | 代碼復審 | 30min~1h | 30min+2h(*) |
| Test | 測試 | 1~2h | 1h30min |
| Reporting | 報告 | ? | ? |
| Test Report | 測試報告 | 30min~1h | 20min |
| Size Measurement | 計算工作量 | 1h | 2~3h |
| Postmorten & ProcessImprovement Plan | 事后總結(jié), 并提出過程改進計劃 | 30min~1h | 1h |
| ? | 合計 | 8h15min~ 14h30min | 16h16min~ 19h16min |
表格補充說明:(*)表示因為前期思考時間不足而重構(gòu)所增加的時間
?
對于C#和四則運算生成和計算,首先我們確定基本的功能模塊(http://www.cnblogs.com/jiel/p/4810756.html)
??????? 對于參數(shù)range和number,能夠依據(jù)參數(shù)生成特定的四則運算表達式,對于必須的基本要求,我們必須確保生成子表達式結(jié)果非負數(shù),同時運算符個數(shù)也不超過3個,而且各表達式不能通過有限次的乘法或加法交換為同一道試題
??????? 對于參數(shù)range和number,在實現(xiàn)基本功能的前提下需要考慮的是性能和效率的問題,比如:“生成的表達式中是否各符號的出現(xiàn)率相差不超過10%”,“括號的出現(xiàn)是否具備較強的隨機性”,“表達式的數(shù)值是否均勻分布在[0,range]區(qū)間”,“查重或者所定義的規(guī)則是否具備較高的時間效率”
??????? 對于參數(shù)exercise和answer,我們需要能夠解析標準的四則運算表達式并將它計算出正確結(jié)果,與answer文件進行對照從而記錄正確與錯誤題號
??????? 對于參數(shù)exercise和answer,在解析并計算標準的四則運算表達式時應盡可能快速地計算出正確結(jié)果,而對于逆波蘭表達式,其時間復雜度為O(kn),而其他效率更高的算法也只是對常數(shù)k進行優(yōu)化,且實現(xiàn)的復雜度極高,因此不妨直接選取逆波蘭表達式作為解析方法
?
0x03 :項目設(shè)計文檔基本思路
1 universe, 9 planets,
204 countries,809 islands, 7 seas,
and i had the privilege to meet you.
?
??????? ? 由基本的功能模塊,我們可以將此次個人項目分解為階段性的模塊工作:
?
??????? 在底層上,需要實現(xiàn)同時支持{數(shù)域:真分數(shù),自然數(shù)}{運算符:四則運算符,左右括號}的數(shù)據(jù)結(jié)構(gòu)或類
??????? 在功能層次上,主要實現(xiàn)表達式的構(gòu)造、生成和計算,并能通過中綴表達式向后綴表達式的運算實現(xiàn)計算結(jié)果的正確性
??????? 同時,我們能盡可能在盡可能的大的范圍內(nèi)實現(xiàn)表達式的構(gòu)造,同時又必須保證不具備重復性,且減法和除法有效性不能被破壞
??????? 在前端層次上,主要實現(xiàn)命令行參數(shù)的解析,最終實現(xiàn)函數(shù)所具備的的生成和計算功能
?
0x04 :UML圖的設(shè)計思路整理與程序正確性證明
To the world,you maybe a person.
But to a person,you maybe the world.
?
?
?
?
0x0401 Number基礎(chǔ)類的架構(gòu)
?
internal class Number
{
??????? /*Basic Parameter for class Number (Random with the parameter of -r)*/
??????? private long parent;
??????? private long child;
}
由UML圖的基本架構(gòu)中,在Number類的基礎(chǔ)類的構(gòu)造中,不僅需要設(shè)置存儲形式為“假分數(shù)”即(child/parent),同時重載了基礎(chǔ)的四則運算(但未同C++時重載運算符),同時重載(Override)ToString()方法,保證在輸出的時候仍為標準形態(tài)的真分數(shù);
?
因此,基于此數(shù)據(jù)結(jié)構(gòu)的架構(gòu),我們隱性地做出了如下的定義:
?
??????? 假分數(shù)實現(xiàn)基本的加減乘除運算,同時為盡可能擴大假分數(shù)的運算范圍,我們在每調(diào)用計算的時候都會調(diào)用最小公約數(shù)gcd()函數(shù)(由于為O(log)級的算法,所以可以相對忽略此時間消耗),從而保證計算效率
??????? 若恰為整數(shù),則強制要求分母為1即可
??????? 在打印的過程中,將通過重載ToString()函數(shù)保證輸出的正確性
?
因此,對于程序的正確性,通過覆蓋性的單元測試(共4 * 4 * 4 = 64種),即將Number劃分為int類型的自然數(shù),long類型的自然數(shù),真分數(shù),帶真分數(shù)四種情況對程序進行測試,運算結(jié)果符合預期,因此通過單元測試不妨默認程序在此測試樣例的情況下程序正確運行,因此,在無特例的情況下不妨認為Number類滿足程序正確性
?
0x0402 ParseNumber基礎(chǔ)類的架構(gòu)
?
internal class ParseNumber
??? {
??????? private String parse;
??????? private Number result;
??????? private Regex regex_1 = new Regex("^[1-9]{1}[0-9]*['][0-9]+[/][1-9]{1}[0-9]*$");
??????? private Regex regex_2 = new Regex("^[0-9]+[/][1-9]{1}[0-9]*$");
??????? private Regex regex_3 = new Regex("^[0-9]+$");
}
?
ParseNumber類通過正則表達式的檢測實現(xiàn)字符串類型變量expression到Number類型的轉(zhuǎn)換,而若無法通過正則匹配時由于字符串切分工作通過其他類正確實現(xiàn),因此,可直接構(gòu)造拋出new NotImplementedException();,通過屏蔽機制在Main函數(shù)中try-catch捕獲即可,對于功能模塊的此類,只能通過單元測試來盡可能保證程序正確性,因此與Number類的程序正確性證明類似,不妨在無特例的情況下認為ParseNumber類滿足程序正確性
?
0x0403 Poiland/MyApp類的架構(gòu)
?
Poiland類通過通過數(shù)據(jù)結(jié)構(gòu)棧的使用實現(xiàn)后綴表達式的快速解析,在注釋中有著較好的說明:
/* Kernel Method
?* - Poiland temp = new Poiland(String);
?*?? temp.getResult();
?*??
?* = String presents for the input of expression(Type:String)
?*?? Init Object temp with initation of input and convert to Behind-Expression
?*?? Cal Such Expression with Stack
?*/
而MyApp類提供Main函數(shù)入口,因此這兩類程序正確性證明暫時可認為滿足程序正確性,主要將針對CreatedList類展開程序正確性的論證
?
0x0404 CreatedList類的架構(gòu)
?
CreatedList類主要實現(xiàn)隨機四則運算表達式的生成,我們首先確定這樣的基礎(chǔ)思想,在任何range參數(shù)的取值情況下,生成數(shù)量與重復率成正相關(guān),但在range參數(shù)足夠大時,若通過隨機化方法生成操作數(shù)和操作符隨機組合,重復概率極小,理論計算基本處于1%%的數(shù)量級,甚至在隨機化的處理方法上,表達式重復概率基本可以忽略不計,而若通過查重的方式逐步插入將占用大量的時間消耗,其消耗的CPU的資源率相當高,甚至在此前測試時占據(jù)96%的采樣資源;
因此,這里我們從兩方面入手分析這一問題,如何構(gòu)造不重復的表達式,如何快速查詢表達式的重復性
?
??????? 如何構(gòu)造不重復的表達式
這里,我們采取子集生成的方式,對于隨機的表達式集合,我們只生成其中的一部分子集,這里對子集做出如下的定義和證明:
? 表達式的操作符數(shù)和數(shù)字數(shù)具備“數(shù)字數(shù) - 操作符數(shù)(不含括號) = 1”的數(shù)學關(guān)系,因此可將操作符隨機選取依次穿插在數(shù)字間,生成中綴表達式
? 表達式的數(shù)字必須呈遞減關(guān)系,且與非遞增關(guān)系不同,我們必須確保生成的表達式的相鄰三個數(shù)字不相同,從而保證表達式可以直接通過String.Equals()方法進行判斷
? 對于減法關(guān)系的生成,我們必須不妨定義相鄰符號組為“[—][+][+|—|×|÷]”或“[+][ —][+]”或“[—][+]”或“[+][ —]”或“[ —]”的組合
?
這里證明,對于交換性質(zhì)的運算符+和×,對于A≥B,則A[+|×]B = B[+|×]A,當且僅當A=B,在此基本定理的情況下,可以證明直接通過String.Equals()方法實現(xiàn)表達式的查重
?
這里放置兩張優(yōu)化圖,說明List<String>.Contains()和Hashtable.Contains()的優(yōu)化程度(getHashCode()方法),這里我們設(shè)置參數(shù)為“-r 1000 –n 100000”
?
?
?
未優(yōu)化前對List<String>.Contains()函數(shù)的觀察可以據(jù)此判斷
?
?
?
優(yōu)化后Hashtable.Contains()函數(shù)的觀察可以據(jù)此判斷
?
因此,實際上,Hashtable的優(yōu)化,基本可以使得查重的效率呈現(xiàn)數(shù)量級上的差異,同時由于任何運算過程中,包括Number的識別和轉(zhuǎn)換都需要調(diào)用正則表達式進行判斷,因此對于100,000道題目的生成,是相對可以容忍而若需要優(yōu)化,可能會涉及到代碼重構(gòu)的操作
?
0x05 :測試樣例與代碼分析
To the world,you maybe a person.
But to a person,you maybe the world.
?
這里測試樣例僅針對“-r -n”的類型操作進行說明(特別說明,若非從命令行中讀入,而是通過VS的調(diào)試窗口進行讀入,應屏蔽MyApp.exe的參數(shù),只敲入-r integer –n interger進行測試,通過cmd則不會講MyApp.exe讀為args[0])
?
CreateMaths.exe –r 1.3 –n 5.6
Print the IndexOutOfRangeException's Message As Followed :
[Message Start]
索引超出了數(shù)組界限。
[Message End]
Less Args is Invalid, Such Args Are Valid:
? Myapp.exe -r 10 -n 10
? Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt
Press Enter to Exit
?
CreateMaths.exe –r 10000 –n 100
Print the StackOverflowException's Message As Followed :
[Message Start]
沒有足夠的內(nèi)存繼續(xù)執(zhí)行程序。
[Message End]
Range parameter(-r) is too large
Press Enter to Exit
?
CreateMaths.exe –r 10000 –n 100
Print the StackOverflowException's Message As Followed :
[Message Start]
沒有足夠的內(nèi)存繼續(xù)執(zhí)行程序。
[Message End]
Range parameter(-r) is too large
Press Enter to Exit
?
CreateMaths.exe –r 5000 –n 100
argument's carried out successfully of -n -r
Press Enter to Exit
?
CreateMaths.exe –r 3 –n 10000
class CreatedList : NotSupportedException Happening!
Print the NotSupportedException's Message As Followed :
[Message Start]
不支持所指定的方法。
[Message End]
You May Well Input "-r 1 -n 10", Large but not Larger -r or -n is welcome
Invalid args Mainly Because number is out of the limition of range
Press Enter to Exit
?
CreateMaths.exe –r 100 –n 100000
argument's carried out successfully of -n -r
Press Enter to Exit
?
測試答案的測試用例由于文件較大,在此不再展示,圍繞文件讀取合法性、題目格式的正確性、答案格式的正確性、題目文件和答案文件是否匹配、答案正確的題目數(shù)量等方面設(shè)計測試用例即可
?
0x05 :測試樣例與代碼分析
To the world,you maybe a person.
But to a person,you maybe the world.
?
在代碼分析上,我們不妨采取設(shè)置參數(shù)為生成10000道范圍限制在100內(nèi)的四則運算表達式
?
?
?
?
顯然, Hashtable的優(yōu)化,基本可以使得查重的效率呈現(xiàn)數(shù)量級上的差異,同時由于任何運算過程中,包括Number的識別和轉(zhuǎn)換都需要調(diào)用正則表達式進行判斷,因此對于10,000道題目的生成,是相對可以容忍而若需要優(yōu)化,可能會涉及到代碼重構(gòu)的操作,因此其改進空間應只涉及重構(gòu)層次上的修改,在此次優(yōu)化過程中,可以判定為改進空間不大
?
0x06 :個人項目總結(jié)
To the world,you maybe a person.
But to a person,you maybe the world.
?
個人項目,實現(xiàn)和設(shè)計的差異性可能只有深入思考才會去探究清晰,工程項目不同于理論學習最大的特征在于測試的完全性和程序本身的魯棒性,可能時候面向?qū)ο蠼Un程的影響,在處理輸入的參數(shù)時總會考慮大量內(nèi)容,從而確保項目能夠在任何輸入的情況下均能完美給出相對的錯誤信息和輸出信息;
同時,自己在初期設(shè)計的時候沒有梳理清楚“表達式的生成規(guī)則”和“基礎(chǔ)的類的設(shè)計”,導致類之間的關(guān)聯(lián)與預期偏離,不同功能交叉在不同對象之間,極大增加了思維難度,從而導致后續(xù)的重構(gòu)消耗了大量的時間,可能軟件工程最大的目的,在于,用清晰的設(shè)計實現(xiàn)優(yōu)美的代碼,以上
?
Hola~BugPhobia With Pocket Panacea
轉(zhuǎn)載于:https://www.cnblogs.com/panacea/p/4831018.html
總結(jié)
以上是生活随笔為你收集整理的软件工程启程篇章:C#和四则运算生成与运算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UILabel自适应高、宽
- 下一篇: C# 之 获取文件名及拓展名