201971010229-劉轉弟 實驗三 軟體工程結對專案-《D{0-1}KP問題 例項資料集演算法實驗平臺》
專案 | 內容 |
---|---|
課程班級部落格連結 | 2019級卓越工程師班 |
這個作業要求連結 | 作業要求 |
我的課程學習目標 | 1.瞭解軟體工程過程中結對專案的開發流程
2.理解結對程式設計的重要性 3.提高個人編碼能力 |
這個作業在哪些方面幫助我實現學習目標 | 1.通過本次作業的具體流程,使得我瞭解到了軟體工程中結對任務的開發流程
2.填寫PSP表格 3.學習相關演算法及編碼 4.瞭解到結對程式設計中程式碼規範,程式碼複審的重要性 |
結對程式設計隊友 | 201971010222-李瑞婷 |
專案GitHub的倉庫連結地址 | 倉庫連結 |
1.實驗目的與要求
(1)體驗軟體專案開發中的兩人合作,練習結對程式設計(Pair programming)。
(2)掌握Github協作開發軟體的操作方法。
2.實驗內容與步驟
任務1:閱讀《現代軟體工程—構建之法》第3-4章內容,理解並掌握程式碼風格規範、程式碼設計規範、程式碼複審、結對程式設計概念
-
程式碼規範: 變數名等的規範,縮排格式的規範,函式介面的規範。 原則:程式碼簡單易懂,邏輯清晰 面向變化程式設計,而不是面向需求程式設計 。程式碼風格規範的原則是簡明、易讀、無二異性
-
程式碼複審: 程式碼審查,是有意識地、有系統地與其他程式設計師一起檢查彼此的程式碼是否有錯誤的行為。可以節省一些不必要的時間和資源,提高開發效率。
-
結對程式設計: 兩人合作工作與兩個人各自獨立工作相比,結對程式設計能編寫出質量更高的程式碼。在面對一個問題的時候,經過討論會得出一些更好的雙方都支援的解決方案,使問題能夠達到最優程度的解決。
任務2:兩兩自由結對,對結對方《實驗二 軟體工程個人專案》的專案成果進行評價
- 2.1 結對方的 github倉庫連結
- 2.2 點評結對方部落格
- 2.3 程式碼核查表
概要部分 | 程式碼符合需求和規格說明麼? | 程式碼符合要求 |
程式碼設計是否考慮周全? | 考慮周全 | |
程式碼可讀性如何? | 程式碼可讀性較強,有著比較好的可讀性。 | |
程式碼容易維護麼? | 容易維護 | |
程式碼的每一行都執行並檢查過了嗎? | 都可以執行 | |
設計規範部分 | 設計是否遵從已知的設計模式或專案中常用的模式? | 遵從 |
有沒有硬編碼或字串/數字等存在? | 沒有 | |
程式碼有沒有依賴於某一平臺,是否會影響將來的移植(如Win32到Win64)? | 沒有,不會影響移植,任何平臺都可以 | |
在本專案中是否存在類似的功能可以呼叫而不用全部重新實現? | 可以呼叫 | |
有沒有無用的程式碼可以清除? | 可以再簡潔一些 | |
程式碼規範部分 | 修改的部分符合程式碼標準和風格麼? | 按照程式碼標準修改的 |
具體程式碼部分 | 有沒有對錯誤進行處理?對於呼叫的外部函式,是否檢查了返回值或處理了異常? | 對錯誤都進行了處理 |
引數傳遞有無錯誤,字串的長度是位元組的長度還是字元的長度,是以0開始計數還是以1開始計數? | 不涉及字串 | |
邊界條件是如何處理的?switch語句的default分支是如何處理的?迴圈有沒有可能出現死迴圈? | switch語句的default分支返回false,沒有出現死迴圈 | |
對資源的利用是在哪裡申請,在哪裡釋放的?有沒有可能導致資源洩露? | 在對資料庫進行操作之前申請資料庫連線資源,操作完畢之後釋放申請的資源 | |
效能 | 程式碼的效能如何?最壞的情況如何? | 達到了具體任務的要求 |
程式碼中,特別是迴圈中是否有明顯可優化的部分 | 可優化 | |
對於系統和網路呼叫是否會超時?如何處理? | 目前沒有出現超時現象 | |
可讀性 | 程式碼可讀性如何?有沒有足夠的註釋? | 可以順利讀取、程式碼有足夠的註釋讓我們讀懂 |
可測試性 | 程式碼是否需要更新或建立新的單元測試? | 有創新點 |
fork操作記錄:
任務3:採用兩人結對程式設計方式,設計開發一款{0-1}KP 例項資料集演算法實驗平臺
- 3.1 需求分析
- 後臺要能夠從給定的檔案中讀取出正確的資料並儲存到資料庫
- java後端給前端傳遞正確的資料,前端根據後端傳的資料繪製散點圖
- java後端實現對自定義資料型別的列表的排序(實現Comparator介面),並向前端傳資料
- 實現java後臺解決D{0-1}揹包問題的動態規劃和回溯演算法
- 後臺將求解後的資料寫入檔案並儲存,前端展示檔案下載閱覽
- 後臺接收使用者傳送的演算法檔案並執行,將執行結果儲存到檔案然後返回前端
- 後臺編寫遺傳演算法求解D{0-1}KP
- 3.2 功能設計
- D{0-1}KP資料可以儲存到資料庫,也可以從資料庫中清除
- 平臺可繪製任意一組D{0-1}KP資料以重量為橫軸、價值為縱軸的資料散點圖
- 平臺可對任意一組D{0-1}KP資料按項集第三項的價值:重量比進行非遞增排序
- 在平臺上,使用者能夠自主選擇動態規劃演算法、回溯演算法求解指定D{0-1} KP資料的最優解和求解時間(以秒為單位)
- 在平臺上,任意一組D{0-1} KP資料的最優解、求解時間和解向量可儲存為txt檔案或匯出EXCEL檔案
- 平臺可動態嵌入任何一個有效的D{0-1}KP 例項求解演算法,並儲存演算法實驗日誌資料
- 平臺可使用遺傳演算法求解D{0-1}KP
- 3.3 設計實現
- D{0-1}KP資料可以儲存到資料庫,也可以從資料庫中清除
3.2.功能設計
- 基本功能:
(1)可正確讀入實驗資料檔案的有效D{0-1}KP資料;
(2)能夠繪製任意一組D{0-1}KP資料以重量為橫軸、價值為縱軸的資料散點圖;
(3)能夠對一組D{0-1}KP資料按項集第三項的價值:重量比進行非遞增排序;
(4)使用者能夠自主選擇動態規劃演算法、回溯演算法求解指定D{0-1} KP資料的最優解和求解時間(以秒為單位);
(5)任意一組D{0-1} KP資料的最優解、求解時間和解向量可儲存為txt檔案或匯出EXCEL檔案。
3.設計實現
(1)ReadTheFil類 :通過檔案路徑來建立檔案例項,把FileInputStream例項 傳遞到 BufferedInputStream,目的是能快速讀取檔案,最後,使用available檢查是不是讀到了檔案末尾。
(2)ScatterDiagram類 :建立二維陣列data儲存profit價值和height重量,以重量為橫軸、價值為縱軸,建立直角座標系畫出散點圖。
(3)WeightRatio類 :分別定義int型別陣列profit和weight陣列將價值和重量儲存,因為所給資料全部為int型,再定義比值ratio為double型別,再將其int型別陣列強制轉換為double進行比值運算,最後運用氣泡排序將比值進行降序排序。
(4)Time類 :使用動態規劃演算法:在0/1揹包問題中,物品i或者被裝入揹包,或者不被裝入揹包,設xi表示物品i裝入揹包的情況,則當xi=0時,表示物品i沒有被裝入揹包,xi=1時,表示物品i被裝入揹包。
4.測試執行
(1)讀入有效資料,如圖1
圖一
(2)繪製散點圖,如圖2:
圖2
(3)重量比排序,如圖3:
圖3
(4)計算最優解及求解時間,如圖4:
圖4
5.程式碼片段
(1)讀入實驗資料檔案的有效D{0-1}KP資料
//讀取txt檔案
File file = new File("E:\\測試資料\\beibao2.in");
BufferedInputStream bis = null;
FileInputStream fis= null;
try{
//第一步 通過檔案路徑來建立檔案例項
fis = new FileInputStream(file);
/*把FileInputStream例項 傳遞到 BufferedInputStream
目的是能快速讀取檔案
*/
bis = new BufferedInputStream(fis);
/*available檢查是不是讀到了檔案末尾 */
while( bis.available() > 0 ){
System.out.print((char)bis.read());
}
}catch(FileNotFoundException fnfe)
{
System.out.println("檔案不存在" + fnfe);
}
catch(IOException ioe)
{
System.out.println("I/O 錯誤: " + ioe);
}
(2)繪製散點圖
int h = getHeight();//重量
int w = getWidth(); //價值
// 橫座標
g2.draw(new Line2D.Double(PAD, w-PAD, h-PAD, w-PAD));
// 縱座標
g2.draw(new Line2D.Double(PAD, PAD, PAD, w-PAD));
double xInc = (double)(w - 2*PAD)/(data.length-1);
double scale = (double)(h - 2*PAD)/getMax();
// 資料點(座標)
g2.setPaint(Color.blue);//點的顏色
for(int i = 0; i < data.length; i++) {
double x = PAD + i*xInc;
double y = h - PAD - scale*data[i];
g2.fill(new Ellipse2D.Double(x-2, y-2, 4, 4));
(3)重量比排序:
//氣泡排序
double tmp;
for (int a= 1; a < ratio.length; a++) {
for (int j = 0; j < ratio.length-1; j++) {
if(ratio[j] < ratio[j+1]){
tmp = ratio[j];
ratio[j] = ratio[j+1];
ratio[j+1] = tmp;
}
}
(4)計算最優解及求解時間:
//1.建立二維陣列
//v[i][j]表示在前i個物品中能夠裝入容量為j的揹包中的最大價值
int[][] v=new int[n+1][m+1];
//存放記錄陣列
int[][] path=new int[n+1][m+1];
//2.初始化第一行第一列(已經處理了,因為預設是0)
//3.根據公式來動態規劃處理
for (int i = 1; i < v.length; i++) {
for (int j = 1; j < v[0].length; j++) {
//公式
if(w[i-1]>j){//因為我們程式i是從1開始的,因此原來的公式中的w[i]修改成w[i-1]
v[i][j]=v[i-1][j];
}else{
//v[i][j]=Math.max(v[i-1][j],val[i-1]+v[i-1][j-w[i-1]]);
if(v[i-1][j]<val[i-1]+v[i-1][j-w[i-1]]){
v[i][j]=val[i-1]+v[i-1][j-w[i-1]];
path[i][j]=1;
}else{
v[i][j]=v[i-1][j];
}
}
}
}
6.總結:
剛拿到題目時,真的感覺這次實驗非常難,而且還要使用GitHub建立倉庫來與Eclipse相連線,又為這個作業增添了不少難度,因為我本身動手能力就較弱。在本次實驗的具體實行過程中,我又熟悉重溫了一遍Eclipse整合開發環境的專案搭建與執行,這次實驗要求較多且很有難度,因為實驗要求需要將Eclipse中的程式碼傳到GitHub中,因此,必須要熟悉並掌握GitHub與Eclipse的連線,在連線的過程中遇到了很多困難,比如在最後一步時系統總是提示Eclipse無法連線github,嘗試了很多方法,雖然我沒有深刻理解這一步的作用,我新增好之後,系統還是提示不能連線,找了很多參考資料,在最後終於找到了一篇文章,解決了我很大一部分問題,這篇文章給了我很多的提示與幫助。
7.PSP展示
PSP | 任務內容 | 計劃共完成需要的時間(min) | 實際完成需要的時間(min) |
---|---|---|---|
Planning | 估計這個任務需要多少時間,並規劃大致工作步驟 | 15 | 10 |
Estimate | 估計這個任務需要多少時間,並規劃大致工作步驟 | 15 | 10 |
Development | 開發 | 840 | 940 |
Analysis | 需求分析 (包括學習新技術) | 30 | 25 |
Design Spec | 生成設計文件 | 20 | 30 |
Design Review | 設計複審 (和同事稽核設計文件) | 10 | 10 |
Coding Standard | 程式碼規範 (為目前的開發制定合適的規範) | 30 | 45 |
Design | 具體設計 | 60 | 65 |
Coding | 具體編碼 | 600 | 650 |
Code Review | 程式碼複審 | 30 | 60 |
Reporting | 報告 | 90 | 71 |
Test Report | 測試報告 | 50 | 25 |
Size Measuremen | 計算工作量 | 10 | 16 |
Test | 測試(自我測試,修改程式碼,提交修改) | 30 | 60 |
Postmortem & Process Improvement Plan | 事後總結 ,並提出過程改進計劃 | 30 | 30 |
已完成專案託管,如圖5