衆所周知,良好的系統研發應該有延續性和一致性,因此不少公司很是注意代碼版本控制,並逐漸慢慢的迭代本身的產品。前端
具體到天然資源行業來講,我司純粹的產品銷售較少,項目開發較多,不一樣的地區,不一樣的客戶對於同一個功能的理解能夠千差萬別。即便是產品銷售也一樣面對相對強勢的無可避免的增長一些個性化功能。程序員
長期以來,公司事業部研發指望統一代碼版本的願望與具體各個項目之間個性化需求致使的代碼變動(數據庫結構變動)之間矛盾越演愈烈。最終造成了底層框架儘可能不改,新增功能經過擴展來改,業務相關沉澱到前端或數據庫函數(視圖,存儲過程)去改的微妙平衡。spring
可是這個平衡是很脆弱的,有較大的風險。數據庫
如上所述,對於代碼版本控制的討論在咱們公司已經舉行了不少次,絕大多數討論都是從管理層面出發,聚焦於代碼權限控制,代碼分支控制等等。今天我想從技術角度談一談代碼版本控制。安全
從技術角度怎麼作代碼版本控制?如何解決通用版本與各個地區相同功能不一樣表現形式之間的代碼衝突?其實C#的asp.net框架和Java的spring框架已經告訴了咱們答案:基於接口開發。架構
就拿日誌來講,不管是asp.net仍是spring都爲咱們提供了官方默認的日誌類,可是若是這些日誌類沒法知足咱們的需求怎麼辦?咱們徹底能夠基於官方接口本身實現一個特殊的,基於個性化業務需求的日誌類,而後把這個獨一無二的日誌類經過依賴注入註冊到框架中,替換和接管原來的通用日誌類。核心框架內部由於所有是基於接口實現的操做,因此什麼都不須要修改。而實現這一點最關鍵的一步就是核心框架中,不一樣的組件之間,不一樣的類之間經過LoggerFactory生成的ILogger去執行日誌記錄,而具體到底使用官方的通用日誌類實現ILogger仍是第三方的特殊日誌框架如Log4都無所謂。
經過這種方式,asp.net和spring作到了核心框架和業務代碼的剝離以及各自的獨立發展。簡略的架構描述以下:
回到咱們的天然資源以及自身的產品(至少我目前瞭解到的政務,不動產登記以及權籍系統),爲何感受代碼版本控制很難,本質上是將通用業務模塊與框架牢牢的耦合在一塊兒了。簡略的架構描述以下:
框架
這種架構的優勢是:框架即產品,開箱即用。它的缺點也很是明顯:只要是和具體業務相關的改動都很不靈活(包括業務代碼,甚至包括部分工做流代碼),而且地區擴展中的代碼只能擴展全新的方法,一旦設計到舊方法的改造,仍是隻能回來修改框架,而爲了減小對框架的污染只能依賴關鍵核心員工修改,效率較低,響應也不快。
對於改造工做量,我認爲無需擔憂,要想使用這種模式來控制版本控制,也不是必定要全面的重構代碼,大動干戈的改造,咱們徹底能夠一個模塊一個模塊的逐步的進行改造。
以不動產農房改造的戶籍信息爲例:
最初的農房批量生成附記由於邏輯相對複雜,沒有按照管理在前端或數據庫完成,而是寫在了核心代碼庫BDC2的HjxxDomainService領域類中。
asp.net
可是批量附記屬於業務性很是強的內容,每個地區的不動產可能都有本身的要求,如衡陽提出要求在家庭成員下添加預編不動產單元號,房屋來源等等內容。這些內容的數據庫字段甚至是衡陽特有的,根本沒法在通用版本里面直接添加 。
遇到這種狀況,要求衡陽本身經過擴展另外重寫一套批量生成附記進而致使有兩套極其相似的大段代碼,要麼經過核心程序員在通用版本中增長很是麻煩的版本判斷分支語句。不論採用哪種方式都很是不利於代碼的版本控制和維護。
若是咱們採用先前描述的框架對應接口,附帶一個通用實現,不一樣地區有本身的對應實現,那麼咱們就能夠簡單的經過增長類文件的形式完成衡陽修改。甚至在個性化類還在利用大部分通用類方法時能夠引入一個通用方法代替實現。粗略架構圖以下:函數
具體到農房批量生成附記,UML類圖改造以下:
優化
核心代碼改造點以下:
將外部控制器要操做的核心領域類從通用的HjxxDomainService,修改成抽象的AbstractHjxxDomainService。
HengyangHjxxDoMainService經過通用的CommonHjxxDomainService實現無需特殊化處理的方法,減小重複代碼。
CommonHjxxDomainService(原HjxxDomainService)繼承AbstractHjxxDomainService和IplGenerateFj(視狀況複雜度能夠不要),其他不作修改。
在AbstractHjxxDomainService中增長一個具體實現工廠(後期能夠優化成依賴注入的形式)
外部控制器中涉及到農房批量註記時將前端傳入的方法名傳入工廠,調用生成對應業務類並執行動做
經過以上5步改造,咱們就不動產的農房業務的戶籍信息領域模塊單獨拆分了一套通用版本和一套衡陽版本,其中衡陽版本除了批量生成附記,其餘模塊本質上仍是用的通用版本方法,只不過已經具有了繼續擴展獨立的可能性。改動量小,安全,且切實可行的可以解決版本控制問題。由於既然可以拆分紅單獨的文件,那麼必定能夠繼續拆分紅單獨的動態庫,而後在工廠方法中經過反射的方式動態尋找,加載和綁定。
遇到全新的方法時,咱們也能夠從容的選擇多種方式,若是是在現有工程中修改,則修改抽象類(接口),而後首先實現通用版本,對其餘地區版本直接調用通用版本方法。固然這樣對代碼破壞性比較大,咱們徹底能夠不要改動現有類庫中的抽象類和接口,經過擴展的方式在原類上增長新的方法和接口(以C#語言爲例)。