天天看點

程式設計原則

作者:Thoughtworks

本文來源于我去年翻譯的圖書《程式設計原則》(Understanding Software)中的譯者序,我真誠推薦你閱讀完這篇文章甚至是該書。我推薦的理由和我翻譯的動機相同,因為它恰到好處地提煉出了我長期工作中積累下來賴以受用的經驗,其中不乏有邪惡和殘酷的一面。雖然書是以作者自己的經曆出發,但也讓我感同身受。相信它一定會對你有所啟發。

它是一本關于什麼的書?

在還沒開始翻譯之前,我對于這篇譯者序就已經有了規劃,很簡單:先聊聊為什麼翻譯這本書,再大緻把書裡内容叙述一遍,最後重點推薦一些有價值的章節。但是在後續潤色譯稿的過程中(其實也相當于重讀了),發現當初的設想是不可能辦到的,因為整書涉及面太廣了:調試代碼、測試政策、團隊協作、效能提升甚至還包括待人接物,可以說無所不談。

此時你肯定也疑惑了,是以整本書究竟想說什麼?難道沒有一個統一的主題成為它們裝訂成冊的理由嗎?

有,整本書用兩個字總結就夠了——原則。

整本書涵蓋的是所有你在開發中可能會運用到的各式各樣的原則。在本書的前言和第一篇中作者就開宗明義指出,本書的目的是幫助你成為一名更好的開發者。希望書中這些作者在他過往工作中總結下來的經驗,能夠讓你在成長的路上少走彎路。

多談原則

關于如何對待程式設計領域内的知識,兩種極端态度我都見過:有人隻看結果,他們隻關心“寫代碼”而對“寫好代碼”一無所知;第二類人深谙各種架構設計、整潔代碼之道,但對于當下你代碼中遭遇的實際問題,他們無法把方法論落地為解決方案。

在網際網路公司的多年工作經驗讓我個人更習慣于從第一種人的視角看待問題,畢竟這是行業性質決定的,跑馬圈地、快速擴張才重要,競争不允許你有時間思考。如果能把行業和公司因素排除在外再看編碼這件事,我作為程式員最大的疑惑是,為什麼每一家公司内我接手的代碼庫都如此難以維護;為什麼總有人寫出500行代碼的函數和1000行代碼的元件;為什麼每一個疊代的最後總是要加班加點,研發、測試、産品經理都叫苦不疊;為什麼問題年複一年的在發生,卻沒有人想做些什麼來改變現狀。

DRY——Don't repeat yourself. 别忘了這可是我們自己說的。

大部分程式員熱衷學習新技術和新架構,對閱讀源碼有發自内心的崇拜,這無可厚非。新技術有機會讓工作事半功倍,功利點說也能給我們履歷增添濃墨重彩的一筆。但技術背後的編寫思路和演化至今的原因同樣值得了解,它們和技術的文法本身同樣重要。你仔細回想就不難發現,工具的好壞和你代碼的好壞沒有關系,從裸寫 JavaScript 的年代,到 BackboneJS*,再到* React,你看到團隊中能把代碼寫好的人真的是越來越多的嗎?

不同行業對于軟體品質的要求是不同的。且不說你所在的行業有沒有意願和資源解決這些問題,如果有,你應該去哪裡尋找方案?

在我看來,前人留下的經驗是最值得我們借鑒的寶貴财富,無論這種經驗是來自傳統軟體行業還是網際網路公司。我們當下遇到的多數問題,對于傳統軟體行業而言他們在十年前甚至二十年前就已經遇到了, 我不敢說在解決這些問題上它們走的有多遠,但他們邁出的每一步都對後人産生了深遠的影響。然而這些經驗也并沒有什麼神秘的,其中有一部分經典就是你已經耳濡目染的各類程式設計法則和開發模式,而另一類更實際的内容就散落不同管道的文字和口述當中,例如本書。

但讓人望而卻步的是,大部分原則聽起來都過于抽象了,甚至是反直覺的。

我明白抽象帶給人的挫敗感,你肯定聽說過不少抽象概念,甚至它們的名字可以信手拈來,什麼可維護性、可擴充性、可讀性、KISS、YANGNI等等,然而應該用什麼标準衡量可讀性的好壞?KISS應該如何在代碼中實施?

反直覺的實踐也比比皆是,如果我告訴你,假設你能在每一次正式開發代碼前提前對代碼做一些重構工作,那麼無論是短期還是長期來看,你的整體付出的開發時間是會下降而不是上升的。你願意相信嗎?你敢于在工作中嘗試嗎?

遺憾的是有一些原則背後确實存在複雜的知識體系作為支撐,哪怕我用思維導圖把背後涉獵的概念一五一十的列舉出來,你的内心可能依然毫無波瀾。因為其中的很多原則需要在你經曆過相似代碼的前提下才能心領神會,輪扁斫輪寓意也是在此。

而有的則通俗易懂,Uncle Bob Martin 在他的「The principles of OOD」一系列文章中,談到過 糟糕設計(Bad Design)的幾個特征:

  • 僵化(Rigidity):代碼難以修改,因為改動會影響到的地方太多
  • 脆弱(Fragility):當你做出修改時,系統中預期之外的地方會遭到破壞
  • 難以修改(Immobility):代碼很難被複用,因為它與目前系統中的功能耦合在了一起

這一系列簡單扼要的描述,就将程式設計中涉及到的原則,和代碼中具體的症狀聯系到了一起。

學習這些知識難嗎?想要了解它們很簡單,但想要在程式設計中靈活運用它們則是另外一回事,畢竟提升程式設計技能靠的不是死記硬背,而是反複刻意的練習。可再困難,也會比将來回過頭設法挽回代碼造成的損失要簡單。

如果他們錯了怎麼辦?

我無法否認這種可能性。但大部分時候——我說的是大部分時候,技術的決策是專制的。如果我在這個技術領域有豐富的經驗,如果我解決過足夠多的問題,哪怕我隻是在這個項目中待的足夠久,那麼對于當下任何一個新的問題,我給出的解決方案一定會更完善。

很多時候這些原則不一定是錯的,而是反直覺到讓你聽上去以為它是錯的。拿注釋來說,很多程式員會認為注釋是消除代碼“惡臭”的靈丹妙藥,但是

  • Martin Fowler 在《重構》裡告訴你沒事别寫注釋
  • Uncle Bob Martin 在《代碼整潔之道》裡告訴你沒事别寫注釋
  • Jeff Atwood 在 codinghorror 技術部落格裡告訴你沒事别寫注釋

那還有什麼理由要繼續寫注釋?

現在依然半信半疑的你有幾個選擇:

首先你可以去了解這些建議背後的動機。這些建議的背後都有支撐它們的理由。"start with why" 有助于你了解它們,神奇的讓你從對立面轉向同一陣線。

但有一些知識可能是無法追溯的口口相傳,或者隻是團隊中留下的實踐。面對這種情況你需要的是“信仰之躍(Take a leap of faith)”。也就是說你此時你需要無條件的相信并遵循,然後日後再慢慢驗證。

或者你還有一種選擇,那就是置若罔聞,但可能需要承擔後患無窮的代價。

如果你依然對書中的原則将信将疑的話,我不得不提我翻譯這本書的另一個原因:書中很多内容與我在實際工作中總結出的經驗不謀而合。

舉一個例子。我個人在從獨立的開發者視角,轉向關注團隊、項目、流程的視角的過程中,發現技術問題不再成為我眼中首當其沖需要解決的難題。

因為哪怕你找到了整治項目的靈丹妙藥(某種最佳實踐),也需要整個團隊的力量來幫助你落地且一如既往的保持下去。項目裡不需要英雄,即使團隊中真的存在能寫一手好代碼的高手,他的幸苦結晶也很快就會被庸才們“孜孜不倦”的“勞動成果”所打敗。

迫切的希望團隊中有“救世主”角色的出現是一個危險的信号,而且通常這個時候救世主也派不上什麼用場。接着靈丹妙藥一說,你有沒有考慮過團隊裡的每個成員能否“咽的下”這顆靈丹妙藥?僅僅隻有幾個人能夠了解這套方案并且在項目裡實施起來是不夠的,是以要怎麼打造這顆靈丹妙藥?底線在哪?說白了,底線就是團隊能力的下線。

那麼如何提升團隊效能,如何幫助團隊中的成員成長進而拉高團隊的底線,都是會在本書中談及的問題。

現實一些

還記得我在開頭提及的第二種人嗎?他們同樣是危險的。如果抛開實作,單純把問題抽象到某種高度,可能會讓問題陷入到一種什麼都解決得了和什麼都解決不了的極端局面中。前者相當于“不就是”,後者等同于“又怎樣”。萬事萬物都可以套用“不就是”與“又怎樣”的句式,這樣的描述看似所向披靡,仔細想想卻破綻百出。

“不就是微前端嘛”——不好意思你說的是哪一種微前端?不同架構下元件間的通信問題是如何解決的?建構時內建流水線的粒度如何?元件間互相依賴的版本管理政策如何?

“又怎樣”的心态更是可惡,當代碼稍有改善時,就會有悲觀主義者“友善”的“提醒”你,這種杯水車薪的改善又能怎樣呢?你不是第一個人,但現在整個代碼庫依然身陷囹圄。

這種思考問題的方式一點都說不通,為什麼代碼腐化是一個持續的過程,但為什麼我們卻想要在某個時間段内一勞永逸把問題解決?

代碼庫滿目瘡痍是常态,問題在于你要如何挽救它,從哪裡開始挽救它。他們沒有錯,無論我們是引入 committer 機制還是代碼評審會議,總有一天會無法堅持下去,最壞的情況無非是我們沒有讓它變得更好,但也保證了在嘗試的過程中它不會變得更差。

上一小節中開發人員的能力困境“不就是”溫伯格的咨詢第二定律:不管一開始看起來什麼樣,它永遠是人的問題。

它夠不夠抽象?夠不夠深刻?夠不夠有哲理?夠。但說實話對于解決我們當下的問題并沒有幫助。如果瓶頸真的在于團隊的成員上,我們想知道的是,我怎麼樣才能提升團隊成員的程式設計能力?再實際一些,作為一個創業公司,我無法提供非常有競争力的薪水來招到頂級的人才;或者迫于傳遞壓力我無法花太多的時間在教育訓練、代碼審查、重構上,那麼我的代碼應該如何被拯救?

在我看來本書的魅力正是擺脫了高高在上的姿态且在“說人話”,作者并非隻是憑空扔給你一組金句之後讓你慢慢參悟。對于一些概念,甚至是常見的概念,作者會進行澄清和定義。如果他提出的是一條建議,那麼他還會解釋這條建議的來龍去脈和它所适用的範圍。對于在實施過程中可能遭遇的阻礙,他也做出了适當的預測和解決辦法。

我不敢苟同他在書中提出的每一個觀點,最終是否适合于你還需要你自行判斷,畢竟在這個領域内沒有銀彈。但相信這些内容能夠給你帶來啟發。自經典,才有可能超越經典。

文/Thoughtworks 李光毅

更多精彩洞見,請關注公衆号Thoughtworks洞見