1. 程式人生 > 其它 >201971010106-陳玉英 實驗三 結對專案—《{0-1}KP 例項資料集演算法實驗平臺》專案報告

201971010106-陳玉英 實驗三 結對專案—《{0-1}KP 例項資料集演算法實驗平臺》專案報告

專案 內容
課程班級部落格連結 2019級卓越工程師班
這個作業連結 實驗三 軟體工程結對專案
我的課程學習目標 (1) 掌握軟體專案個人開發流程,掌握Github釋出軟體專案的操作方法;(2)加深瞭解D{0-1}KP問題;(3)瞭解並熟悉遺傳演算法;(4)在結對合作過程中獲得除知識外其他能力。
這個作業在哪些方面幫助我實現學習目標 (1)通過軟體專案合作開發,體會到了結對程式設計的真正益處;(2)通過對不瞭解的知識內容進行學習,提升自己的程式設計能力的同時也對自我學習的要求有高層次要求。
結對方學號-姓名 201971010157-張穎
結對方本次部落格作業連結 201971010157-張穎 實驗三 結對專案—《{0-1}KP 例項資料集演算法實驗平臺》專案報告
本專案Github的倉庫連結地址 Github的倉庫
  • 任務一:閱讀《現代軟體工程—構建之法》第3-4章內容,理解並掌握程式碼風格規範、程式碼設計規範、程式碼複審、結對程式設計概念
  1. 程式碼風格規範:程式碼風格並不會影響程式的執行,但一段好的程式碼風格,能讓人閱讀起來特別舒服。在企業合作中程式碼格式規範是十分重要的。

  2. 程式碼設計規範:程式碼設計規範可以分為架構設計、類的設計、函式的設計、Log的設計以及競態關係的設計(多執行緒的設計)等等,通過這些設計,可以使程式碼更加規範,標準。

  3. 程式碼複審:程式碼審查是任何正式開發過程中的必要環節。但大多數開發者不知道的是,程式碼審查分為很多種型別。根據你專案和團隊架構的不同,每一種程式碼審查型別都有它特有的優缺點。我們可以在一個很高的層面可以將程式碼審查歸為兩大類:正式的程式碼審查(formal code review)和輕量級的程式碼審查(light weight code review)。

      * 正式的程式碼審查:正式的程式碼審查是基於正式的開發流程。其中最流行的實踐是範根檢查法(Fagan inspection)。它為試圖尋找程式碼的缺陷提供了一種非常結構化的流程,並且,它還可以用於發現規範(specifications)中的或者設計中的缺陷。範根檢查法由6個步驟組成:計劃(Planning),概述(Overview),準備(Preparation),召開檢查會議(Inspection Meeting),重做(Rework),和追查(Follow-up)。基本的思想是:預先制定好每一個步驟所需要達到的輸出要求。接下來,當進行到某個過程時,你檢查其現在的輸出,並與之前制定的理想輸出要求做比較。然後,你由此來決定,是否進入下一個步驟,或者仍需在當前步驟繼續工作。
      * 輕量級的程式碼審查:如今,輕量級的程式碼審查在開發團隊中很常用。可以將輕量級的程式碼審查細分為如下不同的子類
    

    程式碼複審的正確定義:看程式碼是否在“程式碼規範”的框架內正確地解決了問題

    名稱 形式 目的
    自我複審 自己 vs. 自己 用同伴複審的標準來要求自己。不一定最有效,因為開發者對自己總是過於自信。如果能持之以恆,則對個人有很大好處
    同伴複審 複審者 vs. 開發者 簡便易行
    團隊複審 團隊 vs. 開發者 有比較嚴格的規定和流程,用於關鍵的程式碼,以及複審後不再更新的程式碼。 覆蓋率高——有很多雙眼睛盯著程式。但是有可能效率不高(全體人員都要到會)
  4. 結對程式設計:結對程式設計(英語:Pair programming)是一種敏捷軟體開發的方法,兩個程式設計師在一個計算機上共同工作。一個人輸入程式碼,而另一個人審查他輸入的每一行程式碼。輸入程式碼的人稱作駕駛員,審查程式碼的人稱作觀察員(或導航員)。兩個程式設計師經常互換角色。在結對程式設計中,觀察員同時考慮工作的戰略性方向,提出改進的意見,或將來可能出現的問題以便處理。這樣使得駕駛者可以集中全部注意力在完成當前任務的“戰術”方面。觀察員當作安全網和指南。結對程式設計對開發程式有很多好處。比如增加紀律性,寫出更好的程式碼等。

  5. 程式碼風格規範包含縮排、行寬、括號、斷行與空白的{}行、分行、命名、下劃線、大小寫、註釋。

     * 縮排:如何縮排,縮排幾個空格?這些是需要統一的,一般用Tab鍵縮排4個空格。
     * 行寬:行寬必須限制,但是以前有些文件規定的80字元行寬太小了,現在時代不同了,可以限定為100字元。
     * 括號:在複雜的條件表示式中,用括號清楚地表示邏輯優先順序。
     * 程式的風格:最簡格式、斷行結構、用“{“和”}”來判斷程式的結構,改進的結構、“{”和“}”獨佔一行結構
     * 分行:不要把多條語句放在一行上,更嚴格地說,不要把多個變數定義在一行上,
     * 命名:變數命名一般要符合的規則是“看名知意”,也就是說看到這個變數的命名,就可以知道這個變數名是做什麼的。
     * 下劃線:下劃線用來分隔變數名字中的作用域標註和變數的語義,如:一個型別的成員變數通常用"m"表示,或者簡單地用一個下劃線“_”來做字首。移山公司規定下劃線一般不用在其他方面。
    
  6. 程式碼設計規範(不同的程式語言具有不同的設計規範,但是也有通用的原則。)

     * 函式:現代程式設計語言中的絕大部分功能,都在程式的函式( Function、Method )中實現。關於函式,最重要的原則是:只做一件事,並且要做好。
     * goto:函式最好有單一的出口,為了達到這一目的,可以使用goto。只要有助於程式邏輯的清晰體現,什麼方法都可以使用,包括 goto。
     * 錯誤處理:當程式的主要功能實現後,一些程式設計師會樂觀地估計只需要另外20%的時間,給程式碼加一些錯誤處理就大功告成了,但是這20%的工作往往需要全部專案80%的時間。
     * 引數處理
     * 斷言
    
  7. 兩人合作的不同階段和技巧:

     * 萌芽期間(Forming):這一階段由於兩人剛認識,有不同的期望值,彼此雙方並不瞭解,需要更多的磨合。
     * 磨合階段(Storing):剛開始合作時,總會出現這樣那樣的情況,但是隻有這樣才會加深彼此之間的認識。
     * 規範階段(Norming):在經過了磨合階段後,成員之間主鍵合拍,許多意見和建議取得一致,並且配合緊密。
     * 創造階段(Performing):在經過上述三個階段後,團隊成員之間可以達到合二為一的效果,但是並不是所有的合作都能達到這一階段,磨合太多後,可能進入“解體階段”。
     * 解體階段(Deforming):由於在“磨合階段”一方無法接受另一方,導致失敗,只能散夥或找其他合作伙伴。
                          在兩人合作期間,因為每個人都是一個獨立的個體,都有各自的意見和想法,那麼在兩個人平等合作的情況下,如何影響對方,如何說服對方。
    
  • 任務2:兩兩自由結對,對結對方《實驗二 軟體工程個人專案》的專案成果進行評價
    (1)對專案博文作業進行閱讀並進行評論:
    我的評論:

    (2)克隆結對方專案原始碼到本地機器,閱讀並測試執行程式碼

    專案 內容
    結對方連結 201971010157-張穎 實驗二 個人專案-《0-1揹包問題》專案報告
    結對方Github專案倉庫連結 GIthub專案倉庫

    以beibao0資料測試 ,結果如下:


    測試過程發現這個功能存在問題:任意一組{0-1} KP資料的最優解、求解時間和解向量可儲存為txt檔案或匯出EXCEL檔案,經過修改已經實現:

    (3)程式碼核查表:

    複審部分 提出問題 執行情況
    概要部分 1)程式碼符合需求和規格說明麼? 1)程式碼部分被分成了多個部分,功能較周全;
    2)程式碼設計是否考慮周全? 2)程式碼分模組完整
    3)程式碼可讀性如何? 3)可讀性較強
    4)程式碼容易維護麼? 易維護
    5)程式碼的每一行都執行並檢查過了嗎? 5)是
    設計規範部分 1)設計是否遵從已知的設計模式或專案中常用的模式? 1)設計較為遵從常用模式
    2)有沒有硬編碼或字串/數字等存在? 2)有字串和數字存在
    3)程式碼有沒有依賴於某一平臺,是否會影響將來的移植(如Win32到 Win64 ) ? 3)是
    4)開發者新寫的程式碼能否用已有的Library/SDK/Framework中的功能實現?在本專案中是否存在類似的功能可以呼叫而不用全部重新實現? 4)開發者新寫的程式碼無法用已有的Library/SDK/Framework中的功能實現
    5)有沒有無用的程式碼可以清除? 5)基本沒有無用程式碼
    程式碼規範部分 修改的部分符合程式碼標準和風格嗎? 修改的部分符合程式碼標準和風格
    具體程式碼部分 1)有沒有對錯誤進行處理?對於呼叫的外部函式,是否檢查了返回值或處理了異常? 1)開發者對錯誤進行了處理,並且處理錯誤之後還進行了分析
    2)引數傳遞有無錯誤,字串的長度是位元組的長度還是字元(可能是單/雙位元組)的長度,是以0開始計數還是以1開始計數? 2)字串的長度是以0開始計數
    3)邊界條件是如何處理的?switch語句的default分支是如何處理的?迴圈有沒有可能出現死迴圈? 缺少跳出迴圈部分,加入break已解決
    4)有沒有使用斷言(Assert)來保證我們認為不變的條件真的得到滿足?
    5)對資源的利用,是在哪裡申請,在哪裡釋放的?有無可能存在資源洩漏(記憶體、檔案、各種GUI資源、資料庫訪問的連線,等等)?有沒有優化的空間?
    6)資料結構中有沒有用不到的元素?
    效能 1)程式碼的效能( Performance )如何?最壞的情況是怎樣的? 程式碼最壞的情況是執行出錯,程式碼效能較好
    2)程式碼中,特別是迴圈中是否有明顯可優化的部分(C++中反覆建立類,C# 中 string的操作是否能用StringBuilder來優化)?
    3)對於系統和網路的呼叫是否會超時?如何處理? 2)對於系統和網路的呼叫可能會超時,因為在運用回溯演算法的時候耗時較長
    可讀性 程式碼可讀性如何?有沒有足夠的註釋? 可讀性較好,有足夠的註釋
    可測試性 程式碼是否需要更新或建立新的單元測試? 需要
  • 任務3:採用兩人結對程式設計方式,設計開發一款{0-1}KP 例項資料集演算法實驗平臺
    1.需求分析:目前,修改過的 {0-1}揹包問題已經實現了實驗二任務3(實驗二連結)的基本功能,但當{0-1}KP例項中各項的價值係數與重量係數在大範圍內取值時缺乏實用性,為解決這個問題此次專案提出了一種新的求解{0-1}KP的演算法,即遺傳演算法。並且在此基礎開發設計開發一款{0-1}KP 例項資料集演算法實驗平臺,來實現人機互動介面。

     * who 為誰設計,使用者是誰?
      揹包問題(Knapsack Problem,KP)是NP Complete問題,也是一個經典的組合優化問題,有著廣泛而重要的應用背景。對於有不同需求的使用者,可以自主選擇演算法求解問題或者進行不同的專案需求。
     * what 要解決什麼問題?
      資料選擇:可以選擇任意一組陣列;
      演算法選擇:使用者能夠自主選擇貪心演算法、動態規劃演算法、回溯演算法、遺傳演算法求解指定{0-1} KP資料的最優解和求解時間(以秒為單位),並儲存演算法實驗日誌資料;
      資料儲存:任意一組{0-1} KP資料的最優解、求解時間和解向量可儲存為txt檔案或匯出EXCEL檔案;
      散點圖繪製:能夠繪製任意一組{0-1}KP資料以價值重量為橫軸、價值為縱軸的資料散點圖;
      排序:能夠對一組{0-1}KP資料按重量比進行非遞增排序;
      資料庫儲存:{0-1}KP 例項資料集需儲存在資料庫;
      對以上功能放入實驗平臺,人機互動介面要是GUI介面。
    * why 為什麼解決這些問題?
      將零散的功能放在一個平臺,可以方便使用者體驗。
    
    1. 實驗平臺要求:(平臺基礎功能:實驗二 任務3實驗二連結
      (1){0-1}KP 例項資料集需儲存在資料庫;
      (2)平臺可動態嵌入任何一個有效的{0-1}KP 例項求解演算法,並儲存演算法實驗日誌資料;
      (3)人機互動介面要求為GUI介面(WEB頁面、APP頁面都可);
      (4)遺傳演算法求解{0-1}KP,並利用此演算法測試要求(2);
      3.{0-1}KP 例項資料集需儲存在資料庫
      利用MySQL軟體與Python資料庫連線,將實驗二的資料集中的一部分加入資料庫,如圖所示。

      資料庫連結程式碼:

      4.遺傳演算法求解{0-1}揹包問題:遺傳演算法可以認為是一種啟發式演算法,根據達爾文的進化學說中“優勝劣汰”、“適者生存”的觀點來解決一些實際生活中難以解決的問題。其實簡單來說,遺傳演算法所做的事情就是“隨機”生成一些可行解(不是最優解),然後隨機一段時間之後找到區域性最優解。但是這個“隨機”的過程模擬了自然界中的進化規律,也是“更優解”更容易生存,“更優解”與“更優解”的結合能夠生成“更更優解”。不斷重複這個結合的過程,最終可以得到區域性最優解,甚至可能是全域性最優解。
      參考於讀懂遺傳演算法原理如何讀懂遺傳演算法
    種群函式
    交配函式
    交叉函式
    變異函式
    選擇函式

    用beibao3資料作為測試:
    演算法總結:在測試過程中,我發現事實上遺傳演算法並沒有那麼容易實現。就算是對於有唯一解的基礎揹包問題,也很難保證有正確解。仔細回顧演算法的設計其實很容易發現問題的。
    在最開始構造基礎population的時候已經不簡單了,特別是對於有很多資料的情況,你甚至很難可以隨機構造一種情況使得可以滿足給定揹包重量大小的條件。於是就變成了在一堆不怎麼好的sample中,期望通過crossover構造一個較好的sample。這其實是非常不容易的。
    但我其實覺得,這個演算法是可行的,但可能需要比較長的時間。我通過增加mutation的概率來使得一些特別的sample能夠保留下來,並且能夠繁衍。而且我覺得只要進過一段時間後,就可以得到相當不錯的結果。
    但是正如前文所說的,遺傳演算法不是用於求解全域性最優解的(雖然如果有全域性最優解的話,一般都能夠達到),而且用於求解區域性最優解的,所以我們可以認為遺傳演算法得出的結果是“足夠好的”,事實上,也確實是如此。

  1. GUI介面設計(利用python自帶框架tkinter繪製GUI介面)
    GUI介面設計分為五步:


    實現介面如下:

6.結對PSP展示:

任務內容 計劃共完成需要的時間(h) 實際完成需要的時間(h)
計劃 1 0.8
估計這個任務需要多少時間,並規劃大致工作步驟 1 0.8
開發 34.5 43
需求分析 (包括學習新技術) 3 2
生成設計文件 2 2
生成設計文件 0.5 0.5
程式碼規範 (為目前的開發制定合適的規範) 1 0.5
具體設計 3 3
具體編碼 20 30
程式碼複審 3 2
測試(自我測試,修改程式碼,提交修改) 2 3
報告 3 5
測試報告 2 3
計算工作量 0.5 1
事後總結 ,並提出過程改進計劃 0.5 1

7.總結:這次專案的完成,我深深體驗到了兩人合作帶來1+1>2的效果,合作最大的好處就是能夠取長補短,克服個人能力的不足,一個人的想法有限,兩個人的合作,讓思維擴充套件,當一個人的思維受限時,同伴的思維是活躍的,並且可以想到自己想不到的地方。兩個人的分工可以讓一個專案所花費的時間大大縮短,交流可以讓思想融合,可以來說是事半功倍。
其次,這次的專案很多知識是我們不瞭解的,我們通過查閱資料,相互合作,一點點的啃下來,過程辛苦,結果值得。
8.結對過程記錄: