結對編程


1.編碼要求

(1)Fork github 項目https://github.com/Cherish599/WordCount到自己的倉庫,在Github倉庫中新建一個以一位同學的學號為名的文件夾,用於建立C#的項目和第二次作業類似。(結對的兩人中任意一人的學號都可以)。

(2)在開始實現程序之前,在PSP表格[附錄1]記錄下你估計在程序開發各個步驟上耗費的時間,在你實現程序之后,在PSP表格記錄下你在程序的各個模塊上實際花費的時間。

(3)使用C#語言實現,C#請使用Visual Studio Community 2017進行開發。

a)       制定編碼規范,可以參考C#語言的規范:簡版討論版。(鄒欣老師在講義“現代軟件工程講義 3 代碼規范與代碼復審”中所討論的有關代碼規范與代碼復審的內容。內容短小精煉,適合快速入門。)

b)     代碼自審並修正,每個人都獨立完成了自己的功能任務,對照編碼規范,審查修改自己的程序代碼並使其符合規范要求。

c)     代碼互審,按照共同制定的編碼規范,審查合作伙伴的代碼並記錄發現的問題。

d)     合並代碼,兩人協商,將兩部分代碼合並,形成初始版本。注意應設計合理的軟件結構及模塊划分。

e)     提交的代碼要求經過Code Quality Analysis工具的分析並消除所有的警告。

f)       完成項目的首個版本之后,請使用性能分析工具Studio Profiling Tools來找出代碼中的性能瓶頸並進行改進。

g)     使用Github[附錄2]來管理源代碼和測試用例,代碼有進展即簽入Github(至少三次)。簽入記錄不合理的項目會被助教抽查詢問項目細節。

h)     使用單元測試[附錄3]對項目進行測試,並使用插件查看測試分支覆蓋率等指標;並寫出至少10個測試用例確保你的程序能夠正確處理各種情況。

i)       在完成結對項目后,請按照預第二次作業的方式正確地發起一個Pull Request,並設置標題為本次統一使用的學號。

2.博客撰寫要求

(1)在文章開頭給出結對使用的Github項目地址和結對伙伴的作業地址。(兩個人使用同一個)注意:GitHub的地址必須是用於clone的地址即如下圖片中的地方獲取。(如果不是這個地址,助教就無法批量編譯運行你們的程序,出現問題的都會被助教抽中詢問詳情)

(2)描述結對的過程,提供非擺拍的兩人在討論的結對照片(一起工作編碼時的照片)。

(3)給出結對的PSP表格。

a)     解題思路描述。即剛開始拿到題目后,如何思考,如何找資料的過程。

b)     設計實現過程。設計包括代碼如何組織,比如會有幾個類,幾個函數,他們之間關系如何,關鍵函數是否需要畫出流程圖?單元測試是怎么設計的?

c)     給出你們制定的代碼規范或鏈接,記錄你們代碼互審的情況,審查的模塊名、發現的問題等。

d)     記錄在改進程序性能上所花費的時間,描述你改進的思路,並展示一張性能分析圖(由VS 2017的性能分析工具自動生成),並展示你程序中消耗最大的函數。

e)     代碼說明。展示出項目關鍵代碼,並解釋思路與注釋說明。

f)       結合在構建之法中學習到的相關內容與結對項目的實踐經歷,撰寫解決項目的心路歷程與收獲,以及結對感受,是否1+1>2。

注:兩人都要提交博客,結對共同部分,可在其中一個人的博客給出(另一個人給出鏈接),不同部分分別寫在自己的博客中

 

3.項目需求說明

實現一個命令行程序,不妨稱之為wordCount。

第一步、實現基本功能

輸入文件名以命令行參數傳入。例如我們在命令行窗口(cmd)中輸入:

wordCount.exe input.txt

則會統計input.txt中的以下幾個指標

  • 統計文件的字符數:
  • 只需要統計Ascii碼,漢字不需考慮
  • 空格,水平制表符,換行符,均算字符
  • 英文字母:A-Z,a-z
  • 字母數字符號:A-Z,a-z,0-9
  • 分割符:空格,非字母數字符號
  • 例:file123是一個單詞,123file不是一個單詞。file,File和FILE是同一個單詞
  • 輸出的單詞統一為小寫格式
  • 統計文件的單詞總數,單詞:至少以4個英文字母開頭,跟上字母數字符號,單詞以分隔符分割,不區分大小寫。
  • 統計文件的有效行數:任何包含非空白字符的行,都需要統計。
  • 統計文件中各單詞的出現次數,最終只輸出頻率最高的10個。頻率相同的單詞,優先輸出字典序靠前的單詞。
  • 按照字典序輸出到文件txt:例如,windows95,windows98和windows2000同時出現時,則先輸出windows2000
  • 輸出的格式為
·        characters: number
·        words: number
·        lines: number
·        <word1>: number
·        <word2>: number
·        ...
 

第二步、接口封裝

在寫了一些代碼開胃之后,大家都完成了一份滿足基本功能的代碼。
大家的代碼都各有特色,如果現在我們要把這個功能放到不同的環境中去(例如,命令行,Windows圖形界面程序,網頁程序,手機App),就會碰到困難:代碼散落在各個函數中,很難剝離出來作為一個獨立的模塊運行以滿足不同的需求。
同時我們也看到,不同的代碼解決不同層面的問題:

a)     有些是計算數據的(例如統計單詞)

b)     有些是控制輸入的(例如ReadLine,圖形界面的輸入字段)

c)     有些是數據可視化的(例如WriteLine)

d)     有些則更為特殊,是架構相關的(例如main函數,並不是所有的程序都需要某個特定格式的main)

這些代碼的種類不同,混雜在一起對於后期的維護擴展很不友好,所以它們的組織結構就需要精心的整理和優化。
我們希望把基本功能里的:

a)     統計字符數

b)     統計單詞數

c)     統計最多的10個單詞及其詞頻

這三個功能獨立出來,成為一個獨立的模塊(class library, DLL, 或其它),這樣的話,命令行和GUI的程序都能使用同一份代碼。為了方便起見,我們稱之為計算核心"Core模塊",這個模塊至少可以在幾個地方使用:

a)     命令行測試程序使用

b)     在單元測試框架下使用

c)     與數據可視化部分結合使用

把計算核心在單元測試框架中做過完備的測試后,我們就可以在算法層級保證了這個模塊的正確性。
但我們知道軟件並非只有計算核心,實際的軟件是交付給最終用戶的軟件,除了計算核心外,還需要有一定的界面和必要的輔助功能。
這個Core模塊和使用它的其他模塊之間則要通過一定的API來交流。
API應該怎么設計呢?
為了方便起見,我們可以從下面的最簡單的接口開始(僅舉例,你的代碼里可能沒有這個函數):

public int countChar(String path)

這個函數表示輸入path文件路徑字符串,返回這個文件的字符數。
假設我們的Core里封裝了這個接口,那么我們的測試程序可以是這樣:

 

String path = "input.txt";
 
int count = 100;
 
Assert(countChar(in) == count);

當然,這樣的測試程序並不充分,希望大家測試時不要像這樣偷懶。

第三步、增加新功能

在第三步中,我們希望各位在第一步的基礎上,添加一些新的功能:

a)     詞組統計:能統計文件夾中指定長度的詞組的詞頻

b)     自定義輸出:能輸出用戶指定的前n多的單詞與其數量

(1).-i 參數設定讀入的文件路徑

格式如下

wordCount.exe -i [file]

一個例子如:

wordCount.exe -i input.txt

(2).-m 參數設定統計的詞組長度

格式如下

wordCount.exe -m [number]

詞組定義:m個由分隔符隔開的單詞組成一個詞組
-m參數與數字配套使用,用於設置詞組長度
命令行中使用-m參數,例:

wordCount.exe -m 3 -i input.txt
/*
 *要求程序統計input.txt中長度為3的詞組,最終輸出
 *例:input文件中內容為"Monday Tuesday Wednesday Thursday"
 *則輸出如下
 */
characters: 33
words: 4
lines: 1
Monday Tuesday Wednesday: 1
Tuesday Wednesday Thursday: 1

(3)-n參數設定輸出的單詞數量

格式如下

wordCount.exe -n [number]

-n參數與數字搭配使用,用於限制最終輸出的單詞的個數
表示輸出最多的前[number]個單詞
命令行中使用-n參數,例:

wordCount.exe -n 1 -i input.txt
/*
 *程序會輸出文件中出現次數最多的那個單詞
 */

(4) -o 參數設定生成文件的存儲路徑

格式如下

wordCount.exe -o output.txt

則將統計信息輸出到文件 output.txt中。

(5) 多參數的混合使用

在實際測試時,-i 與 -o 參數一定會出現(但文件路徑不一定正確),但-n或-m 參數可能不出現,參數之間的順序並不固定,一個完整例子如下

wordCount.exe -i input.txt -m 5 -n 3 -o output.txt
 

第四步、附加功能

附加需求:用戶交互界面繪制(10')

現在已經有了一個詞頻統計程序的命令行版本,如果想讓大家都能實際使用它,還需要一個簡單的界面。請為你們的程序做一個GUI界面,並附上一個簡單的使用說明。界面需正確實現下述功能,會按點給分:

  1. 支持兩種導入單詞文本的方式:①導入單詞文本文件,②直接在界面上輸入單詞並提交(3')
  2. 提供可供用戶交互的按鈕和,實現-i -m -n -o 這四個參數的功能,對於異常情況需要給予用戶提示(3')
  3. 將結果直接輸出到界面上,並提供“導出”按鈕,將結果保存到用戶指定的位置(3')

以上功能全部正確完成,可以獲得10分滿分。

【注意】選擇完成本附加題目的同學,需要將GUI與單詞計算模塊作為兩個工程開發,后者可以作為依賴庫為前者提供調用接口,但不可以把兩個工程直接混在一起。 GUI相關的部分也需要提供新的可執行文件,放在根目錄的GUIBIN文件夾下。

 

第五步、錯誤處理並設計單元測試

現在我們封裝了接口,並增加了新功能,現在我們要對我們的代碼進行正確性驗證。
另一方面我們都知道健壯性對於軟件來說是非常必要的,請各位使用單元測試對項目進行測試,並使用插件查看測試分支覆蓋率等指標;另外,請准備至少10個測試用例確保你的程序能夠正確處理各種情況,並且不會崩潰。
對待錯誤的輸入,能夠盡可能精確報錯(就像編譯器一樣)。
你可以有“容錯性”的出錯設計,但必須輸出必要的提示或說明。

第六步、效能分析

現在我們已經有了一個基礎的詞頻統計軟件,如果它通過了足夠多的單元測試,那它可能也已經是一個比較完善的詞頻統計軟件了。但是一個軟件光正確了還不夠,還需要有一定的性能。
那么,如何讓軟件又快又好地執行呢?那就需要我們找到執行消耗時間最久的模塊,然后不斷地優化改進它。那么,如何知道哪些語句是軟件的時間瓶頸呢,這就需要用到效能分析。

以下鏈接中的Part6部分有效能分析的介紹

https://www.cnblogs.com/ChildishChange/p/10398212.html

4.評分細則

博客評分規則(總分100)

(1)          在文章開頭給出你們Fork倉庫的Github項目地址。(5')

(2)          在開始實現程序之前,在下述PSP表格記錄下你估計將在程序的各個模塊的開發上耗費的時間。(5')

(3)          計算模塊接口的設計與實現過程。 設計包括代碼如何組織,比如會有幾個類,幾個函數,他們之間關系如何,關鍵函數是否需要畫出流程圖?說明你的算法的關鍵(不必列出源代碼),以及獨到之處。並講講你的設計是如何體現“Design by Contract”、“Information Hiding”、 “Interface Design”、 “Loose Coupling”等原則的。(25')

(4)          代碼復審過程。代碼互審情況、發現的問題等。(10‘)

(5)          計算模塊接口部分的性能改進。 記錄在改進計算模塊性能上所花費的時間,描述你改進的思路,並展示一張性能分析圖(由VS 2017/JProfiler的性能分析工具自動生成),並展示你程序中消耗最大的函數。(10')

(6)          計算模塊部分單元測試展示。 展示出項目部分單元測試代碼,並說明測試的函數,構造測試數據的思路。並將單元測試得到的測試覆蓋率截圖,發表在博客中。(15')

(7)          計算模塊部分異常處理說明。 在博客中詳細介紹每種異常的設計目標。每種異常都要選擇一個單元測試樣例發布在博客中,並指明錯誤對應的場景。(10')

(8)          描述結對的過程,提供非擺拍的兩人在討論的結對照片。(5')

(9)          在你實現完程序之后,在附錄提供的PSP表格記錄下你在程序的各個模塊上實際花費的時間。(5')

(10)       附加功能(10') 

5.附錄

(1)PSP表格

PSP2.1

Personal Software Process Stages

預估耗時(分鍾)

實際耗時(分鍾)

Planning

計划

 

 

· Estimate

· 估計這個任務需要多少時間

 

 

Development

開發

 

 

· Analysis

· 需求分析 (包括學習新技術)

 

 

· Design Spec

· 生成設計文檔

 

 

· Design Review

· 設計復審 (和同事審核設計文檔)

 

 

· Coding Standard

· 代碼規范 (為目前的開發制定合適的規范)

 

 

· Design

· 具體設計

 

 

· Coding

· 具體編碼

 

 

· Code Review

· 代碼復審

 

 

· Test

· 測試(自我測試,修改代碼,提交修改)

 

 

Reporting

報告

 

 

· Test Report

· 測試報告

 

 

· Size Measurement

· 計算工作量

 

 

· Postmortem & Process Improvement Plan

· 事后總結, 並提出過程改進計划

 

 

 

合計

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PSP是卡耐基梅隆大學(CMU)的專家們針對軟件工程師所提出的一套模型:Personal Software Process (PSP, 個人開發流程,或稱個體軟件過程)。

一個功能完備的程序不是一蹴而就的。通過將詞頻統計的需求划分為4個部分,可將一個大任務划分為可操作的小任務,同時最好按照任務難度或緊急程度指定各個任務的完成次序。因此,在動手開發之前,要先估計將在程序各模塊開發所需耗費的時間,以及完成整個項目所需的時間,將這個[估計值]記錄下來,寫成PSP 的形式。
PSP的目的是:記錄工程師如何實現需求的效率,和我們使用項目管理工具(例如微軟的Project Professional,或者禪道等)進行項目進度規划類似。
有關PSP的更多內容,請自行閱讀鄒欣老師的博客:
http://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html

(2) Github

請閱讀鄒欣老師的博客:https://www.cnblogs.com/xinz/p/5044037.html  源代碼管理,了解源代碼管理的10個實踐問題。
本次作業要求使用Github進行源代碼管理,代碼有進展即簽入Github。簽入記錄不合理的項目會被助教抽查詢問項目細節。
對代碼簽入的具體要求如下:根據需求划分功能后,每做完一個功能,編譯成功后,應至少commit一次。本例中,至少應區分基本功能和擴展功能,即分別針對基本功能、擴展功能,編譯成功后,總共至少應commit兩次。具體的功能划分,請自行定義,並在撰寫博客時體現出來,遵循自己對需求的功能划分來提交代碼即可。
對Commit不是很熟悉的話,請閱讀阮一峰的博客:Commit message 和 Change log 編寫指南,了解更多細節。

(3)單元測試

請根據自己以往積累的測試經驗,在編碼完成之后,提交產品之前,設計測試用例,並編寫單元測試,對自己的項目進行測試。
首先,至少應采用白盒測試用例設計方法來設計測試用例,其他測試方法不限。其次,要設計至少10個測試用例,確保你的程序能夠正確處理各種情況。最后,結合測試評估的要求,對自己的測試設計進行評價,這些測試用例能滿足該程序測試的要求嗎?
另一個重要的措施是要把單元測試自動化,這樣每個人都能很容易地運行它,並且可以使單元測試每天都運行。每個人都可以隨時在自己的機器上運行。團隊一般是在每日構建中運行單元測試的,這樣每個單元測試的錯誤就能及時被發現並得到修改。
推薦閱讀鄒欣老師關於單元測試和回歸測試的博客:
http://www.cnblogs.com/xinz/archive/2011/11/20/2255830.html

6.提醒

(1)代碼不要出現抄襲或者直接拷貝的現象,一旦發現作業將沒有成績。

(2)確保代碼能夠運行通過,代碼不能通過,則博客成績最多給60分。

(3)博客要體現出自己的思想,每個人遇到的問題和解決方法以及感獲得的感受都應是不一樣的,博客出現抄襲或者拷貝現象,一旦發現作業將沒有成績。

7.參考

本作業參考北京航空航天大學發布的作業:結對編程 - 詞頻統計,在此表示感謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM