DHH 在 RailsConf 上面對到底要不要 TDD 開了第一槍。雖然引來很多爭議,我認為這是一個非常好的開始。
因為以 DHH 的地位,我認為他是說「我不 TDD」受到的砲火(大家會認為不TDD=不會寫程式)最小的人。當然,他說這句話,引到的其他砲火更猛裂。
但這真的是很好的出發點,讓其他人開始敢說真話以及思考其他可能性。
設計軟體的重點:好讀、易維護、以全局觀點思考。
很多人都是被以「我不 TDD」的爭議點吸來看這篇文章的的。但要繼續讀下去之前,我希望你先做兩件事:
- 上 Justin TV 把 DHH 整場 Talk 看完,在看的時候請把「這場 Talk 是講 TDD」預設觀點拿掉(我們聽現場的人,在進行到一半之前是完全不知道他會扯到這件事的)。
- 看完 DHH 對於 TDD 的論述。(有人翻譯了這篇文章 )
DHH 的這場 Talk 要傳達是「設計軟體的重點:好讀、易維護、以全局觀點思考」。
而不是「我不 TDD」。
而之所以他會選擇「我不 TDD」為出發點,是因為開發者被許多開發上衍生出來的技巧和觀念所綁架了。而且衍生出很多似是而非的偏見。
在軟體界你應該聽過很多指控,如:
- 「不 TDD」 = 「寫 Code 很遜」
- 「不會寫 Test」= 「寫 Code 很遜」
- 「不使用 Design Pattern」 = 「寫 Code 很遜」
- 「不 TDD」 = 「假 Agile」
- 「不想用 Scrum」 = 「不 Agile」
- 「覺得 Scrum 沒有用」 = 「你一定沒有受過 Scrum 完整教育,沒被好的 mentor 帶過」
當然,最大條的當然是「不TDD」,只要哪個 Developer 說他開發時不 TDD,別人一定會質疑他根本不會寫 code,功力是假的。
所以這樣的 false claim 由神人 DHH 出來坦強力反對,當然是最好的。
Developer 的聖杯:功力完霸所有名詞
上面寫的這麼多條指控是真的嗎?
在某些人某些狀況是真的,但是「絕大多數時候」 *不成立*。
這樣講,大多數人可能很難接受。
我想以這樣的角度去切入,一個 Developer 從入門到資深,由產品實作到產品架構設計必須要學習的技能以及標準:
***
(以用 Rails 開發產品為例)
- (前)入門者:學習必備的工具,如 Git, Command Line, CSS / HTML 。
- 入門者:學習 Rails 基本的 API、工具、第三方套件,設計出「可以動的程式」。
- 入門者(後):學會 Ruby 比較進階的議題,學習寫出改得動的程式碼,以及如何寫出佈 Abusing Ruby / Rauls 的 code。能夠自己獨立做完一個小型 project。
- 一般 Developer:學會封裝(method/Class),ORM 優化,效能優化,前端優化,基礎 Testing 技巧,基本 Security。
- 進階 Developer:TDD,基本 Design Pattern 技巧,Gem 封裝,Rails advanced API 使用。能夠自己獨立做完一個中型 project。
- 資深 Developer:TDD with Testing Pattern、PORO Design with Rails、SOA、大型站台 Scaling、大型 Gem 設計。
(完成所有的課題大概需要 5 年以上時間,因為很多東西是需要「大量」「實作」才能得到經驗值。)
其他還需要學習的有:如何跟其他人協作(設計 API 以及最不阻擾大家的工作 Pattern 與 Pattern),專案管理(如何控管進度,學會切票以及抓大放小),基本 Agile 技巧,溝通技巧(如何以有效的方式說服同事、老闆、Stackholder 採取方案)。
***
所以「不 TDD」 = 「寫 Code 很遜」。「不使用 Design Pattern」 = 「寫 Code 很遜」。在對資歷淺的 Developer 是成立的。因為這跟 Developer 程度與開發技巧層面有關係。
而 Developer 的終極浪漫往往是練完這些名詞,並且在一個 Project 裡全部用上這些字。誰擋在自己面前,就一定幹掉對方。
到達終點才知道夢破碎
但是最殘酷的現實是,當爬到最終點時,Developer 才會意識到一件事,這件事情是不可能辦到的。
因為學完所有名詞時,幾乎也會站到 Architect 這個角色去。才會發現幾件事:
- 除非專案有無窮的預算,否則你不可能無止盡的砸時間在軟體工程上。
- 如果專案有無窮的預算,你的產品也不可能成功。太多的官僚 PM 會湧入,太多的「想做到更好的念頭」「太多的產品決策樹」,會把上線的時間無窮往後延。無法上線的產品遠比沒有好 code 的產品糟糕太多。
- 身為一個 Senior / Architect 更重要的事情是「在有限的時間做出『相對好』的決策」,這些決策可能意外著可能要逼著自己或手下寫出 work-around、no-test、not-tdd、ugly code、slow-query,許多會被 developer 鄙視的 anti-pattern。
這就是所謂的抓大放小。
Architect 的兩難
而抓大放小,還會造成更多的麻煩。因為 Senior 平常會逼著 junior developer 學他們應該要的技術。但是你卻無法跟他解釋為何你「現在」要用這些 anti-pattern。因為他們無法連什麼是大,什麼是小都不知道。如何理解什麼是「抓大放小」?
Senior 希望 Junior 不要用 anti-pattern,但必要時又必須自己用 anti-pattern 解決這些問題。用久了這些 junior 還會以為自己老闆根本不會寫 code。一天到晚互相矛盾在打自己臉。
這就是 DHH 所說的「被名詞綁架」。你要做事和討論,雖然用正確的手段。但卻完全無法被放入場景,而且整個氣氛氛圍還會變成:一講出這些話,還會變瞬間貶低為「Amature」(完完全全的政治不正確)。之後相關議題完全無法展開。
所以他選擇開這個第一槍。
Testing / Design Pattern / TDD
Testing
回到 Testing,為何我們要學 Testing,是因為 Testing 可以帶給我們更 Solid 的程式。這在需要長久維護、或者是需要多人協作、牽扯外部第三方元件的程式中至關重要。
可以有效降低開發及維護成本。
Design Pattern
為何我們要學 Design Pattern,是因為使用 Design Pattern 技巧,可以讓我們的程式在某些情況下,相對的更好維護。只要修改小部分的程式碼,就能利用界面擴充出出更大型的程式。
TDD
為何我們要學 TDD,是因為 TDD 可以逼一個 Developer 以開端解 Fail Test 的方式,去「設計」出一支不容易 Fail 的程式(多數情況下,不容易 Fail 等於設計出正確的功能,也正常作用)。
同時,採取 TDD 的方式,且想要寫出品質好且「好測」的 Test,會逼一個 Developer 去思考如何做出好的物件、界面、封裝的設計。可以更深層的了解 Design Pattern、PORO 技巧的美。
所以 TDD 是一個非常好「學習寫進階程式技巧」的方式。
But why not TDD / Design Pattern ?
但為什麼很多 Senior 開發者 TDD 到最後卻選擇性放棄 TDD。是因為 TDD 會造成過於注重 unit 形式的設計,而忽略整體系統架構的設計。(這也是 DHH 所談到的主要 issue,每次他回去認真 TDD,寫一寫又覺得不對勁。但 TDD 不對勁這個議題又幾乎被氣氛綁架到幾乎形同禁止討論)
而且 Senior 對於 TDD 的看法多半是:TDD 適合用來作為「已知解決手法,但有可能過程複雜容易出包」的程式。使用 TDD 可以有效降低爆炸機率,提升開發效率。
但對於「未知解決手法」的程式,使用 TDD 反而會造成效率下降。因為反而會花太多時間在處理 unit 本身,而不是專注於 system 本身的設計。
***
Design Pattern 其實也面臨到相同的狀況。太早 Design Pattern 開下去,當系統要快速迭代變更設計時,原先的 Pattern 甚至或當場「絕對不適用」。
結論 : 好讀、易維護、以全局觀點思考
既然這些高階技巧不適用。那麼我們又該何去何從?
我個人的觀點是,這又掉進了同一個思考誤區。把所有人的所有狀況,看成一種人一種情況:
- DHH 說不是每次都要 TDD。不代表你應該不 TDD。
- DHH 說希望更專注 System Design Test。不代表你應該以後只做 System Design Test。
- Kent Back 說不是每次都需要寫 Test,因為人家付錢給我們是要買程式。而不是買 Test。如果你怕你程式容易爆的話,應該下班偷偷補 Test。
(因為你不是 DHH,你也不是 Kent Back,你現在不是面對他們所面對的問題。更見鬼的是,你也不是他們那層神級開發者的程度。)
他不希望大家聽他講一講,又跳進只專注 system design 的另一個聖杯去。
DHH 整個演講穿插的幾張綠色主題投影片,我想就是一個非常好的 Geneanal 準則(適用各種 Level)。其實你不應該被任何名詞綁架,而應該以這三點:「好讀、易維護、以全局觀點思考,為基準點」去設計你的程式。
(RailsConf 另一個講者的 Sandi Matz 的 Talk 也很精彩,他也提到了用錯誤的抽象封裝比正確的複製貼上 code 還要來的糟。)
不學 TDD 不知道要放棄 TDD
另外就是別因為誰講什麼不用做。就放棄去學什麼。
每一個 Level 都有自己應該要學的課題。
不學 TDD,也不可能一直領悟進化到(可以)放棄 TDD 這件事。
他也鼓勵大家「多寫 Software」,只抱著 Pattern 的書是無法幫助你成為一個厲害的 Developer 的。
***
這真是近年來罕見的一個精彩 Talk (雖然看不懂的可能就是看不懂..還會覺得是垃圾)。
我真的推薦大家「多看幾遍」。