2014年總結——協作篇

  2014年,技術外的事情比技術內有更多波瀾。


  年初,項目從零開始,團隊也是由五湖四海拉來的一幫人組成;策劃對ARPG沒多少概念,美術對移動端斜45度視角沒多少經驗,程序和美術對Unity 3D則都不熟。這是最難熬的一個階段,持續了大半年。

 


(一)  程序和美術/策劃的協作


  項目剛開始的時候,可以感覺出與我合作的策劃與美術都很想將產品做成精品。他們時常在琢磨,不時會提一些很炫的點子,希望我能實現。不過一方面大家從未磨合過,策劃與美術可能喫不準程序能實現到什麼程度;另一方面,可能很多第一次直接與程序合作的設計者會高估程序的實現能力或低估一些設計的實現難度,並且過早將精力放在了許多細枝末節上。這樣一來,作爲客戶端新手的我有時就比較悲催。爲了贏得夥伴的信任,我只好拼上自己幾乎所有能用的時間精力,身心接近透支狀態——Trust is earned。


  後來我和主管UI的美術同事聊過幾次。他也提到,剛開始合作時確實不知道程序的實現和承受能力如何,所以的確也是在試探。對於這個想法,我大致還是認可的,尤其在項目初期階段,什麼都沒有的情況下使勁做加法未嘗不是好的做法,這樣可以在項目內樹立起產品設計上的高度或標杆。


  不過當項目進入後期,程序的精力要逐漸轉到程序健壯性和運行效率的時候,我就不太希望策劃和美術還會提出超越我既有經驗、需要我花很多精力在前端表現上的需求。還好UI美術總體上還是比較配合,而且下半年有一位經驗豐富老練的系統策劃加入項目,並在後來成爲主策,很大程度上解決了UI美術和程序之間的協作問題。協調能力真是衡量策劃價值的重要指標。


  說起美術和程序之間的協作問題,技術篇總結已經提到,手遊對前端技術的更高要求,引發了程序和美術之間的更多博弈甚至衝突。這裏的協作問題主要有兩點:一是很多純美術表現的工作要靠程序實現,程序要花很多精力在表現上,而非邏輯和技術上;二是手機性能有限,能承載的資源有限,但美術追求表現的話往往要堆資源,因此對程序優化的要求極高。這兩點合在一起共同增加了程序的複雜度。


  對於第一點,我很贊同《一像素的恩怨情仇》這篇文章的觀點。我覺得在人手不夠充足、工具不夠強大的情況下,程序和美術相互之間都需要適當關注瞭解下對方的工作,不要太在意職業之間的界限,讓溝通和理解更加緊密順暢,這樣才能讓好的產品落地。加之項目初期時,出於好奇心和學習的目的,我是很願意將精力投入到純表現的實現工作中的;甚至會樂意在一段時間內放下代碼,在編輯器中鑽研各個參數的含義,摸索一些設計的實現方法,甚至偶爾會自己替美術構思一些細節設計。當然要項目中的每個程序和美術都這樣“複合型”畢竟不現實,也不見得好,畢竟術業有專攻。一方面不是每個程序員都願意花很多心思在編輯器裏“繡花”;另一方面美術理解Unity和NGUI中各個組件和參數的作用也比較喫力。不過幸運的是,我們的程序員對拼界面調錶現倒也不算很排斥;UI美術中萬幸也有一位願意學習,並且比大多數美術更能理解邏輯與參數的同事;策劃也有分擔此類工作的意願,大家在這件事情上總體還是比較積極,像《一像素的恩怨情仇》裏提到的開發不願意幫設計調像素的情形基本沒有;再加上我半年多的鑽研也算是爲中後期全民做UI做了些技術和方法上的積累。到了下半年,美術、策劃和測試大都能理解Tween、深度、圖集之類的概念。美術對實現有一定了解後,做出的設計也稍稍地不會那麼天馬行空難以落地。我們也沒有爲“UI表現是誰的分內事”這種問題產生過多少爭執——美術可以做的,就讓美術做,或者策劃調;需要代碼控制的,就由程序做;模棱兩可的,就看大家的喜好和精力,比如有的程序員更喜歡由代碼控制一切,那就都交給程序。不知是否有些敏捷的味道。


  在第二點,即性能問題上,我們程序和美術之間更是爲此PK過多次。年初程序根據一些試驗和推測制定了一些美術規範,可是常被美術忽視。從美術的角度講,資源總是越多越好——模型面數越多越好,貼圖越精細越好,粒子發射器越多越好。這樣品質會更高,美術效果會更好(說到這裏,我也是到2014年才真正理解了爲什麼很多時候外行覺得一款遊戲畫面太爛,其實是美術資源的緣故而不是引擎技術的緣故)。但是資源多則程序性能壓力大。當然在這個問題上程序一般還是先從自己身上找原因,儘量在不減資源不影響體驗的前提下優化程序性能。當程序扛不住,需要美術減資源或策劃改設計的時候,事情往往就要捅到主策主程主美甚至製作人的層面了,這時程序往往要拿出足夠有信服力的證據讓美術妥協。目前爲止UI方面經歷過五次大規模性能優化,其中只有兩次是程序扛不住要美術減資源——貼圖精度從2048降到1440,又從1440降到1024。基本上每週做版本,性能指標都是快要爆表接近閃退臨界值的節奏。我想我可以單獨寫一篇文章總結2014年我們做的UI性能優化。


 

(二)  程序員之間的協作


  程序和美術之間會碰撞,程序和策劃之間會碰撞,程序和程序之間也會碰撞。如果說程序和美術、策劃之間的碰撞是因爲各自的立場和角度不同,那麼程序與程序之間的碰撞則更多來源於每個人的習慣、思維方式和在意的事情不同。


  在命名風格上,有的程序員習慣linux的小寫下劃線風格,有的程序員習慣C#或Java的駝峯法,甚至有程序員習慣駝峯加下劃線風格(比如Function_Name)。在排版上,有的程序員習慣加空格與換行,讓排版空一點;有的程序員習慣空格與換行都不加,全部擠在一起。在大半年的時間內,程序內部都沒有編碼規範,框架方面也沒有規劃,基本上都是憑着感覺和各人自己的習慣寫,代碼風格眼花繚亂,頗有各自爲戰的感覺。對此我只能在動到別人代碼的時候,看看已有代碼是什麼風格,然後與已有風格保持一致;而UI代碼因爲時常使用NGUI接口,所以就用NGUI風格;如果有人要動UI代碼的話,我會跟他提一下(雖然對方也不一定會嚴格遵守)。還好接近年末的時候,在一輪人事變動和崗位調整之後,主程終於決定嚴抓代碼風格,大家終於統一起來。


  比代碼風格不統一更考驗心智的是思路的不同。其實如果僅僅是交流討論,百家爭鳴,那事情還是好辦很多。但當大家要落地做事,而且事情跟我的工作相關,和我的代碼有交集時,我就不那麼容易淡定了。一般當同事想實施某個方案,而你又覺得不妥時,僅從代碼設計或策略的角度來討論是基本不可能說服對方停手的。有一次UI性能優化,負責引擎與工具的客戶端同事打算改動NGUI內部,使優化效果更徹底;而我基於謹慎少出bug的考慮,認爲我們畢竟不是NGUI的作者,並不清楚NGUI在某些地方採用低效率做法的真正原因,而且這位同事很多時候做事情也不太仔細,因此我主張在使用層面進行優化,繞開NGUI內部的低效率邏輯。後來還是隨了他,果然改動之後出了很多bug。不過本着“有bug就修”的態度,這些bug還是一個個逐漸被修掉了。雖然現在在使用上還有一點瑕疵,並且有些bug甚至是經過幾個月並讓我花了很多精力才揪出來的,但同事的優化現在看來已經沒什麼問題。


  所以平常吐槽歸吐槽,同事身上有缺點也歸有缺點(誰又沒缺點?),但當技術方案有碰撞時,除非能明確指出對方方案中存在的邏輯漏洞或複雜度過大的地方,否則即便他要動的是我的代碼,即便我在審美上不喜歡對方的方案,我也不應該輕易否定對方的方案。我又怎麼知道自己的方案就一定更優呢?因此,雖然好些程序員會以“感覺怪怪的”表示他們對一些技術方案的看法(包括剛纔提到的那位同事,有次爲了實現界面中的一個小效果而再次改動NGUI內部,而對我提出的簡單調整一下節點關係的方案提出“感覺怪怪的”),但我告誡自己不要這樣看待其他人的方案。人一般總有思維定勢,不符合自己思維習慣的思路在自己看來總有不順眼的感覺。這時如果能放下有色眼鏡,心平氣和地分析呈現在眼前的新方案——無論它結果是好是壞,思路都會更開闊一些。


  其實如果對方的方案真的有問題,而自己又喫不準的時候,也不必過於糾結。如果對方堅持,那就隨了對方,也算是作爲試錯的手段。如果真的有問題,大家自會抱怨,屆時可拿出最初提出的各種方案重新分析,也會有新的觀點。項目初期時曾有一位從其它行業跳來的老程序員與我一起寫UI。出於對其資歷的尊重,我曾將一些較底層的東西交給他寫。但可能是他在以往工作中積累的思路定勢的緣故,他寫出來的很多邏輯在我看來都頗有過度設計的嫌疑,不易維護且容易出錯。他離職後,留下的模塊要麼被策劃廢棄,要麼在衆人的吐槽和主程的同意之下,被我用更簡單的邏輯重寫了。

 

  正好此時工作室中的另一個項目因爲採用了過多的面向對象風格,每添加一道業務流程都要新定義好些類,註冊很多的回調,讓人甚覺麻煩,所以也多次被吐槽。由此我也總結出,簡單明瞭、易於理解、集中式管理的邏輯一般都受到衆人的歡迎;非到十分必要的時候,不要隨意採用虛函數、回調等會讓邏輯分散在各地的濃厚的面向對象式做法。這讓我想起了以往和師兄合作寫Java軟件的時候,我不時會大力重構他的過程式代碼,將大段邏輯拆成一個個短小精悍的函數,並大量使用繼承、多態和回調,結果師兄常看不懂我改過之後的代碼,出bug的時候感覺無法下手頗爲着急。那時他說我有過度設計之嫌,我還有點不高興。現在看來當時真是給師兄添麻煩了。


  不過當然,產品上線運營之後就不能這樣大膽試錯了,一切改動就真的要謹慎又謹慎。

 

 

(三)  程序和測試的協作

 

  程序和測試之間當然也要打很多交道,不過一般不會碰撞。測試報bug,程序查bug修bug,天經地義。


  在老東家的時候,程序和測試在不同樓層,測試給程序報bug都是通過Mantis提單,郵件通知;單子會說明bug的重現步驟和優先級;程序可以根據優先級和自己手頭的工作自行決定什麼時候修什麼bug;程序和測試之間一般通過Lync和郵件溝通。


  可是現在的團隊裏,所有工種都混坐在一起,測試發現bug時會立刻抓程序來看。雖然我們有Redmine可用來提單,但測試因爲負擔太重,所以不一定每個bug都會提上去;就算提上去,測試一般也不會將重現步驟寫得那麼詳細,只是一兩句話記下有這麼個事而已,優先級更是沒有。可以說,非常“敏捷”。


  所以測試找我看bug之後,我都會第一時間先把這個bug記下來——一些可以秒修的bug就馬上修掉;不能秒修的,先記在自己的筆記裏;如果這個bug比較重要或比較難查,我會囑咐測試提單,並且測試提單後,我會在單子裏補充上重現方法;待修掉後,記下修復的版本,如果是比較難查的比較複雜的bug,再補充上bug原因和解決方案,對應的svn日誌裏也寫上。這樣時間久後,一旦遇到類似bug或是要追查一段代碼是爲了修復怎樣的bug時,就很容易查到。雖然現在團隊還沒有這方面的規範,其他同事也不會這麼幹,但我因爲從學生時代編程起就親身體會過這樣做的好處,所以仍然堅持着。


  優先級和即刻抓人修bug的問題,有時稍微讓我頭疼。編程思路被打斷倒是後話。但有時正在對本地代碼做大改動的過程中,突然來了一個緊急bug需要修復,這時就要小心維護區分改動中的代碼和用於修bug的代碼。以前在老東家用Perforce,我可以先將本地進行到一半的改動shelve到服務端,回退本地,然後開始修bug。但到了新東家用svn,處理起這個問題就比較麻煩。不過年末我開始用git管理本地版本,通過git分支基本解決了這個問題,方案比Perforce還好,在這方面也就不怕緊急bug出現了。


  一般在遊戲研發團隊裏,測試都是黑盒測試,並不懂代碼和實現原理。然而,我們的測試會審查代碼,瞭解一些功能的實現細節,寫測試腳本,實際能頂半個程序(當然這也進一步加重了測試的負擔)。這對程序來講真是益處良多。每當寫好一個系統或是一個比較重要的業務流程後,將代碼邏輯給測試講一遍。講的過程中,思路會越來越清楚,而且有時還沒講完,測試還沒反應過來,自己就會先發現有bug。這時測試同事就是小黃鴨調試法中的小黃鴨。有時測試會對某些功能的實現或對某段代碼好奇,作爲程序員也要能講清楚。說起來以前做學術時,我很擅長這方面的表達,將某個業務或複雜邏輯給人解釋清楚,甚至外行也能聽懂。但2014年我在這方面退步很厲害,甚至幾次闡述邏輯都被主程說“太繞太複雜”。想來如今的工作節奏不允許我花太多時間爲這種表達做充足準備(以前準備一份ppt都至少要花上一週,並且反覆預講),而如今我又常鑽進技術裏出不來,將沒有整理過的原始思路直接表達給別人聽,自然會讓別人聽得雲裏霧裏。

 

  有時測試會指出某段代碼的不嚴謹之處,甚至是不好維護之處,這時偶爾就會產生程序與測試之間的碰撞。當然這種碰撞的激烈程度是遠不及程序與程序之間以及程序與美術/策劃之間的碰撞的。有次測試在QQ羣裏吐槽進入副本的代碼邏輯太亂,相關程序對吐槽表示不爽,在QQ羣裏爭論起來了;最後程序還是整理了那段代碼,而且結果在我參與的起鬨和主程的安排下,程序和測試全體當晚到烤羊排店裏搓了一頓,吃了好幾條大羊腿,又拉近了團隊感情大笑


  因此和測試人員的協作可能是我在2014年經歷的最愉快的協作了(雖然被bug砸的本能感受確實不太好)。



(四)  常被打斷的節奏

 

  2014年我所經歷的團隊協作之緊密、節奏之快,是我以前從來沒有經歷過的。前面提到的所有工種混坐在一起,便是一個體現。不過讓我感受最深的,還是編程中常被打斷的節奏。打斷我的可能來自策劃/美術提需求;美術問工具方面的問題;其他程序員問接口或相關功能如何實現,或讓我幫忙查他們不太好查的bug;測試抓我看bug,或向我瞭解一些功能的實現細節。有時被一位同事叫走之後,回到座位上屁股還沒坐下,就立刻又被另一位同事叫走了。

 

  被打斷的第一反應是情緒上的不爽,誰也不喜歡一件事做得正high的時候被別人拽出來。其次還有恢復思路的問題。有時做事情A的時候,被打斷去做事情B,但做B的過程中又被打斷要去做事情C,這堆棧嵌套太深,恢復上下文就比較麻煩。不過思路的恢復對我來說還是小事,更重要的還是時間被佔用。有時候竟一上午全在被打斷的過程中,半天只寫了一行代碼——真的只有一行代碼!

 

  這當中,我曾對被其他程序員打斷有點介意。按照我以往的習慣,當我的工作需要涉及別人負責的模塊時,我一般會先自己翻翻代碼和文檔,儘量自己先摸熟,然後再問別人。這樣對項目代碼和相關技術的掌握也會更深刻。但是其他程序員不見得有這個耐心,遇到問題就問。不過後來我也想通了。一來不是每位程序員都有強求知慾,各人在意的事情也不一樣,因此不是每個人都會關心模塊內部的實現。二來,更重要的是,單純從完成任務的角度考慮,有問題就問人也會節省不少時間精力,人家需要將省下來的時間精力用來做其它任務;現在基本上每位程序員的工作負荷都是滿的,因此我不應該對人家這種做法有什麼想法;相反,如果明明是別人幾分鐘就可以交待清楚的邏輯,我卻花了太多時間自己摸索,反而有不知輕重緩急、影響工作進度之嫌。所以後來在我自己遇到問題時,我也會根據情況主動打斷別人問問題。

 

  我曾就被打斷的問題請教過主程和老東家的領導,他們均表示這是國內的常態,需要克服自己情緒去適應。這樣也能鍛煉出記憶需求和思路的能力。另外,實現功能時不要過於糾結方案是否完善;先寫,把功能實現出來,以後再完善;在寫的過程中思路也會越來越清晰。糾結於我而言是個大問題,我會另寫文章總結。

 

  雖然我讀過好些文章論述程序員被打斷的代價,但理想很豐滿,現實很骨感。在一個初創且快速迭代的項目和團隊裏,很多我從文字資料中讀到的軟件工程觀點都不再適用。

 

  的確被打斷的節奏在項目中前期尤其明顯。項目進入後期,隨着大家對項目相關的工具、代碼和技術逐漸熟悉,隨着各人崗位逐漸固化,隨着各個模塊逐漸穩定,被打斷的節奏也就不那麼頻繁了。不過預計項目上線後,這個節奏又會緊張起來,而且到時候被打斷的就不僅僅是編程過程了,休假也會被打斷。

 


  這是我第一次用這麼長的篇幅寫純協作方面的事情,看來2014對我來說真是紛亂而不平靜的一年。協作過程中發生了很多人與人之間的碰撞和摩擦,我需要直面同事之間思維、觀念和做事風格的不同。儘管我對這一切都有心理準備,但當我真正面對它們的時候,還是會有很多意外和失落,甚至可能會給同事添堵。因此這一年的心境比起前兩年也是格外不平靜。一年下來,有不少人離去,也有不少人進來,大多數人還是堅持了下來,彼此的磨合越來越順,項目也終究有了走上正軌的感覺。我很欣慰可以跟着項目從最初走到現在,切身體驗了整個過程。不過,事情還沒完。2015,繼續期待。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章