[翻譯] How to Write 3v1L Untestable Code

[翻譯] How to Write 3v1L Untestable Code 如何寫出邪二的不可測試程式碼

原文連結
http://googletesting.blogspot.tw/2008/07/how-to-write-3v1l-untestable-code.html

本文章列出那些會幫助你寫出不可能可以測試程式碼的守則,或是可以避免那些技術來測試你的程式。

# Make Your Own Dependencies

使用自己的相關引用物件,在程式運作間實體化物件,而不是從外界傳進來。當我們這樣作的時候,外界就必須被迫使用我們實體化的物件。也就是說要驗證目前模組,必須先創造那些引用物件的內容。不能建立一個假的或偽裝的物件來協助我們製造例外情形。

# Heavy Duty Constructors

建構子中作大量的運作。在建構子中作越多工作,就越難把物件控制到想要測試的狀態。假如建構子可以創造出外界難以創造的狀態,就更棒了。這種遞移的依賴各種建構子的行為會越來越龐大,龐大的東西就難以測試。

# Depend on Concrete Classes

直接把模組綁在使用的類別上,而不是依賴一個中繼介面。(那些介面可以把使用的類別取代為一個我們真的使用的類別或他們想要實體化卻具有相同介面的類別,別給他們這樣方便的轡頭來測你的程式)

# Conditional Slalom

把判斷式寫成滑雪比賽,每次寫程式時不要忘記把if判斷式與switch寫的又臭又長。這樣會增加需要執行的路線,而測試必須全部涵蓋它們。條件式的複雜度越高,就越難測試。當某人建議用多型的方式取代判斷式,嘲笑他們的多慮。分支要寫的又深又寬廣:如果沒有至少寫出五層,你根本就是邀請那些測試狂人來測試你的程式碼。

# Depend on Large Context Objects

依賴大型的資料物件,傳遞大量的資料物件(或是很難另外製造的小內容)進來。這樣會降低函式的清晰度,譬如說使用myMethod(Context ctx)就比myMethod(User user, Label label)不清楚。為了要測試,那些資料物件必須先創造出來。

# Use Statics

使用靜態,到處都布滿靜態。這會讓測試之路顛簸不已。那些靜態不能特地仿造,也不能隔離出來。物件導向狂戰士會說靜態函式的變數必須只作用在那個函式裡面,但怎麼可能,我們可是專搞破壞的惡魔黨。

# Use More Statics

更多的靜態,靜態根本是一把讓測試工程師跪下的權杖。靜態函式不能在子類別中覆寫。當你使用靜態函式,他們就不能使用那些專門仿造的函式庫來仿造。

# Use Global Flags

使用全域旗標。何必要把函式的參數明確標出來,效法L. 羅恩賀伯特(山達基的創始人),依據"意識決定了物體",在程式裡面設定一些旗標,然後會作用到整個系統上(特別有趣的是把這件事寫在不同的執行緒上)。測試員會瘋狂地想要搞清楚為什麼系統前一步正確,下一步卻壞掉。

# Use Singletons Everywhere

到處使用獨體。可以使用獨體的時候,何必要傳入依賴的管理器。當模組依賴於其他管理器時,就更難測試了。

# Be Defensive – They’re out to Get Your Code!

防禦性地不斷使用assert來阻止那些參數傳進函式與建構子。假如你讓別人傳進一個NULL,那等於是放下防禦罩。那些測試怪咖就是想在外面惡搞你的物件。侵略性地用鐵腕避免這些事情發生。(切記,他們想抓到你這件事絕對不是偏執的幻想)

# Use Primitives Wherever Possible

盡量使用原始資料結構,而不是使用一個整理過後的資料結構。把資料用原始資料結構傳進來,每次需要一個值的時候就自己解析。原始資料讓人們難以了解,也難以存取。我們才不用那些可能是偽裝,空的,甚至是封裝過的物件。

# Look for Everything You Need

盡可能取得全系統的狀態,尤其是取得那些可以讓你的物件看到全系統的掌控權。這會讓測試員不好過,尤其是他想要製造一個測試環境的時候。別害怕取得盡量多的物件,越多越可以製造測試員的麻煩。假如模組叫InvoiceTaxCalculator,就把程式寫成invoiceTaxCalculator.getUser().getDbManager().getCaRateTables().getSalesTaxRate()這樣。別理那些測試維尼告訴你關於置換依賴物件或是最小依賴其他模組的故事。

# Use static initializes

使用靜態的初始值。盡可能在初始化時把事情都作完。想想測試呆頭只是讀入你的類別就把系統搞停會多麼沮喪。

# Couple functional code directly to the external systems it depends on

把程式碼與外部依賴的系統緊密連結。假如程式使用到外部系統,如資料庫,檔案系統,或是網路。確保程式盡量接觸底層。這可以避免其他人以你不想要的方式使用你的程式。(像是只執行2微秒的動作卻必須花上5分鐘)

# Mix Object Lifecycles

混合的物件生命週期,盡量把物件週期搞得長短不一,而且互相依賴。這種會讓人搞不清楚物件是否還存在的事特別邪惡。

# Side Effects are the Way to Go

最好是在運作時製造大量的副作用,越不清楚越好。偏門又明顯不理性的副作用更好。就像增加一層糖衣在上面一樣,讓物件有機會變成不合法的狀態,沒有初始化的成員資料。一旦到達這種境界,別忘記讓人有機會可以呼叫這製造"不合法存取記憶體"或"存取空値"的流程。何必這麼麻煩,乾脆不要使用副作用,直接故意取誤導性的函式名稱來搞混那些聰明的書呆子。

# Create Utility Classes and Functions/Methods

製造一批家族函式,例如假如要處理網址路徑,我們就用字串物件(請回想盡量使用原始資料結構一節)。創造一個用靜態方法的類別如isValidUrl(String url)。別讓物件導向新警察告訴你該另外作一個URL物件。確保你的家族函式還會使用到外部模組更好。

# Create Managers and Controllers

製作一堆管理器與控制器來操縱其他物件,然後把掌控權拉攏在一起。當想要知道SomeObjectManager在幹嘛的時候,就搞不清楚其他狀況了。

# Do Complicated Creation Work in Objects

在物件裡面製作複雜的物件產生流程,別理那些使用工廠模式來建立物件的建議,我們比他們優秀。因為我們的物件有各種不同功能以及數千行程式。

# Greenlight if-branches and switch statements

別怕麻煩盡量使用判斷式,當物件導向牛仔想要用多型來解構物件時,阻止他們。當我們使用判斷式來寫程式,只消把程式像小說一樣全部讀過一遍就懂了。假如使用物件導向,簡直就是變成恐怖的互動式童話書,在類別之間翻來覆去。簡單點只用if就好。

# Utils, Utils, Utils!

不斷寫延伸類別,直到程式噴出獨特的香水為止。反正這些延伸或協助的類別或函式其他人也可以用。先提醒你,那些物件導向警察會告訴你要把功能封裝在物件裡面,就像責任一樣。忘記這些守則,你才是實務上真正解決問題的人,畢竟你有時間壓力趕著出貨。

# Use “Refactoring" whenever you need to get away with something

當想避開責難時就說自己在重構。假如我們想要作某些困難,包含新功能,又不想測試的時候,就告訴他們你在重構,這招可以滿足那些測試導向跟物件導向的呆鵝。而且每次都成功。不要管他們說你得在重構前先有測試機制,或是沒有測試不能加新功能的雜音,先作就對了。

C++特典

# Use non-virtual methods

使用不可覆寫的函式,避免讓自己的函式陷入深度又恐怖的繼承螺旋中,不要使用virtual。這還可以避免測試狂戰士覆寫你的類別。更好的是讓解構子也維持non-virtual。當測試狂人試著作子類別時就會瘋掉。

# Never use pure abstract classes

不要使用純虛擬介面,依賴這些純虛擬介面就會讓測試瘋子到處置放地雷與偽裝你的程式。

# Macros are your friends

巨集是你的好朋友,盡量使用#ifdef PROD與其他編譯的定意切換來讓測試員無法了解真正重要的部分在哪裡。事實上那些程式不到釋出不會真正執行。

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s