陳 暉 柏立悅 史國芳 洪小敏 李 冬
(浙江中控技術股份有限公司)
在文獻[1]《影響工業軟件開發周期穩定性的根因分析》中提到,新手在面對復雜開發環境時表現出的不穩定性使得項目經理很難對其工作效率進行準確地評估,因此開發周期也變得不穩定。所以筆者針對這個問題,探討了多個應對方案及其可行性,并最終篩選出一種相對最優的應對方案。
想要消除新手開發者應對復雜開發環境時表現出的不穩定因素,沒有簡單且有效的方法,因為一個人的業務水平是無法零成本或低成本地提高的,但也可以從側面提出幾種方法來緩解這種矛盾。
招聘有多年經驗的高水平員工進行開發,顯然會使軟件項目的不穩定因素降到最低,但也有較大的不可行性,具體如下:
a.成本過高。全部招聘高水平資深員工,會使得軟件項目的整體成本大幅提升。
b.人才缺口。我國的IT產業相比發達國家起步較晚,IT人才也只有在近幾年才呈現井噴式發展,IT人才的平均年齡相對歐美國家偏年輕化,其中35歲以上的資深開發人員僅占6.7%[2]。
c.人才斷檔。如果沒有年輕員工加入,那么團隊的技術和業務知識就無法得到傳承,團隊的抗風險能力將變得很弱。
因此,全面招聘高水平人才的方法可行性較低。
企業培訓是普遍存在的,例如華為,相對一般企業通常15天的培訓期,華為則把新員工的培訓周期拉長到180天,但其培訓內容主要集中在破冰、企業文化介紹、職業生涯規劃及團隊協作等方面,并沒有集中在軟件開發技術本身。
事實上,企業目前很少存在短時間內對新員工進行高強度培訓的情況,以大幅提升其專業技能的做法,原因如下:
a.新員工存在不穩定性。50%~60%的新員工在入職后的前7個月內會出現工作變動,造成的損失可達員工年收入的150%~250%。
b.高強度的培訓效果不佳。沒有和具體項目開發經歷相結合,灌輸式的培訓很難達到鞏固知識的效果。
c.沒有明顯的收益。除了培訓成本外,業務水平的提高也會使員工對薪資的期望值有所提升,對企業的成本控制來說是不利的。這也是限制企業加大培訓投入的現實因素。
因此,通過加大培訓力度,在短時間內大幅提升員工的技術能力,該方法的可行性也不高。
在科技日益發達的今天,生產力工具呈現豐富多彩的趨勢,如電腦代替紙筆、機器人代替工人,而自動化公司為生產企業提供DCS(集散控制系統)也是一種先進而強有力的生產力工具。程序員也作為一種生產力,軟件開發是一種生產勞動,而Visual Studio等開發軟件則是他們的生產力工具。
顯然,提供一種好的生產力工具可以大幅提升生產力。就軟件開發而言,好的生產力工具有如下幾個特點:
a.降低開發者的門檻。例如C語言的出現使得編程邏輯變得更簡潔清晰,大型程序的編寫也成為了可能。STL的出現則是讓很多初級開發者可以更關注業務邏輯,而不會在數據結構和算法方面耗費精力卻頻頻犯錯。如今互聯網流行的各種開發框架,如最新的Spring Cloud家族就包含了數十種不同的開發組件,它們可以從不同的角度來簡化一些復雜功能的開發[3],這樣就使一些非頂尖的開發人員也能夠參與到大型系統的開發過程中。
b.減少重復勞動。對于技術專家來說,一些高頻出現但并沒有技術瓶頸的代碼,并不是他們想要關心的。在大中型公司,甚至會成立專門的公用構建模塊(Common Building Blocks,CBB)部門來解決這些問題,比如提供一些基礎模塊,包括網絡庫、數據庫中間件等,甚至還有一些業務重合度高的業務模塊,如用戶管理、工作流等。
c.創建容錯環境。一個新手對代碼規范、開發流程的接受和掌握都有一個過程,尤其是像C++這樣機制較為復雜的語言,會有很多隱藏的陷阱;而資深開發人員犯錯的幾率相對會小很多,但難免也有疏忽的時候。所以創建一個容錯環境,輔助開發人員避免一些低級錯誤和能力不足導致的錯誤,那么開發效率的穩定性勢必會得到保障。常見手段有很多,例如C/C++代碼靜態檢查工具可以幫助檢查緩沖區溢出、空指針等多種異常錯誤[4],大幅減少評審成本并提高代碼質量[5]。
可以肯定的是,提供不同形式的生產力工具確實能較好地保障軟件的開發效率,具體程度依賴于生產力工具的功能是否足夠強大以及與實際應用場景的匹配度。
因此可以得出,升級生產力工具這種方案,與前面兩種方案相比更具有可行性。下面將討論如何選用合適的生產力工具來保障軟件開發效率的穩定性。
在選擇合適的生產力工具之前,應先分析所開發產品的現狀。
產品的應用特點應優先考慮整個企業范圍內,或者至少是部門級,這樣改進措施才具有推廣性。下面以浙江中控技術股份有限公司(以下簡稱中控)為例,詳述分析思路。
2.1.1 產品線的特點
以中控的主流產品DCS及其衍生產品為例進行說明,產品線具有如下幾個特點:
a.項目主導型。出于對工廠數據安全和生產安全的考慮,通常以安裝包的形式提供給客戶,然后在每個工廠的機房或中控室里進行安裝,即軟件大多是在封閉空間中運行的。
b.部署和維護簡易化。這并不是表明自動化軟件比消費類軟件更為易用,相反地,它們比很多消費類軟件在功能邏輯上要復雜很多,如為了滿足數千個工廠的差異化需求,需要開放出大量的設置和參數,因此需要專業的工程人員進行部署和維護。為了降低工程門檻,縮減工程成本,那么就要求部署和維護都能盡量做到簡單化。
c.系統結構復雜。一般互聯網企業的服務器通常只具備兩種核心功能,即計算和存儲。例如現在流行的云存儲和云計算,就是對這兩種功能的大型化、集中化,簡單來說是一對多的關系(一個服務器對多個客戶端)。而DCS則更為復雜:多個客戶端對應多個服務器,并且和多種異構系統對接以形成完整的功能。例如DCS的底層通過控制器連接著數百種不同的軟硬件,又通過OPC等協議將自身的數據傳送給其他系統。所以在DCS中并沒有清晰的后端的概念,體現的是各個部件之間多對多交互的關系。
d.負載穩定。出于生產安全的考慮,一般工業現場的硬件都在性能和容量上有所冗余。且因為生產人員和生產計劃是基本固定的,除了擴大生產等額外因素外,一般來說系統的負載是穩定的。那么在選擇生產力工具的時候就可以不用過多考慮這一點。
2.1.2 單個產品的特點
分析完整個產品線的特點后,再把范圍縮小到單個產品。以中控的增值軟件——高級報警管理系統(Advanced Alarm System,AAS)為例,AAS屬于DCS的增值產品,它從多個角度分析DCS的報警信息,指出報警組態的待優化之處,以保證生產安全。該產品的特點與DCS有很多相似之處,除了:系統結構比DCS簡單,可以把它視為廣義的DCS的一個組件,或者其系統部件的剝離;安全性要求比DCS低,因此一般以快速迭代的方式推出新功能、對接新的系統,以快速響應客戶需求。
主流編程語言。編程語言決定了技術走向,例如阿里巴巴主攻Java,而騰訊則深耕C++,中控AAS1.0的編程語言為C++,與中控的主流保持一致。
組件/框架。在確定了主流編程語言之后,還需指出企業是否采用了一些組件和開發框架。組件和框架的來源有多種,包括自研、開源和商業購買。中控AAS1.0采用單服務器、單進程的C/S架構,使用到的部分組件和框架如下:
a.網絡模塊。中控自研,運用范圍廣,主要負責網絡數據的收發,但不負責數據內容的封裝與解析。
b.數據庫中間件。中控自研,負責適配不同種類的數據庫,如FireBird、Sqlite、Oracle及Microsoft SQL Server等。
c.RapidJson。開源庫,負責網絡數據的封包與解包。
一個生產力工具體系的優點和不足有多個方面。接下來以AAS1.0為例,探討生產力工具的哪些缺失和不完善會使得影響開發效率的不穩定因素被放大,甚至嚴重影響開發進度和質量(表1)。

表1 AAS1.0生產力工具存在的問題
從上述分析可以看出,影響AAS1.0開發效率和質量的問題較多,且是多方面的。其中非業務代碼的占比較大,說明優化空間較大,因為非業務相關的代碼在理論上是有提取、封裝成通用框架的可能性的。經過封裝和測試后,該部分代碼的穩定性就可以得到極大的保障,使得影響開發周期穩定性的因素大幅減少。
不管采用何種改進方案,都至少應滿足如下要求:
a.包含組件化規范,從框架層面去解耦合,從而使所有人的代碼質量有一定保障;
b.網絡性能高,不再為相關功能的優化而投入大量精力;
c.有用戶管理/登錄機制;
d.支持遠程調用,省去調用分發代碼;
e.支持異步調用,避免新手為了實現異步而處理各種線程方面的問題;
f.支持本地和遠程統一形式調用,省去本地存根和遠程代理的定義工作;
g.支持消息訂閱/發布;
h.支持數據序列化自動生成,省去封包、解包代碼;
i.支持文件傳輸機制,避免新手寫出蹩腳而不好維護的相關代碼;
j.在Json的使用上要簡潔易懂。
表2列舉了可能可以解決這些問題的改進方案。

表2 可能的改進方案
表2中列出了作者考慮到的幾種改進方案,接下來仍然以中控AAS項目為例,根據自己產品和技術的特點以及對每種方案的優缺點的可接受度來進行選擇:
a.AAS定位于增值軟件,需要快速推出產品進入市場,并快速迭代以適應不同領域的客戶。因此,全自研C++框架的開發周期和成本顯然是不可接受的。
b.全部采用第三方的框架,需要考慮第三方框架的迭代更新和版權變更帶來的風險,以及融合成本、學習成本。
c.全面轉向Java,有極大的風險。因為歷史遺留代碼將完全不能重用,并且開發人員也需要進行大量更換。這在以C/C++為主的工控領域來說可行性很低。
d.轉向其他生態圈則更不可行。
e.最后的混合型方案則綜合了第1種和第2種方案的優勢,同時削弱了其缺點。而且統一封裝會使得組件的迭代更新不會對產品產生大面積的影響。而在不同語言之間難混合的缺點,可以結合工業軟件的場景,把語言依然限定在以C++為主來進行規避。
因此,綜合比較,采用自研和第三方混合并進行統一封裝是可行性最高、風險最小的改進方案。可以借鑒Spring Cloud的“全家桶”模式:選取一些第三方框架,然后用C++實現一個統一的框架,這個框架封裝了所有的第三方框架,并通過自研補充第三方框架缺失的功能,使得整體風格盡量統一。
以上做法在理論上是可行的,但是如果這個框架的功能完全比照Spring Cloud,則會出現特性過多、開發成本過高的問題。而筆者強調要結合自身產品的特點和場景,因此可以把自己所需的特性和Spring Cloud做一個對比再做取舍,Spring Cloud與C++綜合框架的對比詳見表3。

表3 Spring Cloud和C++綜合框架的對比
從表3可以看出,中控的產品,特別是AAS,對很多特性并無強烈的需求,因此在C++版本的綜合框架中可以只包含少部分最核心最基本的組件。這些組件有些是引入第三方框架進行封裝,有些則是自己實現。這相當于實現了一個精簡版本的C++“全家桶”框架,這個綜合框架中的組件數量不多,但是配合使用可以發揮1+1>2的效果。因此,在開發過程中,開發人員的關注點和工作量就會大幅減少,開發效率的穩定性就可以相應地大幅提高。
因此,利用自研框架和第三方框架形成C++版本的綜合框架可以結合各方面優勢,成本低,可行性高,是一種適合中控AAS項目用來改進生產力工具的較優方案。
筆者列舉了幾種消除開發周期不穩定因素的方法并進行比較,最終得出改進生產力工具是相對可行的方法。然后列舉了幾種改進生產力工具的方案,并最終得出適合中控AAS項目的最佳改進方案。其他企業也可以借鑒類似思路,分析自己產品的特點和應用場景,以此來確定一種適合自己的生產力工具的改進方案來提高開發周期的穩定性。