大泥球——世界上最常用的軟件體系結構,一個經久不衰的傳奇。

大泥球是一件很神奇的事情,閱讀文章里列舉了大泥球出現的一系列原因,但是我們貌似很少在其他的領域看到這么不專業的專業行為,從這個角度看看,不妨稍稍刨根問底一下。

我覺得首先有個成本問題——軟件開發可以說是沒有物質成本的。可以看到大泥球能夠工作,而且,造成一個大泥球并不比有道理的開發架構需要更多的物質成本,多調幾個大泥球經費也不會被馬上耗光——一個失敗的設計在量產時需多焊很多的電路板可能會馬上被產品經理批評——相反,軟件工程中的大泥球還能提高時間效率,它能減少了架構設計的思考占用的時間——這一點我還是很有體會的,之后我會提到之前的課程學習經歷來簡述我的體驗。

另外文章說到的能見度也是一個有趣的原因,閉源的軟件產業使得產品和設計的分離,設計對于用戶乃至其他開發人員來說常常是不可見的,軟件開發者并不在意軟件的內部架構在用戶看起來是什么樣,反正你也看不到,軟件就像是一個神奇的魔法盒子,不管它怎么工作的,反正有用。

對于軟件開發,效率是至關重要的,代碼重用是提高效率的一個重要思想,但是正如文章所說也是風險,一個僅需要適應當前需求的架構可以快速完工并且投入工作,但當需求變更來臨的時候怎么辦?架構擴充還是一件小事,有時候新的需求甚至可能會擾動架構的根基,在這英雄的悲劇時刻通常有兩種選擇:

1.推翻架構的一部分或者全部以適應新的需求,再開始新的編碼——無論是一部份還是全部,架構的改變都可能影響架構之上的其他代碼,你都不得不考慮兼容性,一旦兼容無法實現又是另一出悲劇,就算僥幸地架構師是一個天才,幾天幾夜的設計之后,更新的架構能夠承擔新的需求并且完美兼容之前上層建筑,那么——用戶說他還想要來一個新需求呢?

2.或者為了開始一段架構之外的羅曼,作為一個補充,有時候可以在架構之外補充一段代碼,橫跨底層至用戶界面,就像一棟精致的別墅從地板到天花板被開了一個洞,露出了一根電線桿。同樣地,再來幾根,一顆裹著別墅的大泥球誕生了。

為了避免這些悲劇的發生,一個勇敢的架構師說,我們應當預先考慮大部分可能來臨的需求,我們的架構需要在實現當前需求的時候,同時擁有良好的可擴展性,新需求來臨的時候只要擴充就可以了。為了提供預留的這些需求以擴充實現的,便不再有眼前需要設計的小屋,而是一座城市。這個架構本身就需要足夠多時間去設計和建造,相比架構本身,需要實現的功能才成了真正的小部分。結果延長了工程周期,很多人認為這不值得,而且也沒人相信有一個牛逼的架構能夠輕易地擴展實現不講理的一切用戶需求,即便有這樣牛逼的架構,也沒有這樣牛逼的人……

回過頭來談談實際,我作為一個不偏向于大泥球的程序員,一定是對良好架構有這特殊堅持和憧憬的。因為我的理論是沒有架構的工程就像是不寫函數的程序……增加項的工作量是平方的甚至是指數,那是要死……那不科學……我理解中架構的一個有點就是層次地整理可以重用的代碼來減少代碼量,提供可維護性,缺點在于不靈活,然后對于經驗不足的初學者來說,開發周期有時候是更長的。還有一點,當一個人做的不完全是真正的產品,而是一個試驗品、或者說是簡歷填充物的時候,能見度原因就不起作用了,因為要是說代碼給別人一看,讓別人覺得,這TM寫的一坨大……肯定沒有前途。所以我必須堅信寫軟件要有架構。

我大二上的Java大作業和大二下面向對象大作業,基本都是一個人寫的Java小游戲,是個泥球vs設計的正面例子。

Java大作業就像一個大泥球,我只求每個單位只管自己的所有邏輯,能夠運行,有點像用FlashAS寫小游戲的感覺,最后我做出了一個可以玩的版本,只有三個游戲單位,三種子彈,三種效果,一個不太完善不容易制定的固定規則和友好度較差的界面。開發時間之有大約兩周,也算有始有終了。

當我在大二下應對面向對象大作業的時候,我覺得有了上次的經驗,這回我應該能不太費力地寫出一個游戲內容更豐富一些的游戲,增加了一些目標的游戲內容量和網絡聯機功能,等于是對原來的Java大作業作一個擴充。這個時候,我發現逐個單位去考慮各自的邏輯是個噩夢,工作量太大了,而且不便維護,從而開始考慮一個架構。舉個架構主要功能來說:希望用一套邏輯抽象來所有類型的單位,然后以數據文件來定義不同單位的邏輯,這樣就需要一個能夠用動作跳轉的數據結構來控制單位運動邏輯架構,而且這個動作結構又萬能。仿照我之前接觸過的游戲數據形式,我進行著這方面的嘗試,結果大約從開始集中注意力寫作業到一個月過去之后,基本以失敗告終,因為剩下的時間已不多了,剩余工程已經非常巨大,光游戲邏輯還有幾十個類沒有實現,類之間的工作互相依賴,逐個單元測試工作量也極其大。眼看快要到死期了,果斷放棄了新架構的設計,轉而使用簡化的代碼狀態機(而非數據狀態機)編寫。最后的情況是一個簡略得多的架構完成了整個場景只有四種游戲物體的游戲,然后有網絡聯機功能,一坨翔。

不服,果然在之后的大二暑假我還是用C++和DX完成了之前未完成的架構。花了我一暑假。而且在架構實現和游戲實現的過程中,遇到了一些架構設計時未考慮的問題導致游戲實現過程也在反復修改架構,這經驗太寶貴我會出去隨便亂說?

有了這次失敗之后我認識到架構設計有難度的……首先設計就是有難度的。然后實現是更有難度的。而且我堅信了,一定沒有人會愿意用一套動作游戲的動作引擎來編寫動作相對簡單的射擊類游戲的!動作游戲需要動作引擎是因為的具體單位的動作編寫復雜性太高需要的代碼太多了!而我做的游戲是動作射擊游戲!

我一瞬間懂了,所以架構的設計是目標驅動的,如果沒有一個合適的目標,大泥球還是更合適一點。沒有足夠經驗的開發人員希望借助一個nb的架構減少自己的工作量是愿景很美好。而且你不能說要做成什么樣我馬上就設計成什么樣,首先我要試一下。

這些經驗我帶到了軟件工程大作業中,鑒于經驗還不足夠多到能馬上給出一個足夠優秀的架構,而且游戲內容必須不能太少以至于不能改變世界,我很謹慎地先制定好了游戲設計的需求,堅決不要考慮基本不需要的功能,首先使用一個“架構非常簡單+只有少量基本單位+部分地方由小泥球組成”的原型工程,來看看架構設計的需要。然后才和安然開始正式的架構設計,并且和團隊開始完整的開發。如此慢步前進,雖然工程開始的時間相對其他小組較晚,但是……大作業能夠追求一體成型(希望)……

學生團隊有一個好,就是架構設計搓了,也還不要緊,不至于流落街頭要飯,回頭還能滾泥球一下。這使得我們有機會積累更多的軟件工程經驗,避免今后真正進入職業了,也只能天天往工程里塞泥巴。我也以為大泥球依然在正牌軟件架構中有極高市場占有率的原因,是太多軟件工程不敢有足夠宏偉的目標、承擔不起時間和嘗試的成本(也就是沒有足夠NB的架構設計師嘛)。不經歷風雨,怎見得彩虹?一個PM既得要堆過泥巴,也有過足夠多的失敗設計,才能有一天能夠站出來,給出一個頂級的設計,力挽狂瀾。