天天看點

初見,結對程式設計!(上)

項目

内容

這個作業屬于哪個課程

2021春季計算機學院軟體工程(羅傑 任健)

這個作業的要求在哪裡

結對項目-第一階段

我們在這個課程的目标是

和團隊開發真正的軟體,一起提升開發與合作的能力

這個作業在哪個具體方面幫助我們實作目标

通過結對程式設計學習協作設計與編碼、代碼複審、CI使用等

結對項目第一階段的<code>Gitlab</code>倉庫位址

Pair Programming

二人的學号後四位

3110, 3142

部落格位址

MadokaHomura(朱正陽), zixfy(趙子軒)

本次作業最終需要實作一個基于記憶體的檔案系統,它允許使用者通過各類輸入指令來進行檔案的增删查改等互動,資料結構是樹型結構。

在邏輯上某一條指令的處理流程圖如下:

graph LR

input[指令輸入]--&gt;parse[解析位址]

parse.-&gt;pathE&gt;路徑格式錯誤]

parse--&gt;instrType{指令類型}

instrType--增--&gt;instrAdd[擷取路徑倒數第二級目錄]

instrType--查删改--&gt;instrOther[擷取路徑最後一級目錄/檔案]

instrType--遞歸建立--&gt;instrMkdirp[遞歸建立目錄]

instrAdd.-&gt;getFileE&gt;目錄/檔案不存在]

instrOther.-&gt;getFileE&gt;目錄/檔案不存在]

instrMkdirp.-&gt;typeE&gt;目錄/檔案類型沖突]

instrAdd.-&gt;typeE&gt;目錄/檔案類型沖突]

instrOther.-&gt;typeE&gt;目錄/檔案類型沖突]

instrAdd--&gt;addOp[增加子目錄/檔案]

addOp.-&gt;existE&gt;子目錄已存在]

instrOther--查改--&gt;modifyOp[操作檔案/目錄]

modifyOp.-&gt;contentE&gt;檔案内容格式錯誤]

instrOther--删--&gt;delOp[父目錄删除此目錄/檔案]

delOp.-&gt;delPerE&gt;删除工作目錄或其上級目錄]

style pathE fill:red,fill-opacity:0.1

style contentE fill:red,fill-opacity:0.1

style getFileE fill:red,fill-opacity:0.1

style typeE fill:red,fill-opacity:0.1

style existE fill:red,fill-opacity:0.1

style delPerE fill:red,fill-opacity:0.1

是以我們将程式所需實作的功能/子產品列出

PathManager: 一個解析路徑的疊代器

a. 通過路徑構造,并在構造時判斷路徑類型(絕對路徑、相對路徑)

b. 将路徑分級(分段),作為疊代器傳回下一級解析出的單級位址

FileLike: 檔案類/目錄類的父類,下簡稱類檔案

a. 儲存類檔案的基本資訊, 名字,絕對路徑,建立/修改時間,父目錄,大小

b. 自底向上更新檔案/目錄大小

Directory: 目錄類,管理子檔案/目錄

a. 對子檔案/目錄進行增、删、查

b. 向檔案系統提供根據路徑索引檔案/目錄的靜态方法

c. 向檔案系統提供根據路徑索引對應檔案/目錄的父目錄的靜态方法

d. 向檔案系統提供根據路徑遞歸建立目錄的靜态方法

File: 檔案類,管理檔案存儲内容

a. 追加/覆寫檔案内容

b. 對檔案内容進行轉義以輸出

MyFileSystem: 檔案系統類,通過調用底層類按指令語義進行操作或抛出異常

我們随手畫的草稿如下:

初見,結對程式設計!(上)

最終經過縫縫補補改改删删後完成時的<code>UML</code>類圖

初見,結對程式設計!(上)

而且一條指令的執行過程中可能在流程圖中任一執行階段觸發異常,是以我們使用<code>Java</code>的異常處理機制來處理錯誤輸入,我們所定義的各種異常類如下

初見,結對程式設計!(上)

由于本次作業不區分不同異常輸入對應的輸出資訊格式,是以隻要在MyFileSystem中的方法調用過程中<code>catch</code>到相應異常就直接輸出<code>Path x is invaild</code>的錯誤資訊,如果後續需要分辨不同的異常情況,我們隻需修改嵌套的<code>try-catch-throw</code>的邏輯即可

對于<code>PathManager</code>疊代器的實作,選擇了使用自動機,因為路徑的格式定義比較簡單,是以用自動機編寫不難,而且可以清楚地考慮到各種特殊情況。并且疊代器分級解析位址時同時進行了格式檢查,是以相比于<code>check + split</code>不需要額外存儲空間

對于"根據路徑索引對應檔案/目錄的父目錄”, 考慮到我們規定<code>PathManager</code>解析完時<code>next()</code>傳回特殊值<code>null</code>,是以隻要将目錄分成根目錄、單級目錄、兩級以上的目錄(<code>/</code>, <code>/a</code>, <code>/a/b</code> or <code>a/b/c/......</code>)三種情況分别處理就行了,同時在擷取父目錄結束時解析出最後一級位址(檔案名),<code>Java</code>不能傳回多值,是以封裝了一個資料結構保證隻掃一遍位址就okay

對于檔案内容的轉義,我們的實作是在檔案類<code>File</code>中隻維護轉義後的檔案内容,在<code>fappend</code>指令中對連接配接處可能新産生的<code>"@n"</code>作特判

mytql, 根據他的方法我們在<code>CI / CD</code>運作環境中配置好了<code>maven</code>,并使用<code>jacoco-maven-plugin</code>生成測試結果報告(一個網頁和一個表格),最後一次送出得到的測試報告如下圖

初見,結對程式設計!(上)

<code>cobetura</code>與<code>jacoco</code>都能得到這種頁面,但在檢視分支覆寫率時貌似都隻能檢視某一分支的遺漏分支數量,并不能了解在條件表達式在何種布爾表達式下是沒有被測試過的,希望能有<code>dalao</code>指點(

初見,結對程式設計!(上)

為了代碼覆寫率達标,當然要對各子產品中的異常的抛出也進行測試啦,我們使用<code>Junit</code>中的函數标注<code>@Test(expected = myException.class)</code>進行抛出異常的斷言,以及在測試函數中自己手動進行<code>try-catch</code>測試異常是否如預期抛出

現場結對程式設計的照片:

初見,結對程式設計!(上)

專注中...

初見,結對程式設計!(上)

(攝于2021年3月23日)

3/22: 摸石過河

15:05 - 15:30: 設計與思路交流

15:30 - 17:30: 編碼

18:21 - 20:20: 編碼

20:40 - 22:30: 編碼

3/23: 撥雲見日

15:55 - 18:25: 編碼

18:30 - 20:30: 編碼

20:51 - 21:20: 總代碼複審

3/24: 再複審

14:31 - 16:20: 代碼複審 評測 報告

在本階段二人決定角色定位将更有傾向性,但是二人進行了充分的交流,并在一些時間段交換工作,是以都對代碼知根知底,兩人不同角色的工作比例大概都是七三開。本次朱正陽擔任<code>Driver</code>,主要職責是具體源代碼實作,趙子軒擔任<code>Navigator</code>,主要職責是測試與把握整體設計

在第一次結對程式設計中,我主要擔當的是駕駛員(<code>Driver</code>)的角色,通過這次結對程式設計,我主要從以下兩方面發表自己的感想

關于結對程式設計

最開始結對的時候效率并不高,我認為原因主要有以下三點

兩個人在某些細節上想法有所不同

交流上存在一定障礙,有時雙方都無法及時get到對方的點

我沒有提前做好準備,許多東西我還需要進一步消化了解

随着結對不斷進行,雙方交流效率也提高了,任務效率也逐漸高了起來。

結對程式設計也是一個很好的向他人請教的機會,能夠近距離看到隊友是如何程式設計的,對于這個問題他又是怎麼想的,确實能夠收獲很多。

結對程式設計還是一個強迫與他人進行思想上的交流以及傳遞自己想法與觀點的過程。

關于開發流程

在此前的程式設計中,我很少将大部分精力放在設計以及測試上。通過這次結對,我學習到了很多關于單元測試的知識,也真正認識到了設計以及測試的重要性。

關于隊友

有一個非常靠譜的隊友确實可以大幅提高程式設計的效率以及品質。隊友的程式設計習慣比較好,對于程式的架構也把握的很好;在我程式設計的過程中不斷的指導我,耐心糾正我的很多不良的程式設計習慣以及備援;做事比較認真負責。通過這三天的結對程式設計,我也從他那裡學習到了很多東西,這是我一個人程式設計所做不到的。我很感激能有一個這樣的隊友。是以後續也會一起努力,一起進步

接下來應該還會有第二次第三次結對程式設計的任務,希望能在之後的任務中繼續向隊友學習,更加放開交流,努力完成任務,提升自己。

在第一次結對程式設計中,我主要擔當的是<code>Navigator</code>,我的體會與反思:

紙上得來終覺淺,在親曆<code>Pair</code>之後,我認為<code>Pair</code>最大的好處是提升代碼的品質,畢竟在二人協作時讀懂代碼是交流的先決,總是會不自覺地想去保證代碼的可維護性。我認為好的結對程式設計需要以下長期的要素: 信任、執行力以及可見的詳盡計劃。

關于信任,我想這就是教材裡說的道德水準吧,但這更應該是每一個程式員的基本素養。單槍匹馬在以後工作中更是不可能,是以無論是采取何種的合作形式都應該對搭檔給予信任,這是“平等地位”的先決,本次我與zzy全程都在互相支援,并及時進行溝通

關于執行力,這是<code>Pair</code>效率的保證,好在zzy與我都是做事比較投入的那種人,結對現場基本沒有摸魚機會(。但實際上也是以沒有保證每小時都有休息時間,以後一定會協調好時間的

關于計劃,這是我們本次有所忽略的,我作為<code>Navigator</code>沒有給出細緻到小時級别、功能級别的編碼計劃,這一方面使得編碼變成了步步為營,另一方面也導緻有時二人并沒有是為了同一個小目标而工作,進而降低了工作效率。我決定後續一定要在動手前先制定好工作計劃,磨刀不誤砍柴工

我在本次<code>Pair</code>中發現自己的不足如下:

上文3.

我向來是不擅長與他人深入交流的baka,是以<code>Pair</code>實際上是對我的一次考驗,而且我在經常性的交流中更難專注想事情

我太菜了,作為程式設計苦手,想到要6天内完成<code>OO</code>的“第五單元”就頓感亞曆山大。在擔任<code>Navigator</code>時不能保證總是給zzy正确有效的指引,對于整體架構,在實作時自己卻還在改來改去。在自己寫的一些方法裡還<code>Bug</code>頻出

本次<code>Pair</code>之前我對Junit一知半解,但為了能跟上整體代碼的進度,所寫的單元測試代碼便相當的臭長

總之第一階段的<code>Pair</code>讓我明白了團隊計劃與編碼能力的重要性,希望後續能努力做得更好

PSP2.1

Personal Software Process Stages

預估耗時(分鐘)

實際耗時(分鐘)

Planning

計劃

· Estimate

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

5

Development

開發

515

1025

· Analysis

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

30

25

· Design Spec

· 生成設計文檔

· Design Review

· 設計複審 (和同僚稽核設計文檔)

15

10

· Coding Standard

· 代碼規範 (為目前的開發制定合适的規範)

20

· Design

· 具體設計

· Coding

· 具體編碼

180

480

· Code Review

· 代碼複審

60

· Test

· 測試(自我測試,修改代碼,送出修改)

360

Reporting

報告

70

140

· Test Report

· 測試報告

· Size Measurement

· 計算工作量

· Postmortem &amp; Process Improvement Plan

· 事後總結, 并提出過程改進計劃

合計

585

1170

Java

總行數

代碼行數

注釋行數

空行數

Src

918

629

109

Test

745

622

123

Total

1663

1251

232