結對編程第三周總結
項目 | 內容 |
---|---|
課程 | 2021春季計算機學院軟件工程(羅傑 任健) |
要求 | 結對作業-總結 |
項目地址 | 結對編程gitlab倉庫 |
一、結對項目實踐反思
在兩周的結對編程過程中,我印象最深的有兩個階段:分析設計階段和測試階段。所謂說明書有多長,設計階段就有多“痛苦”。你的設計有多復雜,測試階段就有多“痛苦”。當然,這都是誇張的吐槽,但毫不誇張的是,我們組在這兩個階段上花的時間相比coding要多得多。
1. 實踐中問題分析
- 測試相關問題
實不相瞞,我在這一次結對編程前,對於測試這個階段的工作,重視程度並不高。其實我早應該警醒,因為之前的好多作業(比如OO)都是因為測試不到位出錯。或許是過於相信自己的邏輯,或許是偷懶,我在測試方面的工作做的並不好。
但是我的隊友很好的彌補了這一點。這並不是因為每次作業覆蓋率都要超過90的push,我的隊友對於測試重視程度很高,即便是最簡單的函數單元測試,他也會測上很多看起來很冗余的情況。(說實話,在這方面我還是抱了他的大腿)
測試程序應該覆蓋每一個可達的分支
這是書上的一句話。我們在第一次作業很好的踐行了這一點,幾乎所有的語句全部覆蓋了。唯一一條沒有被覆蓋的語句,是為了保險,加入的一個拋異常的語句。(其實這個語句根本無法到達,我們並沒有刪掉)但是我們確實做到了每一個可達的分支,可達的語句都做了測試。
第二次的作業,由於之前分析設計和coding的時間較長,我們的測試覆蓋率剛好超過90。但是最終兩次作業的強測都全部通過,第三次作業測試也只錯了一個點。(錯的這個點確實是分支沒有覆蓋到的地方)
這兩周的結對編程我在真正體會到,測試對於一個程序的重要性,肉眼可見的重要性。當然,在編寫測試的時候,我們也發現了大大小小的Bug,通過不斷的測試,修正過程,我們程序的正確性大大的提高了。
還有在於寫測試的,可能是我們的方法不太正確,出現的部分Bug是因為測試程序邏輯寫錯(其實是測試程序的bug而非程序)。
- 不太好的編程習慣
在這個階段,我們發現的bug絕大多數是在編寫程序時,程序邏輯與我們所設想的邏輯相悖造成的。比如,我們在寫解析文件目錄
的代碼時,喜歡使用復制粘貼,而恰好命令間對於文件目錄
的作用效果有細微的不同,復制粘貼的代碼就出現了錯誤。導致我們花費了大量的不必要的時間去查找問題,瘋狂debug。
- 統一意見太快,缺少細節性的思考
現在復盤前兩次的作業,其實也有很多問題是我們的共性問題。因為我們幾乎大部分時間從需求分析開始在進行面對面結對,所以一開始就比較統一,但是正是由於我們的意見太早過於統一,導致我們進入了相同的思維誤區,導致了一些Bug的出現,而且自己還很難發現。
2.需求分析實踐體會
無止盡的issue,哇,說到這個,真的是非常的佩服我們的助教團隊。我能感覺得到,指導書都是經過反復斟酌,各種情況也寫的很全。可是“人非聖賢孰能無過”,有的地方總會有差錯和不解,這是不可避免的。很少人能夠寫出完全工整的指導書或需求書。
軟件工程,唯一不變的是變化。所以干脆別幻想客戶的需求會在第一時刻很明確,然后保持不會變。
我們也深刻的體會到了這一點。影響設計細節的往往是細節,有時細節甚至會影響到設計整體思路。所以在設計分析階段,我們就曾因為很多不確定的小細節而被迫中斷設計的思考。這讓我們coding的節奏中斷了許多次。
上課的時候,老師給我們舉了一個很形象的例子:
一位顧客拿着一張大部分完整的發型照片找到理發師,要求理發師就按着這個照片剪。一段時間后,理發師100%完成了任務。事無巨細地將每一處細節完美還原,當然也把沒有被照片截進去的部分一刀切了。
造成這個問題的根本原因,就是雙方缺少充足的溝通。
在本次開發實踐中,我和隊友不斷地在針對每一處細節進行討論。隊友間的討論能有效互換看法,從而得到更優解。而更為重要的是,設計人員與開發人員之間的討論。
前幾天我在田同學的博客有如下評論:
記得之前看到一個笑話:
這個世界上難道就沒有一種軟件和腦機接口,能夠把自己所想的自動轉化成代碼嗎?有啊,乙方。
這個笑話很真實,正因真實,我們可以在當中找到一些現實的影子。
真正的工程中或許留給開發人員決定的部分比較多。
或者說是乙方需要跟甲方不斷交流,不斷探討需求書中沒有提及的內容,以達到互相合作解決問題的目的。那么從這個角度來講,一個明確的方向和充足的交流是必須的,細節是次要的。
第二周結對編程就非常好的體現了這個特點,不斷地出現,問題不斷地被解決。
可是換一個角度來想,在現實中真的有這么多正確答案嗎?如果沒有正確答案,那issue會不會無止盡地多下去呢?我認為現實工程中,正確答案會很少,更多的應該是Open Questions,比如這個按鈕放在上面好還是下面好等等。
計網課上,羅老師說過,現在計算機網絡所使用的技術更新很快,因為人們還沒有找到最好的。正是因為沒有最好的,可是又有那么多人要用,需求大,所以要不斷找好用的。
軟件的開發或許也如此:需求過大——快速開發的demo——不斷更新的功能、不斷優化的體驗。但也有很多產品,經過了長時間的沉淀,出道即巔峰。同樣,這里也就涉及到最小價值產品(MVP)還是完美產品(MBP)的問題了。
而對於我們的程序,大部分功能其實能夠根據指導書正常運行,但是可能由於我們對文件管理系統的了解不足和指導書的分析不夠到位,issue區的大部分坑點我們都沒有想到,於是issue區的易錯點成了我們的重災區,比如硬鏈接鏈接軟鏈接的鏈接文件等坑點。幾乎遇上issue的問題都會出或大或小的問題,當然我們在測試部分着重關注了這部分坑點,所以最終的Bug也不是很多。
3. 架構設計體會
在第一部分,我們的設計思路其實非常簡單。我們實現的文件系統的主要元素就只有兩個:文件和目錄。其中目錄之間有包含關系(上下層),文件也會存在目錄中。所以我們創建了兩個類:MyFile
類和MyPath
類分別表示文件類和目錄類。然后對於各個細節的要求,我們就在各個類中完成相應的必需功能並提供給頂層的MyFileSystem
類,用來集成實現最終的功能。而對於第二部分,將第一次作業整合進fileSystem
包中,將此次作業新增的用戶和用戶組相關整合進userSystem
包中,作為兩個相對較為獨立的系統進行代碼編寫和運行。而對於新增的軟鏈接和硬鏈接,我們采取的方法是是分別新增軟鏈接類和硬鏈接類,而不是將軟鏈接和硬鏈接歸為文件類統一管理。
在這個架構的基礎下,由於對象種類增加,我們對原有代碼也進行更新,多了很多對象種類的判斷和運行邏輯。而且對於新增的mv, cp, ln等指令,由於有四類對象的存在,所以每次的對象判斷,我們都需要對這四類對象進行分別判斷和處理,極大的增加代碼的復雜度和冗余度,而且Bug頻發,后期主要精力也花在這一部分。而且代碼冗余的增加進一步的提高了測試的難度,導致我們在debug和測試時都感覺到了一定的困難。這也進一步體現了一個好的架構的重要性。這也是我們在結對部分,在架構設計部分需要進一步提高的問題所在吧。
其實,我們也想過將軟鏈接和硬鏈接歸類為文件對象,但是因為我們第一次作業並未留下這個接口,以及我們認為這樣需要更大范圍的重構,就並未進行這樣的架構修改,現在想想有億點點后悔。
4.進度、質量和溝通管理實踐體會
此處通過PSP流程來總結兩次結對編程的進度管理
PSP2.1 | Personal Software Process Stages | 預計耗時 | 實際耗時 |
---|---|---|---|
Planning | 計划 | 20 +10min | 10+10min |
*· Estimate | · 估計任務需要多長時間 | 20+10min | 10+10min |
Development | 開發 | 895+1420min | 975+2120min |
· Analysis | · 需求分析 | 90+90min | 120+120min |
· Design Spec | · 生成設計文檔 | 30+20min | 30+20min |
· Design Review | · 設計復審 | 10+10min | 10+10min |
· Coding Standard | · 代碼規范 | 5+10min | 5+10min |
· Design | · 具體設計 | 30+30min | 20+60min |
· Coding | · 具體編碼 | 400+500min | 350+720min |
· Code Review | · 代碼復審 | 30+60min | 60+80min |
· Test | · 測試(自我測試,修改,提交) | 200+700min | 380+1100min |
Reporting | 報告 | 135+110min | 110+100min |
· Test Report | · 測試報告 | 100+60min | 60+40min |
· Size Measurement | · 計算工作量 | 20+30min | 30+20min |
· Postmortem & Process Improvement Plan | · 事后總結,提出改進計划 | 15+20min | 20+40min |
合計 | 950+1540min | 1095+2230min |
由於大部分時間我們都是線下面對面編程,而且我們都甚至自己和對方的生活極為”充實“,所以每次在一開始我們都會對進度進行一定的預測和控制,而且從第一次的結果來看,效果極為不錯。但是第二次的難度預估遠超我們的預料,所以進度預估和控制把握不是很好,從PSP表上也能看出,差距較大。程序的質量和交流的效果也因線下而效果較為不錯。
我們在第二階段的最后一天,發現了因為兩人對於硬鏈接
鏈接軟連接鏈接
這個概念理解出現偏差,程序在弱測中出現了bug。我們花了一些時間對這一細節進行了不大不小的“爭論”和探討。
5.提出建議
在結對編程之前一定要先了解什么是“結對編程”。充分閱讀《構建之法》!《構建之法》用了大篇幅來介紹,他從人員配合、分工、過程的每一步都進行了完整的分析。
整個結對編程期間,我與隊友很少出現因為時間沖突、性格不合、說話方式而產生矛盾和問題。隊伍之間討論的最多的,除了以上所談到的一些bug之外,就是細節的設計和實現思路了。
或許在不看這本書之前,與隊友的爭執會讓我有些心浮氣躁,但看了這本書之后,我能清楚地意識到我們只是在對於項目的設計進行爭論。同樣,他也能認識到這一點。
結對編程的伙伴需要對雙方的目標、結對方式、心理預期等等做互相的了解。
社會心理學上有一個概念:
“行動—觀察者差異”。自己對於某件事的看法,相比別人看見你的行為推測你對於這件事的看法是有差異的。你的行為並不能完全代表你的看法。
這是因為行動者與觀察者有着不同的思考、觀察角度,所帶有的價值就不同。而閱讀《構建之法》,相當於在我和我的隊友之間建立了相同的價值,我們就能消除這樣的“差異”,更加心平氣和的去面對“爭執”。
二、CI體驗感想
我認為CI的作用非常的強大。CI能夠進行Junit單元測試程序的自動化測試,並且計算出相應的代碼覆蓋率。CI的部署讓我們省去了很多額外的測試時間。同時,CI強大的功能支持我們通過url下載的官方包進行測試,每次上傳代碼之后就能夠查看結果。但是我們也知道,我們對CI的了解還不是很多,CI還有更多有利的地方等待我們使用和挖掘
三、結對編程感想
1.結對編程方法與經歷分享
我們結對大部分都是在線下進行,面對面的分享和交流,從需求分析開始統一意見和目標,然后采用“領航員與駕駛員頻繁互換身份的方式”,來完成絕大部分的項目開發。線下交流可以及時解決突發問題,然后繼續開發,將影響降到最低,不讓問題過夜。
優點:互相學習和問題交流,取長補短,保證項目的穩定進行
缺點:需要一定時間的磨合,雖然我們的開發過程中沒什么大的沖突和分歧,但是在小部分還是有很多需要改進的地方
分享部分或許大概就是:線下結對編程應該會是體驗最好的方式之一了吧,及時的問題交流和解決,近距離的學習和吸取隊友的優點,體驗非常不錯。一定要統一代碼規范,統一規范的代碼讓隊友能夠快速的理解和上手,可以極大程度的減少不必要的時間開銷。
2.使用工具
交流:宿舍(絕大部分)、微信(后期實在無法線下結對才使用的)
代碼編寫:IDEA軟件,maven項目管理,騰訊會議共享屏幕
單元測試:JUnit4
項目部署:gitlab-ci持續集成(十分感謝討論區大佬的知識分享)
3.隊友評價以及感悟和體會(吐槽)
3821
lhx同學時間管理能力非常令我佩服,在其他工作的壓力之下也能夠拿出大量時間和我進行線下的分析討論與面對面編程。同時lhx同學的分析理解與決斷能力在這次結對編程中起到了重要作用,經常將理解上誤入歧途的我拉回正道。lhx同學優秀的編碼規范也是我們能夠完成結對作業的一大助力。以及或許在思考問題的細節方面能夠再周全和縝密一點,或許能夠更好。當然了,這是一次非常愉快的結對合作,希望都能在軟工課上收獲滿滿,取得好成績。
其實總的來說,結對編程的體驗還是很不錯的。兩個人線下面對面,從需求(指導書)分析到設計,從編碼到最后的單元測試,都是及時討論一起解決的。在分析和設計階段,能夠互相幫助理解需求,集思廣益進行架構設計(不過好像我們的架構也挺一般的orz);在編碼和單元測試階段,能夠及時糾正編碼錯誤,增添對細節點上的測試等。也很幸運有一個優秀的隊友,讓這次結對體驗更加完美。(如果后續的指導書再斟酌、控制一下,那么此次體驗就真的perfect了)。
這次結對作業應該算是有初步的需求不斷變動的工程體驗了。第二次作業上,既要修第一次的bug,又要增添第一次應該考慮但是課程組未測試的細節,還要更新屬於第二次的需求。而且第二次作業需求上的不斷更新與細化,為了不大范圍的變更代碼,我們只好就瘋狂打補丁,最后代碼效果emmmmm(懂得都懂)。這應該是我們需要進一步學習與改進的部分吧。感謝老師和助教在此部分的准備和及時回復,也希望在后面的階段會有更多的收獲。
3676
在文章的開頭我就贊揚了我的隊友,我從他的身上學習到了非常多優秀工程師的品質。其中最為突出的一點:測試全面,前面已經提及了。他對於小模塊的測試也毫不含糊,在結對編程的過程中,這樣的一絲不苟不斷地影響着我,讓我更加重視測試。而在整個過程中,他更像是一種“駕駛員”的角色。他的代碼能力比我更強,而我可能在設計上有些有意義的見解。從頭到尾,我們之間的合作都是非常愉快的。
接着實踐總結部分的最后,我想來談一談結對編程任務。
首先,毋庸置疑的是,這兩周的經歷讓我收獲非常多。收獲不僅在於代碼,設計層面的知識,更是在合作,交流的層面。知識固然重要,但學習別人的優點,與優秀的人交談,領會他們的思維和思想,更是一件幸福的事。我不僅從我的隊友身上學到了很多,我還有機會通過博客的方式,與大佬們進行交流。本人代碼能力並不強,身邊優秀的同學思考得還比我更加深入,我深感慚愧。當然,這也會不斷激勵着我變得更好。
其實翻看第二周的博客,我似乎在“反思”。可是當我翻看其他同學的博客時,我能感覺的到,他們才是真正的在反思。而我只是發發牢騷,對大量投入的時間和不對等的回報感到不滿。在那篇博客中,我將我們比作“小白鼠”,結對編程比作“實驗”,而表達我的“痛苦”。看似“理性”的看待,但實則非常感性。所以我在后面的評論中反思道:
抱歉,這個比喻可能有些不恰當。我並沒有覺得課程組在我們身上做實驗,課程組對於課程的設置一定是經過深思熟慮的。人非聖賢孰能無過,有一些差錯完全可以理解。其實我也在反思自己:自己寫博客的時候是否是在發牢騷,而不是真正的思考;自己的能力是不是還沒有能夠達到課程組的要求,所以才花了這么多時間(相比於其他結對小組,我們的時間也高出了不少)。
但是不管怎么樣,我可以看到的是,我們和課程組都在不斷地進步!“悟已往之不諫,知來者之可追。”過去的已經過去,而為未來做好充分的准備才是現在最重要的事!
既然結對編程已經結束,或許應該好好反思,寫一篇博客,好好睡一覺然后重新出發!