我們是如何將一個專案做爛的

發表於2016-09-01

全篇文字都是以 Java語 言為背景,如有雷同,絕對巧合。

在你讀到這篇牢騷的時候,無數個專案正在慢慢變爛。

我們是如何將一個專案做爛的

既然標題都用到了”爛”這個詞,那什麼才是爛呢?

在你的專案裡,”爛”和”好”一樣無法準確的衡量和定義,在大多數人的職業生涯裡,你聽到”爛”專案肯定比聽到”好”專案的情況要多很多。

當你在一個維護型專案面前,一邊嘴裡跑出一萬隻草尼馬,一邊還在上面Coding,最後居然還如期交付了維護任務,你能說那是”爛”專案嗎?

我自己也沒有遇到過真正”爛”到無法維護的專案,因為我就是那個讓專案慢慢變爛的人。

也許,”爛”專案的罪證無法像《如何編寫無法維護的程式碼》那樣容易羅列,所以你根本就不認為那是爛。

意識到專案的”爛”與聞到程式碼的壞味道一樣是優秀開發人員的基本素養。

不過本文說的”爛”,只是從程式設計師的角度去看專案,與專案本身的創意,專案在公司層面的戰略意義沒有關係。

 

工具

在我剛出道時(06年左右),那時候的Java生態圈其實已經很強大了,但是我剛畢業工作過的幾家公司,幾乎在專案部署上都沒有使用太多的自動化工具。

有的是直接用開發工具Eclipse打包war檔案,其中一家公司,甚至是在本地編譯Java檔案,然後上傳class檔案到線上伺服器,就算那時已經有ANT這樣的先進工具,可惜我們還是類人猿,沒有進化過來, 要知道 使用製作工具是人類起源的重要標誌.

如今我們在一個最好的時代, Maven成了Java構建的標準,Gradle成了Java構建的新秀, 請把打造高可用自動化工具鏈與開發高可用系統提升到同樣一個高度。

如果你的專案中使用到了工具,但是它卻很脆弱:過多依賴環境,依賴複雜的配置,有時候還會有BUG。

如果你的專案還不能做到一鍵命令構建,打包。

如果你的測試環境和線上環境程式部署時間不在可控範圍。

……

那麼你的專案,肯定會慢慢變爛, 因為效率太低。

 

框架

是的,從你找工作開始,就肯定聽說了這個詞,如果你在學校的時候就是一個勤奮好學的同志,那麼你早就聽說過了,在Java的世界裡,你不會幾種框架,還好意思出去混嗎,於是很多招聘裡面都提到,精通Spring,Hibernate,Struts,Mybatis … 我入職的一家公司,甚至還有公司框架Demo程式碼學習這個環節。

So,當你到公司第一次接觸到專案的時候,我想上面提到的這幾個框架,至少有一個出現在你的專案中,先來看看我遇到的專案中使用框架的情況:

  1. 使用了框架,但是版本已經是上個世紀的了,卻依然線上上跑著
  2. 依賴同一個第三方開源工具包,卻有多個版本
  3. 有的地方用了框架的註解配置方式,有的地方卻用的XML配置檔案
  4. 一個本來只需要幾十K程式碼搞定的專案,最後把框架依賴一起打包,至少幾十M
  5. 沒看出來為什麼這個專案需要用到這個框架
  6. ……

框架一詞原本來自建築學,在軟體行業裡面,本人理解框架,就是解決特殊場景問題的 抽象 實現。本著娛樂的精神,這裡就不引入太書面的文字,容易引起反感。

如果你的專案和我遇到的情況一樣,滿足了上面兩點以上,我相信,只要這個專案還要繼續,就會繼續變爛,原因大概有以下幾點:

  • 你是一個有理想的男青年,你想把機械鍵盤砸在那個已經不知離職多久的前前前同事的臉上,然後大聲喊出來“老子要重構”,然而老闆說:可以,你先把這一堆需求實現了再說。
  • 最後老闆還是同意了,沒事兒你就重構吧,但是,你敢把一個正在好好running的線上專案框架換成最新版本嗎?(你的專案用到還不只一個框架,有些框架之間在版本上還有依賴的,你不可能只升級其中一個)
  • 想到這裡,再抬頭看看周圍Coding的同事,有的是已經工作了數年的老臘肉,還有一波剛入職的小鮮肉,他們是否和你一樣有理想,有追求呢
  • ……

如果你學過PMP,那麼上面這些問題可以概括為風險和成本。

引入了框架, 那麼專案成員是否在框架上做足了技術儲備? 如果僅僅是達到使用的地步,那麼由於框架引發的問題,你是否能夠在最短的時間內解決?

不然框架就成了專案的枷鎖,即使不會讓專案慢慢變爛,也不會讓專案慢慢變好。

 

領域模型

對啊,沒問題,我們專案裡面的使用Spring,爽得不要不要的,Spring不是提倡面向介面程式設計嗎,我們有完善的Service介面層。

是的,就像上面提到的,我曾經學習過公司的框架Demo程式碼,裡面把Module都分好了,Domain, Dao,Manager(用於管理DAO層的事務),Service,Web。 真實的情況卻是,Service裡面,一個Service介面對應了一個Dao(大部分情況是這樣的),你有幾個資料表,大概就有多少個Service介面,如果有個新業務來了,新增了一張表,就再搞一個Service介面,Service,Dao基本都是在為資料庫CRUD服務。

一個介面類從專案產生就沒有出現過多個實現, 當時定義介面僅僅是為了遵循面向介面程式設計。

在充滿疑惑的歲月裡,我找到了真相,原來我把名詞理解錯了,“DDD”的含義有兩種,一個是Data-Driven Design,一個是Domain-Driven Design

一個沒有領域模型抽象的專案,遲早要慢慢變爛。

 

程式碼

框架和模型是讓你站得更高的角度來看專案,最後還是得回到程式碼上,好的專案(應該說團隊)一定能夠找到一套規範(當前流行叫”軍規”), 每個團隊制定的規範可能有些不同,但還是能找到很多共性.

  • 程式碼規範(Checkstyle, 方法名,類名規範,註釋規範,程式碼格式規範……)
  • 工程規範(構建流程,版本釋出……)
  • 設計規範(設計複雜度控制,模組依賴……)
  • 資料庫表設計規範, SQL規範
  • ……

經過我多年的經驗,制定規範這事兒,其實重點在如何讓專案成員理解和認同,最後才是執行,很多專案成員對規範的牴觸源自浮淺地認為規範只能讓他們將時間消耗在非功能性需求上.

規範是一種認同感, 但要想讓專案成員建立更好的認同感, 有時候你必須利用人格魅力(如果你有的話),或者慘痛的經驗(老司機肯定有的).

抬頭看看你的專案, 能不能找到一條硬性要求的規範, 如果找不到, 可以直接跳出該文.

如果你有所覺悟,然後只是到網上到處借鑑各種軍規堆砌在專案裡, 那麼依然沒什麼卵用.

規範並不能讓你的程式碼變得多優秀. 規範只是防止程式碼裡到處瀰漫著單身屌絲程式設計師(猿)的個人感情色彩,規避一些顯而易見的錯誤.

有了規範, 你有沒有程式碼審查?

你在網路上到處都能搜尋到” XX團隊如何看重程式碼審查,XX團隊為了程式碼質量開發了一個程式碼審查工具”, 可是你很難找到XX團隊是如何做程式碼審查的,所以搞清楚如何讓程式碼審查起到作用 比程式碼審查本身更重要.

總之,在程式碼審查之外,你還需要權衡,要不要把程式碼審查搞成政治任務,要不要搞成批鬥大會, 如果你在程式碼審查的氣氛裡面聞到了壞味道, 那就應該停下來.

一個做好了程式碼規範和程式碼審查的專案,想變爛都沒那麼容易.

 

測試

我在大學裡面學程式設計的時候,似乎老師都沒教過什麼是測試,當時寫TC的時候,老師只是說上機執行,現在回想起來,好像當時的教材也沒有專門講測試。(也許我就沒有好好學過)

從專案程式碼來看,最基本的就是單元測試。

你的專案雖然有單元測試,但是他們要麼過時(沒有和被測試程式碼一起演化),要麼根本就沒有達到覆蓋率要求。

當你想給一個功能補寫單元測試的時候,發現編寫單元測試的難度比重新實現這個功能的難度還要大,結果你就真那樣做了。

測試的目的就是為了發現儘可能多的缺陷, 儘量 保證質量。

然而很多專案根本就沒有清晰定義出 質量 的邊界,甚至只完成了功能測試。

羅列你專案中的測試項,將他們分類列舉,如果測試項用一張紙都能寫完, 那麼這個專案本身就是爛的,根本不需要慢慢變爛。

再強調一下,如果沒有充分測試(怎樣才是充分測試?)的專案,其實已經爛了。

 

需求

所有的業務需求你都應該去滿足

業務是專案的基本驅動力,可以說沒有需求就沒有專案存在。

然而對於一個發展中的專案,有可能正是需求在讓它慢慢變爛.

因為我見過太多的需求來至專案控制人員(簡稱領導),而不是來至於真正使用者,這些專案控制人員還會振振有詞地說:”我也是使用者中的一員”,大部分開發人員基本上又都處於食物鏈的最低端, 所以遇到上面這種情況,基本是無解的(排除那些真正執行工程師文化的公司).

大部分專案的需求,都會對應到一個系統功能,系統功能都會有生命週期,但是專案中的程式碼卻往往隨需求一起增長,對於過時的功能程式碼,沒人敢隨便刪除,然後就變得臃腫。

另外一種情況就是需求超越了領域模型,例如:ATM取款機,讓你植入視訊播放功能(現實生活中卻真有的),你有時候無法分辨出這類需求,然後卻漂亮地實現了它。

恭喜你,你的專案正在面臨慢慢變爛的風險。

 

負面情緒

負面情緒讓專案慢慢變爛,聽起來有點牽強,其實負面情緒與專案中的”爛”有點像雞與蛋的關係,但這也只是其中一方面,放眼望去,專案中的負面情緒來自於方方面面。

部分開發人員如果遇到《如何編寫無法維護的程式碼》 中提到的問題會讓他們大怒,然後抱怨沒有統一的程式碼格式化工具,沒有規範的目錄結構,甚至日誌輸出格式也是五花八門……

如果你在專案中經常聽到這種罵街的聲音,那麼你所在的專案還不至於那麼快變爛。

不滿現實,並動手去改變它,這也是優秀程式設計師的基本素養,但你必須停下來思索一下,你周圍的人是不滿的多,還是動手去改變的人多。

我自己就非常願意和不滿現實並且情緒化的開發人員一起工作,非常懼怕那些只是抱怨,說到動手去改變的時候又保持沉默的人。

情緒會傳染,有些情緒在團隊中會產生負面的效果,有些卻能成為動力,這取決於團隊的自我認知能力。

如何識別專案中遇到的負面情緒呢?

  • 小A最近經常一邊寫程式碼,一邊上逛招聘網站
  • 小B經常給你說,某某公司的工資更高,全員MAC環境開發,23寸顯示器…
  • 小C給你講,小A和小B的程式碼寫得真爛
  • 小D抱怨技術上得不到提高
  • ……

放心,如果你在專案中是個領導角色,上面這些抱怨列表你基本上是不會聽到的,如果你只是一個普通的開發人員,那麼就去購買一本《程式設計師自我修養》,將負面情緒轉化為正能量。

 

保持現狀

有一個老程式設計師自豪地告訴我,他寫的一個程式已經線上上跑了快10年了,從來沒動過。

我只是笑了笑,說了一句:牛逼

如果我寫一個列印Hello world的程式,部署在一臺太陽能Linux機器上,然後把它放到外太空,誰知道能執行多久呢。

我做的部分專案裡面,用到的第三方工具距離最新版釋出時間有的至少快5年了。

同事告訴我,用著這麼穩定,幹嘛要升級。

你要知道,JDK現在多久釋出一次?每次都有哪些BUG修復?有哪些效能提升?你用的這個第三方包,可是在5年前那個版本的JDK下開發完成的,而且那個開發第三方工具包的人有可能還死了。

請注意,我們不是在討論升級的問題,我們是在討論 變化 的問題.

保持現狀是一種惰性思維,它已經麻痺了開發人員對專案變化帶來的風險評估。

如果將專案比做一輛汽車,它只是在不停地行駛,卻沒有定期保養。(重點是你不知道應該保養哪些部件)

不要讓保持現狀的思維腐蝕了專案,讓專案慢慢變爛。

最後記住:

在一個團隊協作的時代,你不是一個人在挖坑。

相關文章