遊戲開發中的PvP:程式設計者 VS. 程式設計者

來談談 Programmers 與 Programmers 之間的合作關係。

一直到出了社會,經過幾年的工作歷練以後,我才深深地體會到以前在學校中大部分的課程作業與考試,往往太過於注重個人的程式能力,卻忽略了團隊合作的重要性。「一個人能夠將程式完成;一群人卻反而未必能將程式完成。」現今的大專院校設立了許許多多的資訊相關科系,但是對於有志朝向軟體相關產業發展的學生,卻很少有機會學習合作開發的相關知識,更缺乏與同學共同撰寫程式系統的實作經驗,實在是一件很令人惋惜的事情。

除了「《Top 10 Traits of a Rockstar Software Engineer》:明星程式設計師必備的十項特質」中所提到的十點必備特質以外,我認為對於程式設計者來說,最重要也最關鍵的特質就是溝通技巧協調能力。「溝通」以及「協調」,聽起來是再尋常也不過的普通字眼,有什麼重要性?又有誰做不到呢?在現實世界中,不會每件事情都如課本中的理論般,達到準確無誤的理想狀態。如果能夠與同儕間達成良好的溝通與協調,撰寫程式也會變得容易許多;反之,如果無法達到雙方都能接受認可的滿意狀態,將會造成許苦痛、誤解,甚至對立的情勢。

無論是正式的會議或非正式的會談,溝通的程序,經常會佔去許多工作上的時間。在《人月神話:軟體專案管理之道》中提到,當專案中的成員數目往上增加時,彼此之間的溝通成本也會相對地提高,達到門檻上線之後,增加成員就幾乎無法對專案產生任何正面效益了。而除了與企畫設計者、美術設計者以及專案管理者的溝通以外,許多程式設計者經常忽略的層面,反而是與程式部門的內部溝通程序

在遊戲專案的程式系統開發流程中,分工是必然為之的自然法則。在分工合作的開發模式下,通常會有一位主程式設計者 (Lead Programmer),負責撰寫最關鍵的主系統功能,並且整合其他所撰寫的子系統功能。主程式設計者通常是由部門中最資深的程式設計者擔任,而部門內其他的程式設計者,則會分別負責使用者介面系統、人物系統、場景系統,以及特效系統等等不同項目的子系統。

由於遊戲專案中的程式碼檔案往往成千上百,同時也會隨著專案的進展而不斷演化成長。因此不可能等到程式設計者全然瞭解專案中所有的程式碼以後,才開始動手撰寫新的程式功能。在這樣的情境之下,缺乏部門內的溝通協調,就會造成糟糕的後果。舉一個常見的例子,假設在開發中的 MMO 遊戲專案裡,具備 5 種角色職業可供玩家選擇。對於負責開發角色系統的程式設計者來說,很自然地會利用列舉值定義的方式,撰寫出以下的程式碼:

// @ file Character.h
enum CharacterCareer
{
    Career_Warrior,
    Career_Rogue,
    Career_Priest,
    Career_Witch,
    Career_Paladin,
};

class Character
{
    // My super character class!
};

有了 CharacterCareer 列舉值的定義之後,就能夠在 Character 類別以及與角色系統相關的程式碼中使用 switch-case 敘述句,很便利地對不同的角色職業進行個別處理。

然而,專案中的另外一位程式設計者,負責撰寫使用者介面系統的功能項目,同樣也會需要對各種不同的角色職業進行個別處理。在缺乏內部溝通,同時也沒有檢視過人物系統程式碼的狀況下,很可能會寫出這樣的程式碼:

// @ file CharacterUI.h
enum CareerUI
{
    UI_Warrior,
    UI_Rogue,
    UI_Priest,
    UI_Witch,
    UI_Paladin,
};

class CharacterUI
{
    // This is CharacterUI!!!!!
};

一項是定義在 Character.h 中的 CharacterCareer 列舉值,另一項則是定義在 CharacterUI.h 中的 CareerUI 列舉值,其實兩者的用意完全相同。如此一來,遊戲專案就需要同時維護兩份功能作用相同、定義名稱略有不同的程式碼。如果又有第三位程式設計者,負責製作與公會或組隊相關的系統功能,可能又會出現第三種版本的角色職業列舉值。像這樣重複性的程式碼,非常容易導致系統維護上的陷阱與潛在的問題。

如果這兩位程式設計者,能夠在下手撰寫程式之前,多考慮一點其他的可能性,或者向部門內的同儕稍事詢問,就能夠將這種各子系統都需要使用的列舉值定義,獨立出來寫在一個表頭檔中,就能夠讓任何需要的系統自行取用,而不會再寫出重複多餘的程式碼。假設部門內的其他程式設計者,目前並沒有撰寫角色職業相關的列舉值,經過詢問之後,也能確保在他以後有需求時,會先想到你曾經寫過這部份的程式碼,因而降低了撰寫重複程式碼的可能性。

上述的案例,其實只是最旁枝末節、影響最微不足道的情節。在程式設計者的真實世界中,經常會遭遇更感人肺腑或者賺人熱淚的情景。例如,在人物系統中存在著一個名為 CSingleton 的類別,而在特效系統中又存在著另一個叫 Singleton 的類別,兩個類別的功能用途幾乎完全相同;或者是 70% 的功能相同,30% 的功能不同的類別或函式等等,多到不勝枚舉的狀況。在撰寫一項獨立的功能之前,只要事先詢問同儕是否有撰寫過功能相同或相似的程式碼,就能夠避免產生出重複的程式碼。正如「明星程式設計師必備的十項特質」中的項目所述:善用既存的程式碼;所謂的既存程式碼,理所當然也包含同儕所寫的程式碼!

另一方面,如果以子系統程式設計者的角度出發,由於最終的子系統成品都要交付給主程式設計者進行整合,所以子系統程式設計者應當要將主程式設計者視為客戶的角色,主動去瞭解使用層面的需求,才能夠讓整合與維護的程序更加順遂。在理想狀態中,主程式設計者應該不需要去探究子系統的實作細節,而只需閱讀類別介面與系統的設計文件,就能夠完善地使用這些已完成的子系統組件。

因此為了建立雙方都能夠認可的子系統溝通介面,在子系統與主系統程式設計者之間,可以使用 Design by Contract(依合約設計)的方式進行系統規劃與設計。所謂的 Design by Contract,就是如同契約般白紙黑字的設計模式;兩人事先約定好,只要你能夠給我 A、B 與 C 的參數值,我就可以保證輸出 X、Y 與 Z 的結果給你。以特效系統為例:

特效系統函式契約

函式用途:創建特效物件
函式名稱:CreateEffect

參數 1:std::string 型別,指定特效的檔案名稱。
參數 2:Vector3 型別,設定特效播放的座標。
參數 3:bool 型別,設定特效是否循環播放。
回傳值:Effect* 型別,創建的特效物件指標。

注意事項:特效物件使用完畢後,需要交回特效系統進行回收與毀滅的行為,不可自行使用 delete operator 刪除。

依照契約般的合作方式,不僅能夠使主程式設計者事先考慮子系統的 Use Case(使用案例),相對地也會使子系統程式設計者得到更明確的設計需求規格。主程式設計者不能總是做個善心人士,不論子系統程式設計者交出什麼長相的程式介面一律照單全收,導致原來只要 1 個函式就可以解決的功能程序,卻需要拐好幾個彎,多使用 3 個函式呼叫才能完成。所謂兵來將擋、水來土淹的作法,並不適合用於這樣的開發情境中。

溝通,並不僅止於以「語言」的形式進行。有時候,甚至存在著更微妙的溝通形式。

為了建立起程式部門內部的有效溝通管道,更有效的一項方法是採用 Code Review(程式碼檢閱)的程序。根據 Wikipedia 的定義,Code Review 是一種系統化的程式碼審閱方法,能夠用來早期發現且早期治療錯誤,增進整體的軟體品質以及開發者的技能。Code Review 有正式與非正式等許多不同的形式,簡單來說,就是將程式碼交由撰寫者以外的人進行檢閱與審核。一般的 Code Review 程序,經常是由資深的程式設計者檢視新手撰寫的程式碼,並且給予適當的指正與引導。這樣的方法,一來能夠協助新手更迅速地進入專案的狀態中,二來也能夠避免新手犯下無心之過,而對專案造成難以彌補的慘劇。

但是這樣一對一的 Code Review 程序,並不能夠完全發揮最佳的溝通作用。事實上,如果能夠訂立出週期性的 Code Review 程序,使程式部門中的所有人共同參與,不僅能夠集眾人的智慧找出程式碼中潛在的問題與臭蟲,同時也很有利於統一專案程式碼中的寫作風格與命名慣例。然而,在專案時程緊迫,每個人總有做不完的功能與除不完的蟲的情況下,Code Review 會花費許多額外的時間,目的只是為了檢視已經完成的程式碼,這樣做值得嗎?

撰寫程式碼的時間減少了,檢閱別人的程式碼以及溝通協調提問的時間增加了,反而能夠使程式系統更加穩固,有效降低後續除錯與維護所需的心力,因此實行 Code Review 實際上並不會延宕專案的時程。參與檢閱的程式設計者,能夠以很短的時間瞭解其他同儕撰寫的功能系統,而對於被檢閱者來說,也能夠學習到許多自己原來不熟悉的設計作法。當 Code Review 成為專案中每週例行的程序以後,每位程式設計者在平常撰寫程式碼時,只要想到這是必須給所有同儕檢閱的內容,也會更加地謹慎仔細思考。只要妥善地實行 Code Review 程序,將能夠在部門內形成一股良好的正向循環風氣,對團隊中的每位成員產生出正面的效益。

當然 Code Review 並不是萬無一失的銀子彈,管理者仍然需要視團隊狀況小心調整程序的實行細節;例如,需要注意會議時間不可過長、注意團隊中的討論氣氛,以及做出適當的裁定與指示等等,才不會反而招致負面的成效。關於 Code Review 的一些實際執行狀況與心得,可以參考黑暗執行緒中的「Darkthread’s Code Review Theory」這篇文章。

我並不是很願意承認這件事,但是我認為國內的遊戲業界,在「合作開發」這件事上,還有很長、很長,很長足的進步空間。在遊戲業界中,我見過許多個人能力很強、各有擅場的程式設計者,但其中有許多人總是習慣於單兵作戰,與他人合作共同撰寫程式時,卻反而綁手綁腳般地難以發揮實力。其實他們並不是沒有能力或者不願意與其他人合作,有時候只是缺乏了流程制度的推動與溝通管道的建立,以及一位恰如其份的居中協調者。如果身為程式部門主管的角色,請盡量少一點動手寫程式碼,多花一點心思建立部門內的橋樑,多花一點心力製造出無形的溝通形式吧!

回過頭來想,程式設計本來就是一種很需要個人獨處空間,以及高度專注力與集中力的工作。包括我自己在內,在思索臭蟲來源與架構設計問題時,經常都會像失了魂似地盯著螢幕想、吃東西時想、上廁所想、開會時也想,所以難免會減少了與同儕之間的溝通互動行為。因此,身為管理者的角色,要能夠把程式設計者從埋頭苦幹與獨群索居的自然習性中,稍微拉出來一點點,讓大家都能夠自願地、自然地探頭呼吸與說話,才能夠使團隊中的每位成員都可以在工作中獲得成長,同時也會使程式設計者對進行中的專案更具有認同感以及向心力

我並不會妄想遊戲業界能夠一下子大刀闊斧地推行 Agile DevelopmentTest-Driven DevelopmentPair Programming 等新穎的軟體工程方法,但是如果我們希望國內的遊戲業界朝向大成本大市場大製作大團隊的開發模式邁進,當務之急就是必須捨棄以往業界中常見的「英雄開發模式」,一步步學習如何真正發揮 Teamwork 的本事,使開發者與開發者之間不再是單純的加減法效應,而是發揮出乘法般的正面效應與戰鬥能力!

身為程式設計者的妳或你,今後,也要愉快地 PvP 唷! :)

8 Replies to “遊戲開發中的PvP:程式設計者 VS. 程式設計者”

  1. 我個人很喜歡我的lead重新看過我的codes。一來可以知道自己有什麼地方寫的不夠好,二來也可以多了解我們小組的寫作風格。而且寫得好的地方有時還可以得到一點誇獎,這也是成就感的來源之一呀~ :p

    半路:
    看來你們公司在程式部門內的溝通管道,也做得很不錯呢~
    我覺得口頭上的稱讚,的確是滿受用的激勵方法。 XD

  2. 看不懂 = =
    但我知道程式設計者一直打不贏破解者

    半路:
    程式設計者與駭客破解者之間的戰爭,永無平息之日。

  3. 雖然不是我想說 但是國內都發展FOR WINDOWS 的遊戲
    而大多數有規模的遊戲公司都是搞ONLINE GAME

    偏偏大部分的遊戲模式都一樣
    實在太…
    我寧願花1000多買一個國外遊戲+中國漢化
    也不碰打到手抽精卻也練不好的RPG ONLINE

  4. @路人假:
    你的留言和這篇文章的關連性是……= =a

    不論是國內的遊戲或國外的遊戲都沒關係,只要用實際的行動支持好遊戲就對啦!請付費購買你想玩的遊戲,支持那些優秀的遊戲開發者們吧~

  5. 重點不是在「絕對不買」「國內遊戲」,而應該是「絕對不買」「擺明是要來騙錢」的遊戲吧…

    要是國內某天出了好遊戲,不支持的話,是讓這些好遊戲的製作者沒有出路──也就相當於扼殺國內的遊戲產業。

    有時候某些大作也會出騙錢續作,這時候玩家應該發動拒買行動,讓廠商知道,「錢不是那麼好騙的!」

  6. 您好,雖不是遊戲開發者,但最近敝團隊也正在嘗試導入Agile,
    為了日後能順利運作下去,開始嘗試加入CodingConventions以及開始做CodeReview、
    還有讓稍微資深的同事帶一些新手做Pair Programming

    雖然感覺有點辛苦,畢竟以前可以一個人開心的寫Code現在卻要花上大半的時間在做CodeReview
    或是觀察同事Pair Programming的合作情形是否順利、思考之後該如何繼續導入方案讓大家素質整體更上升。

    但其實也得到很多,藉由幫人做CodeReview無形之中也更能了解同事的情形,
    進而互相指導學習,等於也幫日後會時時擔心同事出狀況的情形打了一劑強心針。
    (因為都看過了,所以之後要是出狀況也不至於只能沒頭緒的窮緊張了)

    畢竟我已經無法再忍受每次都要擔心某些人寫的code出狀況怎麼指導都指導不好的痛苦了 :(

  7. @pp:
    我一直沒那個運氣在有 pair programming 的環境中工作過。但我覺得任何一個稍具規模的開發團隊,只要有行有餘力,都應該建立起 code review 程序和 naming convention。

    做這些事情短期可能看不出明顯成效,但長久做下去應該就會逐漸發現使用這些軟體工程方法的優點了。

Leave a Reply