看板 Soft_Job 關於我們 聯絡資訊
純粹看這篇 #1FS87xEJ (Soft_Job) 認真看了一下 How to Write 3v1L Untestable Code 這份文件,感覺真是超惡搞的. 原文 http://googletesting.blogspot.tw/2008/07/ how-to-write-3v1l-untestable-code.html http://tinyurl.com/95fhyh5 有些翻的不好就請見諒啦 How to Write 3v1L Untestable Code(如何寫出邪二的不可測試程式碼) 本文章列出那些會幫助你寫出不可能可以測試程式碼的守則,或是可以避免那些技術來測 試你的程式。 # 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與其他編譯的定意切換來讓測試員無法了解真 正重要的部分在哪裡。事實上那些程式不到釋出不會真正執行。 -- "May the Balance be with U"(願平衡與你同在) 視窗介面遊戲設計教學,討論,分享。歡迎來信。 視窗程式設計(Windows CLR Form)遊戲架構設計(Game Application Framework) 遊戲工具設計(Game App. Tool Design ) 電腦圖學架構及研究(Computer Graphics) -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 1.164.86.122 ※ 編輯: NDark 來自: 1.164.86.122 (10/03 22:12) ※ 編輯: NDark 來自: 1.164.86.122 (10/03 22:13)
yauhh:好有故事性的一篇文章. 講了非常多東西 10/03 22:30
SansWord:可是有些事情不是應該做嗎?例如be-defensive? 10/04 00:30
cobrasgo:超惡搞的XDD 10/04 08:55
snaketsai:#define double int //Don't ask ; it's scary 10/07 11:47