為應用程式導入版本控制。了解簽入程序。發揮版本控制的功用。
書名:軟體構築美學
作者:Kyle Baley,Donald Belcham
譯者:蔡煥麟,張簡才祿
發行公司:悅知文化,精誠資訊股份有限公司
解決專案開發環境的問題,從版本控管(version control)開始。
問題描述
參考錯誤
第一次從版本控管系統的程式碼,編譯時通常都會出現參考錯誤
簽出時檔案即被鎖定
檔案已被其他成員取出,無法編輯。
維護已經上線的程式碼
同一個 Bug 卻要修正兩份不同版本的程式碼。
版本控管系統裡面有什麼?
必備功能
保留修訂紀錄:保存檔案的不同版本。
連結性:讓每個成員都能輕鬆取得程式碼。
不可分割的交易:檔案的異動要麼全部成功,否則就全部失敗。
減少阻礙
好的版本控管系統,在你簽入時,會讓你能夠回答以下問題
1. 誰做了這次的修改?
2. 改了哪些檔案?
3. 為什麼要改?
比較檔案版本
差異比對可能是找出程式碼為何被改壞的唯一辦法。
容易使用
不論是方便結合IDE的版本控管系統,或是擁有彈性的命令列工具,只要符合團隊就可以了。
檔案管理
主要的兩種模型:檔案鎖定 版本合併
檔案鎖定模型(鎖定-編輯-送交)
優點:操作起來直覺,簽入程式碼的動作簡單,而且發生衝突的機會也很低。
缺點:開發人會經常搶檔案的擁有權,阻礙程式開發。
檔案被鎖定,無法繼續前進時,你有兩條路可選
1. 停止這項工作,等到檔案解除鎖定再來處理。
2. 想辦法把程式碼寫到別的地方。
版本合併模型(編輯-合併-送交)
你只要開始編輯檔案的內容,檔案就會自動被簽出。
如果你要簽入的檔案已經先被別人修改且簽入了新版本,你所做的修改就必須和目前的版本進行合併。
採用單一責任原則以及養成經常簽入的習慣,你會發現合併衝突的機率非常低,就算碰到了也很容易解決。
誰是對的? 看團隊而定,但建議使用版本合併模型。
分支
分支指的是讓程式碼分成兩條或兩條以上的路徑。
使用情境
正式上線的版本出現 Bug,但與目前手邊修正的版本差異太多,可以在上線版本拉出一條分支修正,朝自己的方向前進。
實驗性質的程式碼(spike),為了評估特定解決方案所撰寫的程式碼,例如UI測試,或是測試新框架。
寫這類程式要有時間限制,避免方法行不通,卻花費了太多時間。
這些實驗性質的程式碼應該是可以用完即丟。
記住,我們是要從這些實驗中學習,而不是要寫成正式的程式碼。
分支合併
分支並合併為主線:修正Bug完畢,或實驗解決方案成功,並合併回主線。
分支不再合併回主線:新版本的 .net framwork,專案必須更新為新版本,舊的版本維護一段時間就退下來(原主線),新的版本(新版本分支變為主線)。
頻繁的分支
一般會頻繁建立分支,通常是為了應付多變的需求。
為每項功能建立一個分支,每個分支都只有一個開發人員,達成隔離效果,缺點是將眾多分支合併為主線比較麻煩。
為每一個Bug建立分支,而不是將Bug全部集中到同一條分支線,一旦Bug修正完畢,就合併回主要開發或維護分支。
不要害怕分支,把它當作一個能夠隔離變動的工作來使用就好了。
導入版本控制
在開始將專案加入Repository之前,還有一些問題需要考慮
1. 你的專案是否有用到任何外部元件?
2. 專案的目錄結構是否穩定了?
3. 專案中是否有不需要納入版本控管的檔案或資料夾?
處理外來元件的相依性
1. 從版控系統取出最新版本。
2. 開始VS專案。
3. 編譯並執行
新建成員應該只要執行這幾個點簡單步驟就開始撰寫程式,若手續太複雜,就會形成阻礙,並且降低生產力。
通常最後一步會失敗,參考元件失效。
1. 開發人員的機器上缺少必要的元件或函式庫。
2. 必要的元件或函式庫安裝在不正確的地方。
3. 安裝了不正確的版本。
解決之道是不要依賴開發人員自行安裝這些元件或函式庫,而是將它們直接放到應用程式的目錄結構中。
放在一個集中的地方,讓開發人員都能輕易取得。
只要你的版控系統有保存你應用程式需要的版本,就能避免元件新舊版本不相容的問題。
目錄結構
資料夾名稱 | 說明 |
Build | 包含自動建置的相關檔案。 |
Docs | 用來存放任何與程式碼直接相關的文件。其他文件應該以內容管理系統的形式儲存(不放入版控內)。 |
Lib | 包含應用程式需要用到的外來元件。 |
Src |
app - 包含應用程式的原始檔。 test - 包含測試專案的原始檔。 |
Tools | 用來儲存任何工具或公用程式。這些工具並非應用程式運行的要件,但建置程序可能需要他們。例如:單元測試框架、自動建置工具、用來分析程式碼涵蓋範圍或其他度量的工具。 |
關於 tools 資料夾的注意事項
如果會更著應用程式一起部署,就是屬於 lib,否則就是 tools 。
適合放在 tools 資料夾的檔案 | 適合放在 lib 資料夾的檔案 |
自動建置工具(例如:NAnt) 單元測試框架(例如:NUnit、MbUnit、XUnit) 原型(mocking)框架(例如:Rhino Mocks、TypeMock、Moq、Autofac) 程式碼涵蓋範圍 / 度量分析工具(例如:NCover、NDepend) |
UI元件(例如:DevExpress、Infragistics、Telerik) 控制反轉容器(例如:Castle Windsor、StructureMap、Spring.NET) 記錄(logging)框架(例如:log4net) 物件關聯對應元件(例如:NHibernate、LLBLGen Pro) 自行開發的共用函式庫 |
哪些檔案不需要加入Repository
在 Visual Studio 編譯專案時,bin 與 obj 都不應該加入版控。
因為它們都自動編譯應用程式時自行產生的。
因為每次編譯時,裡面的檔案都會被更動,會頻繁的簽入簽出。
其他可以考慮排除的檔案包括
與程式開發有關的使用者設定檔(*.suo、*.csproj.user、*.vbproj.user)
Visual Studio 附加元件所衍生的檔案(例如:CodeRush與ReSharper產生的檔案)
最後可能有一項例外,你想要讓所有專案成員共享某些生產力工具的設定檔,你可以把這些檔案加入版控
第一次簽入與簽出
不要草率簽入程式碼,以為可以將來出問題時再修補就好。
應該要仔細看簽入時的對話視窗,至少第一次簽入時要特別注意。
簽入程序
步驟4跟5,為了解決當你和其他人同時都在修改程式時可能產生的問題。
確保版控中的程式碼都處於穩定的狀態。
造成衝突的人,要自己負責解決。
版本控制的運用技巧
兩個技巧:經常簽入 使用標籤/標記(labeling,tagging)策略
經常簽入
每當程式碼已經有一點進展,完成一小部分的時候就盡快簽入。這樣就能減少需要處理合併的情形。
使用標籤/標記(labeling,tagging)策略
每次部署應用程式到新環境時就要加個標籤。萬一出現嚴重的Bug,就可以馬上回到上一個可正常運行的版本。
使用標籤的時機
1. 每次簽入時(這種作法有點矯枉過正了)。
2. 每天晚上(要搭配每晚自動建置發行才有用)。
3. 每當完成一項功能時。
4. 當你要大幅度重構程式碼時。
總結
要能有效率地比對檔案差異
了解各種操作版控的方式。
了解你的版控如何處理簽出檔案,並考慮採用版本合併式的版控,不要用檔案鎖定模式。
應用程式開發與運行所需之相關檔案都要加入版本控制。
重新組織你的專案目錄結構,把非程式碼的檔案也納入考慮。
每次簽入程式碼的時候,依本章建議的簽入步驟進行。
將程式撰寫的工作分成較小的單元,以便經常簽入。
為團隊制定一個適當的標籤策略。