我在中興軟創這9年

>>>  小城故事吳儂軟語溫婉人心的力量  >>> 簡體     傳統

 一個月前離開呆了 9 年的中興軟創,有不少東西值得寫下來,千頭萬緒,不知從何寫起,自己留下了 10 多萬字的回憶,但這里面涉及的東西太多,不便公開,還是把這些年對工作的感悟寫一下吧,這 9 年的工作基本都是圍繞前端框架的。

  中興軟創的主要業務稱為 BOSS,也就是電信行業的運營支撐軟件。早期的 BOSS 系統一般都不是 Web 化的,而是C/S架構,當時大家做所謂的“前端”,用的是 Delphi,C++ Builder,或者 Java Swing。后來B/S流行之后,大家就逐漸往瀏覽器上遷移。

  那個時期的瀏覽器,不像現在這么多樣化,一般指的都是 IE,而且可以具體到三個版本,5.0,5.5,6.0。第一批遷移到B/S模式的系統,多半是那些簡單表單的系統,界面只是填值,作個簡單校驗,然后提交給服務器。可以說,這個時候的 Web 前端是很乏味的,因為沒什么可做的,用 table 布局,里面放些 form,極少量的 JavaScript 代碼,更談不上用 CSS。

  不久,Web 系統就復雜化了,在C/S里面,我們可能有大量的“控件”可用,基本的輸入框這些不談,在 HTML 里也有,時間日期這類,就要費些周折了,更復雜的,比如 Tree,DataGrid,甚至 TreeGrid,就更折騰。當時寫 JavaScript 的人還是有不少的,面對這種情況,也想出了一些辦法。

  這些辦法的根本原理,都是用已有的 HTML 來拼湊出一個控件的樣子,再加上事件,一直到現在也沒有更好的辦法。比如說,日歷,就用 table 標簽來生成一個表格,然后當前日期加個顏色。又比如 DataGrid,也是一個表格,然后 tr 上面加點擊事件。有的流派是跟現在一樣,把控件的聲明和初始化都放在 JavaScript 代碼中,只在 HTML 里留一個容器標識,更主流的方式是用 HTC 來封裝控件。

  如果仔細看過早期 ASP.net 的代碼,就會發現它帶了幾個 htc 文件,比如 treelist,tabstrip,multiview 等等,這些控件的功能已經基本能滿足需要了,就是有些丑,有些人在此基礎上作美化,04 年的時候,中興軟創的多數基礎控件就是這么來的。HTC 提供了一種擴展 HTML 標簽的機制,業務開發人員用起來很方便,所以很有效地降低了開發門檻。

  再看另外一個方面,傳輸的問題。最開始大家都是把數據用 submit 按鈕提交給服務端的,但是提交就會刷新整頁,效果不好。我們知道,AJAX 的概念是 05 年提出的,但是在此之前好幾年,就有不少用 XMLHTTP 的人了,我自己入職之前,03 年的時候,就用過這個,入職之后看公司的前端框架,也一眼發現了這些東西。中興軟創的這套傳輸機制是在微軟顧問的幫助下創建的,傳輸的原理就是在前端把表單數據序列化成 XML,通過 XMLHTTP 傳給后端的 Servlet,當然,那時候用的是同步傳輸,傳的時候界面會卡一會。

  05 年我剛入職的時候,還沒看過系統,老大問我對前端這塊有什么看法,我說可以考慮做組件化,把更多的東西封裝成 HTC 那樣的組件,然后組件內部通過 XMLHTTP 跟服務端通信,他聽了之后說我們現在已經有一些 HTC 控件,通信也基本都是 XMLHTTP 了。回想起來,當時我的思路是縱向的組件,端到端,每個組件實際上只通過事件和方法與其他組件交互,各組件自身就可以獨立運行,應該算是早期前端組件化的一種思路。

  為了通用性,前端封裝了一個方法叫 callRemoteFunction,三個參數,分別是后端的 Java 類名,方法名和參數對象,用 XMLHTTP 發送到后端的 Servlet 之后,通過前兩者反射得到對應的 Java 方法,執行結果再返回給前端。這樣,在 JavaScript 里“調用”后端代碼,就像調用普通的 JS 函數那么方便。也有這樣調用動態 SQL 的,后來這兩者統一成服務,只要傳入唯一的服務名和參數,不用管是 Java 服務還是 SQL 服務。

  有了這些東西做保障,業務系統的B/S化就容易多了。當時的開發模式是前后端分離,后端負責寫服務,前端寫界面和 JavaScript,這種模式也帶來很多好處,比如有的業務系統后端從 .net 遷移到 Java,前端部分基本除了登錄之類,都沒什么要改動的,人員的協作也是很順暢的。

  在遷移系統的過程中,也有其他一些混雜技術,比如說,處理一些監控圖形之類的,由于缺乏經驗,加之為了重用之前的 Swing 代碼,搞了一些 Applet,雖然混搭的風格不太好看,但當時是沒什么人講究這個的,業務系統能用就行了。因為我入職之前搞過 VML,所以極力鼓動把各種圖形的東西搞成 VML,這個東西在當時最大的優點是不需要給瀏覽器安裝插件,其他任何方式都做不到。

  后來就有了 IOM 系統那個很典型的自動布局流程建模界面,核心部分有 3k 多行 JS,花了近 2 個月,期間還重構過一次,后來陸續改需求,到 06 年下半年才不太改動了。從此之后,公司的 Web 圖形這塊,基本都是用 VML,不再有人提 Applet 的事了,而且幾年內也沒有用 Flash 做這類圖形的,據我所知,業界當時用 Flash 做圖形界面比用 VML 的還多些。

  到了 07 年,Firefox 就占不小的市場比例了,而且 HTC 這個東西,微軟自己也不太看好,所以不得不未雨綢繆,考慮這些東西的替代方案。正好當時調動部門,新部門打算徹底翻新產品,所以有機會考慮前端的新方案。作為前端的整合框架,有兩條道路可走,一條就是選擇別人的方案,比如早一點的 Bindows,還有當時比較火的 ExtJS,另一條就是先引入一個 JavaScript 基礎庫,然后在上面自己做控件。經過慎重考慮,還是選了后者,因為我們的業務需求比較復雜,改控件的情況很多,要是用了 ExtJS 這類,雖然看起來什么都有,但是改東西估計就痛苦了。

  接下來就是選基礎庫了,流行的有 Prototype,Mootools,jQuery,甚至還有萬常華的 JSVM,在那個時候其實很難預料到后面 jQuery 這么火,就算到現在我也不能理解,所以我們的選擇是 Prototype,然后在它基礎上構建外圍庫,主要是控件。

  當時看過很多 UI 庫的機制,比較來比較去,覺得最能接受的還是 YUI 的方式,所以大致按照這種方式做下去了。我們的控件體系是比較松散的,彼此之間無任何依賴關系,可以獨立引用,控件的唯一參數就是父容器,然后傳入初始化參數,加載數據之類。

  這一代控件的 DataGrid 和 TreeGrid 是我做的,跟上一代最大的區別是簡化了事件。比如說,之前的控件選中行用的是點擊,但是鍵盤的方向鍵也可以改變選中行啊,這時候業務方需要監聽控件的兩種事件,在每種里面都做選中行變更的操作。這一代里面我只給業務方開放 change 事件,不管實際是從什么事件發起的,最終需要關注的只是這個 change,在控件上,行的點擊事件這種過于原始的事件是沒有意義的,直接拋給業務方非常不合適。剛開始改成 change 的時候,有些業務開發人員不太習慣,不過很快就覺得這樣方便了。

  這一代的 TreeGrid 控件我作了懶加載,但實現的細節上有些考慮不周了,比如說,下層節點在未展開的時候,DOM 不創建,這沒有問題,但是我連節點對象都沒創建,當業務方要訪問未展開的節點數據時,只能從數據源上去獲取,已展開的節點和未展開節點的訪問方式不同,這算是一個敗筆。

  整體來說,這一代的框架運作還是很成功的,比較穩定,但整個版本關鍵的一點沒有達到,就是跨瀏覽器,也就是說,即使把控件代碼改成純 JS 的,也沒讓整個版本跨瀏覽器,這很悲劇。一個關鍵問題是版本時間太緊,框架層從無到有三個月之后,業務側就大量啟動開發,有不少問題沒有來得及解決,更本質的問題在于當時我們缺乏經驗,沒有對業務開發人員作約束,比如說,有些要避免的寫法沒有列出,對于跨瀏覽器怎樣測試,也沒有時間作考慮。等到打算解決這些問題的時候,面對海量的業務代碼,已經無從下手了。

  這個版本中,也遇到一些比較新的需求,比如說有的監控需求,要實時通信,那時候沒有 WebSocket 可用,就用 Flash 的 Socket,搞了一個不顯示的 Flash,專門用來連 Socket,然后再用 JS 跟它交互,效果還可以,只是因為 Flash 的跨域策略升級過幾次,導致踩了一些坑。

  說到這個 Flash,又扯到另外一些話題,早期搞前端的人,多數都玩過它。Flash 內置一些控件,比如基本表單輸入,還有調用 WSDL 格式 WebService 的通信控件,整個體系其實成熟度不比 HTML 低,只是我一直對時間軸很痛恨,所以即使搞,也都傾向直接用 AS 寫,很少用元件轉 MovieClip 那些東西。后來 2004 年推出的 Flex1.0,徹底不一樣了,我研究過一陣,也想過如果在企業應用領域,全部用它來構建前端如何?

  這個想法是有些激進,但對于企業應用而言并不過分,企業應用連 Applet 都能接受,機器上要裝 10 多M的 JRE,那用 1M 多的 FlashPlayer 不是更好嘛,而且當時很多開發人員寫不好 JS,尤其是代碼規模較大的時候,但他們寫 Java 都還湊合,如果用 AS 來寫,代碼效果應該好不少。

  當時的 Flex 是要部署到應用服務器里的,運行機制大致就像 JSP 那樣,文本代碼經過一個預編譯,然后發到瀏覽器端來執行。當時制約 Flex 發展的主要因素是客戶端機器的配置,Flash 體系的界面效果較好,但比較占資源,而且在開發階段的優勢也體現不出來。

  但我一直認為,Flex 體系在較大一個時間段中很適合企業應用體系,因為瀏覽器混戰的時期很長,亂象環生,老的瀏覽器遲遲不去,多少年也抹不平兼容的坎。對企業應用而言,搞跨瀏覽器兼容這方面并非它的核心價值,如果有一種技術能暫時抹平這些瀏覽器的差異,優勢會是很明顯的。要說占資源大,難道 ExtJS 占資源就小了?企業應用連 ExtJS 都可以接受,當然更能接受 Flex。

  所以從 09 年開始,又逐步進行 Flex 的引進,當時的 Flex 發展到了 3.0,整體算是比較成熟了,后來陸續花了兩年時間支撐業務產品的開發,效果還可以,但從引入時機來說,還是略有些晚,如果再早兩年引入,狀況會更好一些。

  另外一方面,BOSS 領域的應用系統并不局限于企業應用類,也有一些是面向個人用戶的,比如說自服務和網上商城,前者類似 10086.cn 那種模式,個人消費者可以登錄辦理一些簡單業務,后者就是典型的網店,只是所賣的限于電信類的實體商品(手機、上網卡等)或者虛擬商品(套餐,流量)等。

  這個場景跟之前的內網應用大有不同,算是真正的互聯網模式了,所以它所用的前端框架就與其他的不同。由于精力所限,開始幾年在這方面的投入很少,一般都是用 jQuery 外加一些開源的控件,這樣整合起來用,頁面不花哨也不復雜,基本功能也是能夠滿足的,做的效果只能算是湊合,主要是沒有熟悉 CSS 的人。

  在做電信業務運營支撐的這類公司,UI 一直是薄弱環節,不可能得到本質上的重視。整個中興的整個體系里,軟件的重視程度并不如硬件,比如從手機上面就看得出來,賣了手機之后就不太重視后續軟件升級了,還是賣老的功能機的思路。在軟件體系里面,前端也處于相對弱勢的地位,畢業生入職的時候,都會優先讓編程水平較高的做后端,在前端里面,邏輯和業務的重視度又高于 UI,所以 UI 保持能用就不錯了,在關鍵的一些跨瀏覽器兼容,CSS 規劃方面,基本是沒有什么進展的。好在近兩年,由于有了 BootStrap 這樣的東西,把很多原本要做的事情做掉了,所以只要對界面沒有特別的需求,光會寫 JS 也能把界面搞得像模像樣。

  這部分的前端框架,其實也不是這么搞就完事的,基于傳統的思維,做這些界面的時候,開發人員仍然傾向于使用偏重量級的控件,而不是使用界面模板庫等方式來做一些數據展示的效果,這一方面帶來的是觀感的不佳,另一方面,由于引用的一些控件庫沒有很精細地隔離,往往都是整套控件一起引入,甚至在一個界面里還出現同時引用多種界面庫的惡劣情形,一個并不算復雜的界面,引用的壓縮之后的文本代碼就高達1-2M 之多。

  所以從這個方面講,公司的多數前端人員并不專業,專業與不專業體現在什么地方?是要有一個整體的優化。前端與后端開發方式的一個本質差異是引入任何東西的代價都比較大,因為你的代碼要先經過一次網絡傳輸才能執行到,而且還要注意避免沖突。如果只要引用某個功能,就不應把其他不相關的東西也一起引入,所以那種一個大控件庫整體打包的方式在這種面向互聯網終端用戶的模式下非常不合適。這個道理并不難理解,但為什么操作的時候很少有人注意避免呢?

  因為兩個原因:

  • 精確控制的代價較大。這一點確實是個大問題,要做精確控制,最小依賴,需要把整個框架的依賴關系理清楚,在現有的開發體制下,誰為這個時間買單?既然沒有,那基本上就沒人管了。
  • 加載的字節量未作為系統上線的考核指標。從反面說,如果這么做了,功能倒是能用,但系統加載慢了,有多慢,這個沒有預設的性能底線,一般趕時間做的系統也都不會太糾結在這上面,能用了按時上線了就大家都謝天謝地。

  從決策層的觀念上,也有一個誤區,比如認為自服務類系統不算核心系統,對開發技能的要求也不會多高,湊合能用就行了,事實并非如此!企業應用型的系統,才是不特別考驗開發技能的,考驗的更多是架構水平,它在前端的坑并不多,所以完全可以由個別架構水平高的帶著一群偏弱點的開發人員做,而網站類的對每個開發人員的前端技能水準要求都更高,如果不改變以往的思維方式,后續這類系統會經常收到投訴。

  近兩年,因為要考慮未來老舊瀏覽器淘汰之后的事情,所以我花了不少時間研究了一些懶加載框架,還有一些前端 MV*框架,尤其在 AngularJS 上,花了很多精力,比如 12 年的時候打印了源碼來看,也做了各種嘗試。這些東西用在企業應用領域,是極好的。第一次看到 AngularJS,是因為當時在尋找通過 HTML 屬性實現數據綁定機制的方案,然后就看源碼,看同類方案,一發不可收拾。

  后來的規劃,是用它來實現核心邏輯,而外圍的 directive 層分為 PC 瀏覽器和移動終端兩類,這樣可以實現邏輯的共享。到了該考慮移動端的時候,又碰到了 Ionic,真是想什么來什么,也說明我的這些路不孤單,還有一些人用同樣的思路在走。

  之前公司也搞過移動端的系統,用了響應式設計,也碰到一些坑,從我的角度看,公司用響應式設計還是要慎重,因為完全沒有熟悉 CSS 的人,要用這個風險很大。

  近兩年考慮的另外一些事情是前端開發的工程化,這個路也不孤單,各大公司都或多或少的在做,比如前端組件的管理,自動化測試,發布等等,典型的有百度 FIS。當系統規模擴大的時候,在代碼管理和發布問題就特別多,前幾天看到 winter 的微博,應該也是踩到不少坑。。。所以說,架構師要考慮的事情,一方面是系統自身的架構,另一方面要考慮團隊在協同開發時候可能遇到的問題,從技術角度盡可能及早把這些東西化解。這方面花費的精力很可能比真正在產品里花的還多,而且是很痛苦的,做了很多之后還不容易看出作用。

  去年在上海一家公司面試的時候,跟面試官聊得非常投緣,他問一句我答一句,有時候他話沒說話我就接著說下句,我話沒說完他就接著說下去,最后兩個人相對大笑,那是發自內心的苦笑,前端架構這個大坑啊。他說,對吧,架構這事,比的就是你踩過多少坑,我們這一路上踩過來的坑,都是血和淚。我倆笑得像《投名狀》電影里,劉德華最后流著淚笑得樣子。

  碰到的另外一個聊得很投緣的人就是支付寶的玉伯,可能因為業務場景比較接近,而且大家的努力方向都在前端的工程化方面,所以很多東西都是所見略同。

  早些年,公司的前后端分離開發,效率很高,問題也少,不知為什么做著做著就成了不分的模式,開發人員從 HTML,JS,Java 一直寫到 SQL,什么都搞,什么都不專業,很可怕,我提了不知多少次意見,從未得到回應。雖然最近業界很多鼓吹全棧工程師的,但這只能讓那些個人能力較強的去做,作為補充,不能成為普遍做法,對于招聘人員水準比不上互聯網公司的傳統軟件商,更是應當把人員分工搞好,這樣才可能真正做好產品。

  過去的事情都過去了,回頭看看自己這些年,在工作上還是花了不少心思,每次有想法,都會說出來,哪里覺得不對,都會認真提出自己的理由。努力做一些與眾不同的事情,會寫一些工作方面的文章,會用業余時間組織培訓交流,會自己出錢買書送給同事。從未提出過讓自己團隊任何人加班,研發過程獎也從未給過自己一分錢。有時候真不知道自己的堅持是為了什么,努力過之后,發現能改變的東西還是太少,很失落。

  曾經是一個缺乏勇氣的人,下棋或者打游戲碰到形勢不好就立刻認輸,后來看我同學阿龍打星際,屢屢被人打得只剩一個農民還到處逃竄開礦企圖翻盤,看得多了,也就比以前肯堅持。人的一生,兩件事最重要,一是努力,二是選擇。這兩者都不容易,這次狠心選擇了新的道路,希望能堅持下去,不知道再有 9 年之后,會是什么樣?


網載 2014-03-16 20:59:37

[新一篇] 你為什么成不了技術大牛

[舊一篇] 程序員的人性思考(上)
回頂部
寫評論


評論集


暫無評論。

稱謂:

内容:

驗證:


返回列表