你的程式碼是我的地獄

發表於2011-09-15

我最近作為一個Rails程式設計師的經歷可能並不常見。

我經常被叫去維護一些已經做好的Ruby/Rails專案,在力所能及的地方進行改進和完善。這樣,絕大部分我需要接手的專案在我出現前都已經開發完成了。事實上,在我的記憶裡,我只參與了一個商業性質的格林菲爾德Ruby專案的開發。其它的,在我看來,都是“歷史遺物“,相當多的程式程式碼在我之前都已經出品了。(不包括個人和內部專案)。

我知道,我的這種經歷在Ruby和Rails程式設計師中並不常見。由於Ruby/Rails的高產和創業公司為主的使用者環境,大多數Ruby愛好者都是在這樣剛成立的公司裡開發全新的專案。而我的工作更多的是基於最初的開發人員走後留下來的程式碼。

Rails的讓人不堪的小祕密

在受僱寫Ruby程式之前,我也接手過一些歷史程式,它們有的歷史達數十年之久,程式碼量數十萬行之多。你很容易在這麼多程式碼裡找出寫的很爛的東西;有時候,這種爛程式碼的數量多的讓人驚訝。

但是,在Rails開發中,你會發現一個讓人不堪忍受的小祕密;在我的職業生涯中,我見過的最亂的、最棘手的、最臭的程式碼,都是在Ruby on Rails專案裡找到的。我所見過的那些Rails專案,它們兩年下來積累的技術債務和廢棄物,跟一個10年之久的C/C++程式相比,會讓你覺得後者更乾淨和優雅。我說的並不是某個專案。我看到這種情況到處都是。

有時候我會想,這也顯示了這種語言的強大之處。如果在一個Rails應用裡有500個錯誤,你可以不停的往裡面新增程式碼、再新增程式碼、點選“reload“,一直到它好用為止。從來都不需要寫測試或重構程式碼。在很多語言和框架裡,這種”補到它不漏為止“的開發方式顯而易見是行不通的。但Ruby on Rails卻提供了讓你這樣做的平臺。

不幸的是,作為它的直接後果,眾多我要處理的專案都可以被看作是一種應急產品。從某種角度來看,這種圖省事的做法的後果還是由開發團隊來承擔,你這樣做一天把它解決了,可引出的相關問題和不可預料的副作用,你花2周都解決不掉。

題外話:經常的,最初的開發人員會在完成開發後轉移到新的專案上。同時會有新員工接手這些程式碼。管理部門會抱怨,為什麼這新接手的團隊修改問題時沒有老團隊迅速呢?而新團隊遇到的問題是,在他們能給這些遺留的程式碼上新增新功能前,他們需要讓這些程式碼具有更高的測試覆蓋率,有可能還需要把它們分離成更小的模組;在商業層面,一個永久不變的聲音是:測試和重構就是拖延工期。看來這原創團隊都是比較明智的。

好了,牢騷發完了。

Rails的情況更為特殊!

Rails程式設計師有時候會顯得很傲慢和固執。我不清楚這個判斷的可信度;我並沒有看到太多的人是這樣,但也許我跟這個社群太接近了,也許我本身也是傲慢和固執的。

而我發現的卻是一種“Rails例外主義“。還記得第一次網際網路繁榮的時期嗎,當時有幾個經濟學家跳出來說”不會的,這次不同,網際網路改變了遊戲規則,市場會一直走高、走高“,本質上我感覺很相似,有些人相信,Ruby on Rails開發是某種不同的東西,不需要跟其它型別的軟體專案一樣。

這有一些例子,讓你明白我究竟在說什麼:

  • “設計模式是Java上的東西。Ruby裡只管寫你的程式碼就是了。“
  • “Ruby裡丟擲的警告都是無聊的,禁止掉就行了。“
  • “的確沒有單元測試,而且物件隔離做起來了很難,沒有人這樣做。“
  • “到處打補丁對於其它語言來說是不贊成的,但Ruby沒問題。目前還沒有出現問題。”
  • “像Demeter 定律這樣的東西在Ruby裡並不是這麼重要。“
  • “把方法分成私有和公有,這是變態控制,Ruby裡不需要這樣做“
  • “Java程式碼裡才會有程式碼異味(code smell)。“
  • “只有在大專案裡才會有這樣的問題“(暗示這個專案永遠不會變大)

我還看到了很多專案和子系統例外主義者:“我知道一個類不應該搞的太大,但是對這個類是有意義的,它是為了把所有的東西放到一個地方“。

歡迎來到小人國

事實上,Ruby on Rails專案確實有一點很例外:都是小專案。上週在James Gray在Lone Star Ruby Conf大會上有個極好主題,他提到的“巨型“專案有4萬多行程式碼。這讓我微微一笑,因為我被僱來做的頭兩個專案分別有5萬行和7萬行。這看起來不少,但根據行業標準,它們很小。

造成這種現象的原因有不少。Ruby是一種比Java更富有表達性的語言,所以,從某種程度上說,Rails專案,在相同的情況下,總是比那些更講究的語言顯得更小。

而且,Rails程式設計師很喜歡接受把系統分割成很多很小的、相互聯絡的小應用。但是經驗告訴我們,這種策略是有問題的。

不,我想這導致Rails應用體格較小的最大的原因是,顯而易見的:這個框架還很年輕。這個領域裡有大量不成熟的產品。一個Rails應用如果有3年的歷史,那就可以算是古老了。

我可以很有信心的說,這種情況不會一直持續下去。我們會看到越來越大的程式專案。我不需要鼓起勇氣就可以做下面的預言:很多專案將於遭遇想Lisp,Smalltalk,C++,Java等語言曾經遭遇過的相同的架構瓶頸。

你並不特殊

  《programming literature from the 80s》這個作品讀起來非常的有趣。動態,物件導向的系統引導了從“小規模“到”中等規模“的過度。聽起來耳熟,是吧?

每一次的革命都會堅稱這次是與眾不同的,不會造成上次革命後出現的政黨紛爭和官僚腐敗。起初你很容易被這些宣感測染。每個人都很興奮,熱情的去幫助;這時出現的問題還比較小;然而這只是市場的大機器還沒有注意到這場運動。

事實上,你要解決的問題也許並不是你想像的那樣例外。你思想裡的這種拜占庭模式只是遠古時代那些使用跟Ruby類似語言的人留下來的遺產。

不要驚慌

放鬆。我這裡要說的並不是告訴你過去的幾年只是一場可愛的夢,Ruby實際上一直處在它應有的地位上。

Ruby仍然是一種奇妙的語言,它令人驚異的地方就是它在付出微小的約束代價下能輕鬆的接納大型系統的設計模式。注入依賴?兒戲。物件委託和組合?小菜一碟。跟你的錯覺正好相反,Ruby並不拒絕嚴謹的設計模式和SOLID程式設計原則;Ruby能做到的事是讓它們更容易的表達出來。事實上,Ruby強大的富於表達的架構風格是讓很多人第一眼就喜歡上它的原因。

拜託:請在你告訴我Ruby和Rails不需要任何的約束之前,請跟那些仍然在維護你當初開發的Rails應用的兄弟們聊一聊。

 

相關文章