結對項目作業
項目 | 内容 |
---|---|
這個作業屬于哪個課程 | 2020春季計算機學院軟體工程(羅傑 任健) |
教學班級 | 005 |
項目位址 | Team Intersect |
PSP 表格記錄
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 15 | 20 |
· Estimate | · 估計這個任務需要多少時間 | 30 | |
Development | 開發 | - | |
· Analysis | · 需求分析 (包括學習新技術) | 60 | 120 |
· Design Spec | · 生成設計文檔 | 80 | |
· Design Review | · 設計複審 (和同僚稽核設計文檔) | 40 | |
· Coding Standard | · 代碼規範 (為目前的開發制定合适的規範) | ||
· Design | · 具體設計 | ||
· Coding | · 具體編碼 | 720 | 1200 |
· Code Review | · 代碼複審 | ||
· Test | · 測試(自我測試,修改代碼,送出修改) | ||
Reporting | 報告 | ||
· Test Report | · 測試報告 | ||
· Size Measurement | · 計算工作量 | ||
· Postmortem & Process Improvement Plan | · 事後總結, 并提出過程改進計劃 | ||
合計 | 1195 | 1920 |
花了很多時間學習QT,碰到了許多問題,由于代碼結構不好,寫的不規範,報了許多沒見過的錯誤,耗費了相當長的時間。
接口設計說明
由于我和隊友對C++的接口不是特别熟悉,是以這一次寫的代碼,展現的接口的概念不是特别清晰,也是以重複造了很多次輪子。其實在開始擴充代碼時,有過使用接口的想法,當時不知道這種想法是“接口”。比如對于新增的線段,射線,其實都是直線的一種,如果在寫直線類時留有一些接口,在實作另外的線的類時就會輕松一些,代碼内容也會緊湊一些;或者比如直線,線段,圓這些都屬于一個圖形類。大體思想應該是類似的,隻是這次做了很多重複工作,讓代碼看起來很臃腫。(頭檔案寫的也不是很規範,寫的有點像
.java
檔案)
另外,一開始寫的時候并沒有刻意去考慮使用接口,嘗試之後報了一些錯誤。于是為了防止一些不必要的麻煩,我們還是采取了一些簡單的做法,哪怕是複制粘貼,先保證能寫出正确的代碼。
由于對接口的認識不夠,是以就從三方面總結一下這次的不足和以後需要注意的點。
Information Hiding
- 設計不符合面向對象的規範,沒有将資料封裝好。每個類中的成員變量不應設定為public,沒有為其配備相應的get方法,盡管在使用時直接使用
或.
比較友善。但是就這一次而言,應該不算是大問題,如果工程更大的話,這種細節問題就必須引起重視。->
- 多層設計中的層與層之間加入接口層。
- 所有類與類之間都通過接口類通路。
Interface Design
- 沒有設計好接口層,代碼架構較差。
- 接口應該将内部實作細節封裝起來,外部使用者通過預留的接口可以使用接口的功能而不需要知曉内部具體細節。
- 可以采用純虛函數的方式來實作。這樣做的好處是能夠實作封裝和多态。
Loose Coupling
- 由于本身寫法就比較蠢,是以這次所寫的類與類之間的依賴性比較低。
- 對于底層函數,功能盡量單一,盡量避免修改底層函數。功能相近的函數,可以設計2個以上,不要為了減少代碼量,把一個函數的功能設計的太多。
這次作業沒有用好接口,以後要做出改進,讓代碼變得靈活。
計算子產品接口的設計與實作過程
起初的想法是,每種幾何對象都是一個類。是以會有圓,直線,射線,線段這四個類,并且有最基礎的類
Point
。由于上次已經完成了圓和直線類,是以這次首先考慮了射線,線段與直線的相似性,希望使用繼承等方法盡量簡化代碼,避免不必要的工作。對于射線和線段,其實和直線類似,算出結果後隻需要判斷一下該點是否在射線或線段上(是否符合條件)即可。對于新增的兩個類,應該有着與直線類同樣的求交點方法,同時在圓類裡配置求交點的方法,是以三種求交點函數就足夠,再根據具體情況寫一些判斷函數。
按照這種想法進行後,發現由于對C++還不是很熟悉,會犯許多錯誤,甚至不符合文法規範,最終還是決定先按照笨辦法完成代碼。
算法的關鍵之一是判斷所求出的點,是否确實在我們的幾何對象上,主要涉及線段和射線,這兩類線由于長度限制顯得比較特殊。另外就是三種求交點的方法。
獨到之處在于記錄了直線的斜率k和截距b,在後續操作中提供了很大的友善,并且求交點的方法是根據圖形及方程得到的公式,易于了解。
UML 圖顯示計算子產品部分各個實體之間的關系
使用VS自帶的類設計器畫出的UML圖如下:

沒有用到太複雜的關系,各個類比較獨立,函數重複性太強,值得反思。
計算子產品接口部分的性能改進
由于對于自己寫的hash沒有保證,是以沒有選擇将
set
改為
unordered_set
。
生成1000個随機的幾何對象,一次性能分析如下:
能夠看出來,消耗最大的還是
set
關于紅黑樹的建構,這是使用此容器難以避免的。
3000個随機幾何對象,得到239萬個交點,性能分析如下:
依然是紅黑樹的建構部分消耗最大。
看Design by Contract,Code Contract的内容,描述這些做法的優缺點,說明你是如何把它們融入結對作業中的。
契約式設計有三個關鍵詞,規定了各方的一種“責任”或是“義務”。
- 前置條件:為了調用函數,必須為真的條件,在其違反時,函數決不調用,傳遞好資料是調用者的責任。
- 後置條件:函數保證能做到的事情,函數完成時的狀态,函數有這一事實表示它會結束,不會無休止的循環。
- 類不變項:從調用者的角度來看,該條件總是為真,在函數的内部處理過程中,不變項可以為變,但在函數結束後,控制傳回調用者時,不變項必須為真。
它能夠:
- 幫助開發者獲得更優秀的設計,讓設計變得更加清楚,簡單,系統。
- 幫助開發者了解代碼,更好地測試代碼。
- 對開發者和調用者(使用者)負責,因為是一種強制的規定。
但是,它也有很多缺點,比如:
- 撰寫合格的契約(如JML)有一定難度,需要長時間的學習。
- 撰寫契約很耗費時間,而且可能比代碼還複雜。
- 過于複雜的契約可能對開發者沒有好處。
在本次作業中這種思想展現的不是太明顯,因為用到了許多容器,其實這些容器可能本身就是一種契約,規定某個容器隻存某種對象,在寫UI子產品時直接調用即可。
計算子產品部分單元測試展示
單元測試部分代碼如下:
構造測試資料時主要考慮了可能實作的10種情況,在每種相交或其他情況之中再考慮比較特殊的情況,如圓與圓内含,内切,外切;射線的端點在直線上;直線平行等。最後設定了同時存在四種幾何對象的情況,一共11個Test,每個Test之中再進行細分,同時根據測試覆寫率再修改一些測試資料。
單元測試運作如上,代碼覆寫率如下:
消除Code Quality Analysis中的所有警告
計算子產品部分異常處理說明
錯誤類型 | 描述 | 期望輸出 |
---|---|---|
輸入檔案輸入格式錯誤 | 包括幾何類型不存在,坐标出現字母,沒有給出N等情況。(支援坐标為小數,關于坐标必須是整數也沒有硬性規定) | WRONG FORMAT |
線類給定的兩點重合 | 确定線的兩個點相同,無法确定一條線。 | CANNOT SOLVE THE SAME POINTS |
無窮個交點 | 包括圓和圓重合,直線與直線重合,直線與射線重合,線段與線段的重合等情況。(準确來說也不是一種錯誤) | INFINITE INTERSECTANT POINTS |
圓的半徑小于0 | 顯而易見。 | RADIUS CANNOT BE LESS THAN ZERO |
指令行參數不正确 | 包括參數錯誤,缺少參數。 | COMMAND ERROR |
坐标超出範圍 | 坐标不在(-100000,100000)内 | COORDINATE EXCEEDS LIMIT |
一共定義了六種異常,針對某些異常會有提示資訊,一些測試樣例及輸出如下表:
測試樣例 | |
---|---|
L 0 0 1 1 R 0 2 4 8 | Please tell me how many figures do you want first And please ensure your input is a right number... |
2 R 0 2 HelloWorld 8 | If you want a line,plase input as: L x1 y1 x2 y2 If you want a circle,plase input as: C x y r And please ensure your input is a number... |
Z 0 2 2 8 | Sorry,we do not support this type yet... |
6 R 3 3 5 5 R 3 3 -9 -9 L 0 1 4 1 C 0 0 2 C 0 0 20 | Sorry,your input N is wrong... |
3 L 0 2 0 2 L 5 4 8 7 R 8 7 9 8 | |
L 1 0 2 0 R -8 0 0 0 | |
C 0 1 5 L 1 0 5 4 | |
1 C 0 0 -5 | |
更改指令行參數為: input.txt | |
L 1 2 3 4 S 2 3 4 100001 | Coordinate should be within -100000 and 100000 |
界面子產品的詳細設計過程
界面子產品與計算子產品的對接
之前完全沒有接觸過UI設計和子產品封裝,是以這兩部分完成的不盡人意,碰到了許多困難。總的來說就是有一些可行的想法,但對實作過程很不了解,在嘗試的過程中又出現了無數難以解決的問題。
首先在學習将寫好的cpp檔案及頭檔案封裝花費了大量的時間,不知道應該怎麼将函數或是接口導出到dll中。在網上學習後通過給函數聲明前加
_declspec(dllexport)
,成功生成了
.lib
及
.dll
檔案。但具體怎麼引用,引用之後如何使用都不太清楚。在原先的代碼中,幾何圖形都是用C++的STL容器存儲的,在引用dll的時候是否可以使用原先的容器?嘗試後發現并不可行,隻能對引用相應的接口函數,那麼能否通過接口将要添加的幾何圖形添加到之前的容器中?······說到底還是對編譯,連結的概念不夠清楚,才會問這種簡單的問題。
假設可以的話,我的想法就是通過接口将UI輸入的圖形添加到原先的容器中,最後調用
intersect()
方法傳回交點值,并且接口中應當有傳回交點容器及其他圖形容器的功能,進而在UI子產品進行繪制。但是這兩部分怎麼資料互通,現在也一頭霧水。
另外對于如何調用dll中的接口也不是很清楚,最後查到需要在聲明前加
_declspec(dllimport)
在封裝時,由于代碼本身寫的不規範,頭檔案中的函數全部都是定義而不是聲明,是以給後續發展帶來了許多問題。在QT中引用封裝好的dll和lib時,由于一些頭檔案的include會碰到各種奇妙的編譯錯誤,比如某個函數或是變量在
*.obj
中已經定義等重複定義問題,最後竟然報了800多個錯誤,實在是心有餘而力不足了。
對于Qt的學習,實際上增加一些按鈕函數不是很困難。但由于無法和計算子產品對接,這部分的實作也顯得很吃力,總是會報錯。
最終,UI界面隻有一個初步的設計架構。起初通過引用第三方的
qcustomplot
庫還可以通過VS編譯,畫出來的UI界面還有坐标顯示,但最後不知道動了哪裡,編譯也通不過了,而且VS和Qt似乎本身就有很多不太相容出錯的地方。
描述結對的過程
這兩部分過VS2019自帶的Live Share插件以及微信語音一起讨論并寫代碼。
由于Live Share插件過于不穩定,延遲非常高,是以有時一方修改代碼時另一方看不到,甚至會出行錯行等奇怪的錯誤。為了解決此問題,隻能将代碼發至微信後盡量隻由一個人修改。
結對程式設計評價
結對程式設計 | 我 | 隊友 | |
---|---|---|---|
優點 | 1.兩個人寫代碼速度更快,對問題的考慮也更全面; 2.互相監督,工作效率高,不容易摸; 3.對于互相學習很有利,能夠取長補短。 | 能夠耐心聽取隊友的意見,并給出一些意見;代碼書寫較規範,可讀性強。 | 對問題思考全面,交流積極,能夠很快指出我對問題思考的不足之處。 |
缺點 | 1.如果兩人有分歧或沖突,會對程式設計很不利; 2.可能會出現大佬歧視新手的情況; 3.适用範圍有限,如一些小型且簡單的程式設計。 | 對C++不夠熟悉,思考不全面,容易寫出bug。 | 也不熟悉C++,代碼風格需要改進。口齒不清頭發太長 |