天天看點

結對第二次—文獻摘要熱詞統計及進階需求

所屬課程 軟體工程1916|W(福州大學)
作業要求 結對第二次—文獻摘要熱詞統計及進階需求
結對學号 221600327、221600329
基本需求Github項目位址 PairProject1-Java
進階需求Github項目位址 PairProject2-Java
作業目标 運用結對程式設計完成作業,增強團隊協作能力
參考文獻 《建構之法》、《資料結構與算法分析 Java語言描述》

PSP表格:

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 20 30
• Estimate • 估計這個任務需要多少時間
Development 開發 1060 1290
• Analysis • 需求分析 (包括學習新技術) 60 120
• Design Spec • 生成設計文檔 10
• Design Review • 設計複審
• Coding Standard • 代碼規範 (為目前的開發制定合适的規範)
• Design • 具體設計 40
• Coding • 具體編碼 800 960
• Code Review • 代碼複審
• Test • 測試(自我測試,修改代碼,送出修改)
Reporting 報告 80
• Test Report • 測試報告
• Size Measurement • 計算工作量
• Postmortem & Process Improvement Plan • 事後總結, 并提出過程改進計劃
合計 1160 1440

目錄

  • 1.WordCount基本需求
    • 1.1、PSP表格
    • 1.2、需求分析
    • 1.3、解題思路
    • 1.4、設計過程
    • 1.5、性能分析
  • 2.WordCount進階需求
    • 2.1、PSP表格
    • 2.2、需求分析
    • 2.3、解題思路
    • 2.4、設計過程
    • 2.5、性能分析及改進
    • 2.6、單元測試
  • 3.其他
    • 3.1、代碼規範
    • 3.2、分工情況
    • 3.3、Github的代碼簽入記錄
    • 3.4、遇到的代碼子產品異常或結對困難及解決方法
    • 3.5、評價隊友
    • 3.6、感想
    • 3.7、學習進度

任務1、WordCount基本需求

(一)成品:wordCount的指令行程式

(二)功能性需求:統計input.txt中的以下幾個名額

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

characters: number

words: number

lines: number

: number

...

(三)非功能性需求

1.接口封裝

  • 統計字元數 ;
  • 統計單詞數 ;
  • 統計最多的10個單詞及其詞頻 ;

1.3.1統計字元數:

我了解的input.txt的内容應該是,檔案中隻包含ascii碼以及空格,水準制表符,換行符這些字元。是以想直接用String存儲檔案内容,用String.length()來得到字元數。但是這個會有一個問題,就是在windows平台下,換行符是用"\r\n",String.length()會統計為兩個字元,用“\n”代替“\r\n”,即可解決問題。

1.3.2統計單詞數:

檔案由兩種字元分割符(空格,非字母數字元号)和非分隔符構成,單詞統計與非分割符無關,是以直接為了接下來split友善,将所有的分割符都替換為“|”,第二步分割字元串,第三步,使用正規表達式比對題目所規定的單詞,統計單詞數。

1.3.3統計有效行數:

一開始我想的統計行數是使用readline();去讀出每一行,然後逐行判斷這行有沒有ascii碼值<32的字元存在,因為ascii碼值小于32的是在文本中不顯示的,是以我開始的想法就是這樣的;不過試了一下之後發現對于"\r\n"之類的字元和空白行單靠ascii碼是區分不出來的,然後在網上找了資料之後,發現String.trim().isEmpty()是可以去除空白行然後統計的,最後使用的是這個方法。

1.3.4統計各單詞的出現次數,輸出頻率Top10的單詞:

因為處理場景為單機,是以決定選用散清單,順序掃描剛剛的到的單詞數組,當掃描到某個關鍵詞時,就去散清單裡查詢。如果存在,就将對應的次數加一;如果不存在,就将他插入到散清單,并記錄為1,以此類推,周遊完後,散清單中就存儲了不重複的單詞以及其出現的次數。

然後就是求Top10,建立一個大小為10的小頂堆,周遊散清單,依次取出每個單詞及對應出現的次數,然後與堆頂的單詞比較。如果出現次數比堆頂單詞的次數多,就删除堆頂單詞,将這個次數更多的關鍵詞加入到堆中,以此類推,周遊完散清單,堆中的單詞就是出現次數top10的單詞。然後排序輸出。

1.4.1代碼組織&接口設計:

  • bean包:Word類
  • unitl包:BasicWordCount類、IOUnitls類
    • BasicWordCount類:
      • 統計字元數函數 :
        /**
        * 計算檔案字元數
        * @param fileName 檔案名
        * @return long 字元數
        */
        public long characterCount(String fileName){}
                   
      • 統計行數 :
        /**
        * 計算檔案行數
        * @param fileName 檔案名
        * @return long 行數
        */
        public long lineCount(String fileName){}
                   
      • 統計單詞數 :
        /**
        * 計算檔案單詞數
        * @param fileName 檔案名
        * @return long 單詞數
        */
        public long wordCount(String fileName){}
                   
      • 統計詞頻top10的10個單詞及其詞頻 :
        /**
        * 計算出現次數top10的單詞及其詞頻
        * @param fileName 檔案名
        * @return Word[] 單詞數組
        */
        public Word[] topTenWord(String fileName) {}
                   
    • IOUnitls類:
      • 讀檔案
        /**
        * 讀入指定檔案名的檔案資料
        * @param fileName 檔案名
        * @return BufferedReader
        * @throws IOException 
        */
        public static BufferedReader readFile(String fileName){}
                   
      • 寫檔案
        /**
        	 * 将制定字元串輸出到result.txt
        	 * @param fileContent 字元串
        	 */
        	public static void writeFile(String fileContent, String fileName) {}
                   

1.4.2關鍵代碼及其流程圖(詞頻Top10單詞統計):

解題思路

流程圖:

結對第二次—文獻摘要熱詞統計及進階需求

代碼:

//進行統計的散清單
public Word[] topTenWord(String fileName) {
    ...//省略讀取檔案、将文本處理成單詞數組的過程
    	Map<String, Integer> countMap = new HashMap<>();
    	for(int i = 0; i < splitStrings.length; i++) {
    		if(Pattern.matches(regex, splitStrings[i])) {
    			Integer outValue = countMap.get(splitStrings[i]);
    			if (null == outValue) {
    			      outValue = 0;
    			}
    			outValue++;
    			countMap.put(splitStrings[i], outValue);
    		}
    	}
    	//求top10
    	PriorityQueue<Word> topN = new PriorityQueue<>(10, comp);
        Iterator<Map.Entry<String, Integer>> iter = countMap.entrySet().iterator();
        Map.Entry<String, Integer> entry;
        while (iter.hasNext()) {
          entry = iter.next();
          if (topN.size() < 10) {
            topN.offer(new Word(entry.getKey(), entry.getValue()));
          } else {
            // 如果目前資料比小頂堆的隊頭大,則加入,否則丢棄
            if (topN.peek().getCountNum() < entry.getValue()) {
              topN.poll();
              topN.offer(new Word(entry.getKey(), entry.getValue()));
            }
          }
        }
        //結果集
        Word[] result = null;
        int wordCount = countMap.size();
        if(wordCount < 10) {
        	result = new Word[(int) wordCount];
        }else {
        	result = new Word[10];
        }
        topN.toArray(result);
        //對top10單詞排序
        Arrays.sort(result, comp);
    	return result;
}
           

複雜度分析:周遊散清單需要 O(n) 的時間複雜度,一次堆化操作需要 O(logK) 的時間複雜度,是以最壞情況下,n個元素都入堆一次,是以最壞情況下,求TopK的時間複雜度是O(nlogk)。

從CPU Call Tree圖可以看出,耗時主要是在對字元串的分割和單詞的正則比對。

結對第二次—文獻摘要熱詞統計及進階需求
結對第二次—文獻摘要熱詞統計及進階需求

任務2、WordCount進階需求

2.2.1 成品:

①程式一:爬取CVPR2018論文到本地result.txt的指令行程式

②程式二:支援指令行參數的wordCount指令行程式

2.2.2功能性需求

(1)使用工具爬取論文資訊**輸出到result.txt檔案
(2)自定義輸入輸出檔案**
        WordCount.exe -i [file] -o [file]
(3)加入權重的詞頻統計**
         WordCount.exe -w [0|1]
(4)新增詞組詞頻統計功能**
        WordCount.exe -m [number]
(5)自定義詞頻統計輸出**
        WordCount.exe -n [number]
(6)多參數的混合使用**
        WordCount.exe -i input.txt -m 3 -n 3 -w 1 -o output.txt
           

2.3.1 爬取CVPR論文資料

要從網頁上爬取資料,就得分析網頁HTML源代碼構成,從CVPR2018首頁的HTML代碼可以看出,在首頁的論文清單中,每一篇的論文标題在HTML代碼上展現為如下形式:

<dt class="ptitle"><a href="xxx.html">論文标題</a></dt>

           

其中

<a></a>

标簽裡的href屬性為論文詳情頁的網頁位址。

由此我們可以擷取每篇論文詳情頁的url:

第一步就是在網頁的DOM樹中提取所有的<dt class="ptitle">的節點。
第二步從每個<dt class="ptitle">的節點中提取出<a>标簽的href屬性。

           

接着分析論文詳情頁的HTML代碼,

我們可以發現,在詳情頁源代碼中,論文标題的html代碼長這個樣子:

<div id="papertitle">論文标題</div>

           

論文摘要的html代碼長這個樣子:

<div id="abstract">這是論文摘要</div>

           

由此我們可以擷取每篇論文的标題和摘要:

第一步從網頁的DOM樹中找到<div id="papertitle">的節點,擷取他的文本即為paper title。
第二步從網頁的DOM樹中找到<div id="abstract">的節點,擷取他的文本即為paper abstract。

           

2.3.2 自定義參數

自定義參數的實作是先設計一個CommandLine類,把作業中的參數作為類的私有成員,然後從String []args中讀取指令行參數,存進CommandLine類中,再使用getxxxx()公有函數取出相應的參數就可以使用自定義參數了。

2.3.3 加入權重的詞頻統計:

從爬取的論文資料可知,title獨占一行,abstract獨占一行,是以可以按行處理資料。如果-w 參數為1,修改基本需求的檔案,當一行的開頭是title:,那麼這一行的單詞的權重為10。其他的一律權重為1。

2.3.4 詞組詞頻統計:

因為詞組不能跨越Title、Abstract,而且需求給定Title和Abstract都是獨占一行的,是以按行讀取。

然後構造一個隊列,對讀取的一行開始掃描,接下來的判斷邏輯如下圖:

結對第二次—文獻摘要熱詞統計及進階需求

掃描完後,對獲得的散清單進行topK操作,即可。

2.3.4 自定義詞頻統計

這個很簡單,基本需求規定的是top10,而這裡我們隻要從參數擷取topK的值,傳入參數,周遊單詞清單,然後維護一個大小為K的小頂堆即可。

2.4.1 代碼組織和接口設計

  • bean包:Word類、CommandLine類
  • unitl包:AdvancedWordCount類、Command類、IOUnitls類
    • AdvancedWordCount類:
      • 統計字元數函數 : 同基本需求
      • 統計行數 : 同基本需求
      • 統計單詞數 : 同基本需求
      • 統計單詞詞頻topK的K個單詞及其詞頻 :
        /**
        * 計算單詞的(權重)詞頻和topK
        * @param fileName 檔案名
        * @param topK 詞頻前K的單詞
        * @param isWeight 是否啟用權重計算
        * @return Word[] 有序單詞數組
        */
        public Word[] topKWordWeighting (String fileName, int topK, boolean isWeight) {}
        
                   
      • 統計詞組詞頻topK的K個詞組及其詞頻 :
      /**
        * 計算詞組的(權重)詞頻和topK
        * @param fileName 檔案名
        * @param groupNum 幾個單詞為一個組
        * @param topK 詞頻前K的詞組
        * @param isWeight 是否啟用權重計算
        * @return Word[] 有序單詞數組
        */
        public Word[] topKWordsWeighting (String fileName, int groupNum,int topK, boolean isWeight) {}
      
                 
    • Command類:
      • /**
        * 解析指令行參數
        * @param args 參數
        * @return CommandLine對象
        */
        public CommandLine ParseCommand(String[] args) {}
        
                   
    • IOUnitls類(同基本需求)

2.4.2 關鍵代碼(詞組詞頻統計之詞組劃分):解題思路

...
			//進行統計的散清單
			Map<String, Integer> countMap = new HashMap<>();
			while((line = bufferedReader.readLine()) != null) {
				String regexTile = "Title: .*";
				int weight = 1;
				if(Pattern.matches(regexTile, line)) {
					line = line.replaceAll("Title: ", "");
					weight = 10;
				}else {
					line = line.replaceAll("Abstract: ", "");
					weight = 1;
				}
				line = line.toLowerCase();
				//按字元分析
				int groupnumber = 0;//詞組單詞個數
				int wordStratPosition = 0;//單詞開始下标
				int wordEndPosition = 0;//單詞開始下标
				int flagPosition = 0;//标記詞組第一個單詞的結束位置
				Queue<String> wordReadyQueue = new LinkedList<String>();
				for(int i = 0; i < line.length()-3;) {
					boolean flag = false;
					
					if(Character.isLetter(line.charAt(i))) {
						if(Character.isLetter(line.charAt(i+1))) {
							if(Character.isLetter(line.charAt(i+2))) {
								if(Character.isLetter(line.charAt(i+3))) {
									wordStratPosition = i;
									for(int j=i+4; j < line.length(); ++j) {
										if(!Character.isLetterOrDigit(line.charAt(j))) {
											wordEndPosition = j;
											//得到一個單詞,加入到隊列
											wordReadyQueue.add(line.substring(wordStratPosition, wordEndPosition));										
											groupnumber++;//詞組單詞數+1
											if(groupnumber == 1) {
												flagPosition = j;
											}
											i=j;
											flag = true;
											break;
										}else if((j+1)==line.length()) {
											wordEndPosition = j+1;
											//得到一個單詞,加入到隊列
											wordReadyQueue.add(line.substring(wordStratPosition));
											groupnumber++;//詞組單詞數+1
											if(groupnumber == 1) {
												flagPosition = j;
											}
											i=j;
											flag = true;
											break;
										}
									}
								}else {
									if(!Character.isLetterOrDigit(line.charAt(i))) {
										wordReadyQueue.add(line.charAt(i)+"");
									}else {
										while(wordReadyQueue.poll()!=null) {}//清空隊列

										while(Character.isLetterOrDigit(line.charAt(i++))) {
											if(i >= line.length()){
												break;
											}
										}
										groupnumber = 0;
										flag = true;
									}
								}
							}else {
								if(!Character.isLetterOrDigit(line.charAt(i))) {
									wordReadyQueue.add(line.charAt(i)+"");
								}else {
									while(wordReadyQueue.poll()!=null) {}//清空隊列

									while(Character.isLetterOrDigit(line.charAt(i++))) {
										if(i >= line.length()){
											break;
										}
									}
									groupnumber = 0;
									flag = true;
								}
							}
						}else {
							if(!Character.isLetterOrDigit(line.charAt(i))) {
								wordReadyQueue.add(line.charAt(i)+"");
							}else {
								while(wordReadyQueue.poll()!=null) {}//清空隊列

								while(Character.isLetterOrDigit(line.charAt(i++))) {
									if(i >= line.length()){
										break;
									}
								}
								groupnumber = 0;
								flag = true;
							}
	
						}
					}else {
						if(!Character.isLetterOrDigit(line.charAt(i))) {
							if(groupnumber!=0) {
								wordReadyQueue.add(line.charAt(i)+"");
							}
						}else {
							while(wordReadyQueue.poll()!=null) {}//清空隊列
							while(Character.isLetterOrDigit(line.charAt(i++))) {
								if(i >= line.length()){
									break;
								}
							}
							groupnumber = 0;
							flag = true;
						}
					}
					if(groupnumber == groupNum) {//達到要求個數,加入散清單
						String wordGroup = "";
						String wordOfQueue = wordReadyQueue.poll();
						while(wordOfQueue != null) {
							wordGroup = wordGroup + wordOfQueue;
							wordOfQueue = wordReadyQueue.poll();
						}
						groupnumber = 0;
                        //權重
						Integer outValue = countMap.get(wordGroup.toString());
						if (null == outValue) {
						      outValue = 0;
						}
						if(isWeight) {
							outValue += weight;
						}else {
							outValue++;
						}
						countMap.put(wordGroup.toString(), outValue);		
						i = flagPosition;
					}
					if(!flag) {
						++i;
					}
				}
			}
			...

           

2.4.3 關鍵代碼(爬取論文标題和摘要):解題思路

因為之前寫安卓應用曾經使用者jsoup抓取教務系統上的成績等資料,這次自然而然使用了jsoup來對論文進行爬取。代碼如下:

/**
		 * 從cvpr網站爬取論文資料,并寫入result.txt
		 * @param URL
		 */
	    public static void getFile(String URL) {
	    	BufferedWriter bufferedWriter = null;
	        try {
	            File outputFile = new File("result.txt");
	            bufferedWriter = new BufferedWriter(new FileWriter(outputFile));
	            //get方式得到HTML資料
	            //預設設定下,jsoup逾時時間為3秒,鑒于目前網絡環境,修改為10秒
	            //預設設定下,jsoup最大擷取的長度隻有1024K,設定maxBodySize(0),可不限長度
	            Document doc = Jsoup.connect(URL).timeout(10000).maxBodySize(0).get();
	            //從HTML中選擇所有class=ptitle的節點
	            Elements paperList = doc.select("[class=ptitle]");
	            //從ptitle節點中選擇a标簽的href屬性值
	            Elements links = paperList.select("a[href]");
	            int count = 0;
	            //分别當問每篇論文的詳情頁
	            for (Element link : links) {
	                //論文詳情頁URL
	                String url = link.attr("abs:href");
	                Document paperDoc = Jsoup.connect(url).timeout(10000).maxBodySize(0).get();
	                //擷取論文title
	                Elements paperTitle = paperDoc.select("[id=papertitle]");
	                String title = paperTitle.text();
	                //擷取論文Abstract
	                Elements paperAbstract = paperDoc.select("[id=abstract]");
	                String abstracts = paperAbstract.text();
	                //資料寫入檔案
	                bufferedWriter.write(count++ + "\r\n");
	                bufferedWriter.write("Title: " + title + "\r\n");
	                bufferedWriter.write("Abstract: " + abstracts + "\r\n\r\n\r\n");
	            }
	        } catch (Exception e) {
	        	System.out.println("擷取論文資料失敗");
	            e.printStackTrace();
	        }finally {
	        	try {
				if(bufferedWriter != null) {
					bufferedWriter.close();
				}
	        	}catch (Exception e) {
		        	System.out.println("擷取論文資料失敗");
					e.printStackTrace();
				}
			}
	    }

           

2.5.1、性能分析

考慮到進階的資料量可能比較大,在壓力測試時,我們用了近60M的txt(近6000萬的字元)檔案進行測試。記憶體占用在1G左右,由于複用基本需求的接口,在性能測試時,依然是對字元串的分割(split)耗時最多占用記憶體很大,原因是因為原來的代碼是把這6000萬字元存放到字元數組裡,在進行合法單詞的判斷。

2.5.2、改進方法

在統計單詞時,直接周遊一遍文本資料,識别單詞的start和end的下标,直接截取單詞進行識别。代碼如下:

for(int i = 0; i<updateString.length();) {
		startPosition = i;
		endPosition = i;
		while(Character.isLetterOrDigit(updateString.charAt(i++))) {
			endPosition++;
		}
		if(Pattern.matches(regex, updateString.substring(startPosition, endPosition))) {
			countOfWord++;
		}
	}

           

我們用的是Eclipse中的JUnit4進行的測試,我們總共設計了16個測試單元,其中字元計數,詞計數,行計數各三個,進階單詞和詞頻各兩個。測試用例都是根據作業要求設計的各種字元混雜,有空白行,數字字母混雜的形式進行測試,測試結果都顯示我們的程式滿足了題目的要求。

單元測試 測試覆寫 測試代碼塊 測試個數
BasicWordCountTest.testCharacterCount() 普通字元、空格、各種符号 BasicWordCountTest.CharacterCount() 3
BasicWordCountTest.testWordCount() 普通字元、空格、各種符号,字母大小寫,數字與字母各種組合 BasicWordCountTest.WordCount()
BasicWordCountTest.testLineCount() 空白行、非空白行 BasicWordCountTest.LineCount()
BasicWordCountTest.testTopTenWord() BasicWordCountTest.TopTenWord()
AdvancedWord.TesttopWordWeighting() 混合單詞 AdvancedWord.topWordWeighting() 2
AdvancedWord.TesttopWordsWeighting() 混合詞組 AdvancedWord.topWordsWeighting()

部分測試代碼

package Untils;

import static org.junit.Assert.*;

import org.junit.Test;

public class BasicWordCountTest {
	public static BasicWordCount basic=new BasicWordCount();
	static String fileName="testinput2.txt";
	String []testTopWord= {"abcd123","here","your","aaaa","abss","bbbb","cccc","ddda","dera","esds"};
	int []testTopWordCount= {7,2,2,1,1,1,1,1,1,1};
	@Test
    //測試字元統計
	public void testCharacterCount() {
		System.out.println(basic.characterCount(fileName));
		assertEquals(189,basic.characterCount(fileName));
	}
	//測試單詞統計
	@Test
	public void testWordCount() {
		basic.wordCount(fileName);
		assertEquals(21,basic.wordCount(fileName));
	}

	@Test
	//測試top10單詞
	public void testTopTenWord() {
		basic.topTenWord(fileName);
		for(int i=9;i>0;i--) {
			System.out.println(testTopWord[9-i]+"=="+i+"=="+basic.topTenWord(fileName)[i].getKey());
			assertEquals(testTopWord[9-i],basic.topTenWord(fileName)[i].getKey());
			assertEquals(testTopWordCount[9-i],basic.topTenWord(fileName)[i].getCountNum());
		}
	}

	@Test
	//測試行數
	public void testLineCount() {
		basic.lineCount(fileName);
		assertEquals(4,basic.lineCount(fileName));
	}
}


           

其中一個測試結果截圖

在JUnit4的測試下,我們的總體代碼覆寫率在80%左右,其中Main.java類是用來輸出結果的類,是以沒有加入測試,還有一些原因是很多的異常處理是沒有辦法觸發的,這些代碼沒有覆寫住。不過我們主要代碼的覆寫率都在90%左右,甚至以上的,是以說我們的測試結果還是對程式正确性做了有力驗證的。

三、其他

3.1、代碼規範:

​ 碼出高效 :阿裡巴巴Java開發手冊終極版v1.3.0

221600327:

​ 行數統計、指令行參數解析、輸入輸出子產品代碼編寫、單元測試、文檔編寫

221600329:

​ 字元統計、單詞統計、詞頻統計子產品代碼編寫、爬蟲設計和實作、性能測試、文檔編寫

本來我們認為的詞組詞頻統計會過濾掉單詞間的非法字母數字字元,而後來助教重申了需求,要求輸出這些字元。因為原先的做法是先把非法字母數字字元都替換掉,然後再進行操作。這需求一改,不就全涼了。後面隻能一個字元一個字元的周遊,再截取單詞。但是最後發現在資料量大的時候,不采用split去分割字元串,直接周遊反而速度更快,而且更省記憶體。

3.5.1 221600329 評價 221600327

隊友給夠按時完成配置設定的任務,有耐心,可能基礎不是特别紮實,但是肯學肯做,這點事值得肯定的。

需要改進的地方:編碼能力需要加強。

3.5.2 221600327評價221600329

我的隊友在我們結對中大部分時間是駕駛員的角色,他對于需求的分析能很快劃分成若幹個字子產品,在程式設計方面他資料結構和算法方面的基礎知識相當紮實,編碼實作能力也很強。我最欣賞的是我的隊友認真和仔細的态度,他對作業近乎追求完美,在滿足正确性之後還盡量去優化性能;還有他的堅定的信念,就算他在這周身體不舒服,每天狂咳嗽,但是他還是沒有是以落下過一點進度,這是我很敬佩的。

需要改進的地方:在任務配置設定方面可以均衡一些,不然會累着他自己。

3.6、 感想

這次作業碰上了我重感冒的時候,一直咳嗽不止(不敢熬夜了),再加上自己程式設計能力不突出,是以時間上安排的不好,對于附加部分的需求,沒有時間去考慮和設計。這兩次都是結對任務,我和隊友之間的協作能力有了進步,但是目前還是沒有很高的效率,可能還沒度過學習階段,依然處于磨合階段。

這兩周的任務都是結對任務,是以以此為契機我們閱讀了《建構之法》第四章兩人合作,了解到結對程式設計是極限程式設計這一思想的具體展現,結對程式設計有三種形式:

①鍵盤滑鼠式②Ping-pong式③領航員-駕駛員式。

了解到結對程式設計,因為在結對程式設計過程中有随時的複審和交流,可以減少犯錯,提高解決問題的效率,形成知識傳遞。

了解到要做好結對程式設計,需要遵守相同的代碼規範,在不同的階段,不同的人之間要有不同的方式,而且要養成個人良好的生活習慣。

但是我覺得雖然結對程式設計有很多好處,但是結對程式設計的兩個隊友,程式設計水準不能相差過大,不然可能會造成交流變成了教學,浪費更多的時間,影響效率。