1. 程式人生 > >由引入 Google Protobuf 引發的工程管理思考

由引入 Google Protobuf 引發的工程管理思考

看到標題,很多人可能會在想這個 Google Protobuf (後面簡稱 PB ) 是一個什麼東東,其實最開始我聽說的時候也在懷疑,甚至一開始我還以為是之前跟著大牛寫服務端功能時使用的 Thrift 混為一談,深入接觸後才發現,其實不然。至於 PB 到底是啥呢?我在這就不詳細介紹了,想了解的人可選擇傳送門

  • 引發思考的場景

應該多端統一開發需求,需要在 Windows 客戶端開發中引入 PB 協議,但是由於是體力活,所以想如果能不增加開發人員的休力勞動是一件多麼好的事件。

很多人會想,同步協議這個過程並不會多費時,但是,如果說在專案初期或者是在專案重構時引入 PB,當一切都未定論的時候,修改再所難免,這時體力勞動可想而知。我也是基於這個場景設計了一套屬於懶人同步協議的方案。

希望對大家要管理一些特殊工程時有所啟發。


  • 解決問題思路

在開始講述方案前,需要了解如下概念:

  1. Visual Studio 中有 Build Event 這一配置項,它有 Pre-Build、Pre-Link 和 Post Build 三個子項;
  2. Visual Studio 中還有 Forced Include File 選項及預編譯標頭檔案;
  3. 在我們的日常開發過程中,有時需要充分利用指令碼程式設計,Windows 下有 bat,Linux 下有 shell,在我這些開發過程中都給我帶來過巨大的便利。

接下來我們深入剖析我的解決方案。
首先,我們需要編譯 PB 檔案來生成 C++ 檔案,這裡需要注意的是在使用 protoc.exe 時最好帶上 -I 選項,不然編譯可能無法進行。大家都會想到,這裡會引入指令碼

protoc.exe –cpp_out=”%_OutDirectory%” -I”%_SrcDirectory%” “%%f”

當然檔案多時也可以用萬用字元來處理。可是,天有時總不隨人願,PB 檔案有個編譯選項 optimize_for,可選 CODE_SIZE、LITE_RUNTIME 等,在服務端開發中需要使用 CODE_SIZE,但是在客戶端中因為強迫證根本不想引入過多的資訊,所以會選擇 LITE_RUNTIME,這就引來一個檔案,協議檔案不可能存兩份,否則帶來的危險是未知的。所以我們在編譯時需要替換了,通過指令碼修改

setlocal enabledelayedexpansion
for
/f "delims=" %%i in ('type "%%f"') do ( set str=%%i set str=!str:CODE_SIZE=LITE_RUNTIME! echo !str!>>"%%f_tmp" )

看似很完美了,但是模組開發的概念又把我們帶入了一個新的問題當中,因項專案管理需要,我必需提供 SDK 形式的模組,別人並不需要關心協議的細節,所以我們會想以 DLL 方式提供,這需要為每個類或者方法新增 __declspec(dllexport),這如果說在編譯協議之後手動加是不現實的,修改編譯命令

protoc.exe –cpp_out=dllexport_decl=FRAME_CLASS:”%_OutDirectory%” -I”%_SrcDirectory%” “%%f”

修改完成後,滿懷驚喜的使用指令碼,編譯,發現 FRAME_CLASS 並沒有在生成的 PB C++ 檔案中引用到,如何解決,考慮過從 PB 協議上新增,未找到方法,於是從標頭檔案中來思考,如何才能把帶有 FRAME_CLASS 巨集的檔案準確加到生成的 C++ 檔案中,通過指令碼控制有點難,所以想到了預編譯標頭檔案和 Forced Include File 選項,處理如下:

  1. 把帶有 FRAME_CLASS 巨集的檔案包含到預編譯標頭檔案中;
  2. 在 Forced Include File 選項中填入預編譯標頭檔案。

好的,現在上面的指令碼能很好的工作了,也能解決編譯時自動編譯已經修改的 PB 檔案了,將編寫好的 bat 檔案加入 Pre-Build 選項中,大功告成。


  • 進一步完善解決方案

確實,目前已經完成了半自動化的編譯 PB 檔案了,但是,在 PB 逐漸完善的時候,第一次編譯都重新編譯 PB 檔案的做法就有點雞肋甚至有些不可取了,這時又不得不回過頭來思考,如何做增量編譯?

我所想到的是檔案修改時間,因為這是每次修改檔案後都會改變的值,也是我們可以最小量儲存的中介軟體。

在處理檔案修改時間時,最開始使用 bat 時,發現處理起來不是很方便,所以我又引入了 VB script。這裡不作詳述。