• 作者: Ash Furrow
  • 原文: http://ashfurrow.com/blog/ios-developer-discomfort

過去幾年來,我注意到一些我所敬重的人們,在所撰寫的程式碼中,有著一些趨勢。他們都是非常聰明的人。

這些人寫的這些程式碼,經常看來有些外來的情調,甚至有點奇怪。

當我第一眼看到以下我要描述的這些程式開發取徑的時候,我感覺不舒服。有些事情感覺不自然,在我過去賴以工作的許多抽象概念,在新世界中變得完全不管用。

這些聰明人通常不會只是出於好玩,所以才提出解決問題的新方案。他們是因為新的方案比較好,才提出新方案。我們不妨一探究竟。

以下列出的,是我所注意到之前讓我覺得不舒服的地方,但是實務上卻幫助我成為更好的軟體開發者。

宣告式程式設計 (Declarative Programming)

我們的第一個例子是宣告式程式設計。我注意到許多有經驗的開發者企圖避免修改物件實體的狀態,取而代之的是使用不可變動的物件。

宣告式程式設計企圖讓電腦 如何 完成目標抽象化,並且關注於到底需要完成 什麼 。這也就是寫一個 for 迴圈與寫迭代函式(enumerate function)的差別

Objective-C 是一們可恨的語言(我個人倒是很愛就是了)。它是一們在物件導向(object-oriented)基礎上的訊息導向(message-oriented)語言,而又是建立在 C 這門命令式語言(imperative language)。呃,不用說,在 Objective-C 裡頭想要讓一般的事情抽象化,也都可以搞得很髒,但是在像是 block 與新的 literal 寫法出現之後,抽象化變得比較容易些了。

如果把宣告式程式設計推到極致,你可以在應用程式啟動時,宣告整個應用程式全部的行為,然後直到應用程式結束,都不用做其他的宣告。

我為什麼開始用它?

宣告式程式設計避免修改物件狀態,可以減少 runtime 錯誤以及各種行為上的問題。而無論是在功能測試、整合測試還是單元測試方面,都讓我的程式碼更容易被測試(之後我們會在單元測試上有更多著墨)。它將我從電腦如何運作的枝微末節中解放出來,把複雜無聊的工作交給編譯器。對於大多數應用程式而言,當中的效能差異非常小,根本不需要額外考慮。

為什麼很難採用?

我開始覺得難以採用宣告式程式設計,是因為它打破了我過去所習慣的事物,我也必須要重新熟悉新的工具。我的程式開發效率短時間內受到了影響,感覺起來我要在我的程式還不成熟的時候就要做最佳化。這讓我很不舒服。

不過,我還是認為這值得一試

相關資源

我之前曾經寫過與 ReactiveCocoa (或簡稱 RAC)的相關文章

如果您對於開始使用 RAC 有興趣,可以閱讀我在上面提到的文章,或是在 NSHipster 上的這篇。此外,所有人都應該讀一下 Rob Rix 的這篇〈後現代程式設計〉

Dot 語法

Dot 語法就是在 Objective-C 語言中,將 obj.property 自動轉換成 [obj property] 的訊息傳遞的語法。編譯器基本上不太關心你用什麼方式寫,但是人們倒是對此引發不少筆戰。(反方正方)。

我看到不少聰明人大量採用 Dot 語法,不僅只是在處理屬性而已,只要這個 method 不需要傳入任何參數,都可以透過 Dot 語法呼叫。當然你也可以完全不用 Dot 語法。

我的個人喜好居於在光譜的中間,是透過 Dot 語法取得數值內容,像是 UIApplication.sharedApplication 或 array.count,但是我不會寫出 array.removeLastObject。

我為什麼開始用它?

我很難說明為什麼你應該在所有取值的地方都用 Dot 語法。我所聽到最好的理由就是,我們從此不用搞懂 header 裡頭到底怎樣宣告method 以及 property,一概使用 Dot 語法就好了。

趨勢是愈來愈多的人使用 Dot 語法。剛開始接觸 iOS/Mac 開發的人,可能根本不知道在 Dot 語法上曾經發生過什麼筆戰。對我而言,要用不用並不重要,只要能夠維持程式風格的一致就好。

為什麼很難採用?

很難採用,主要原因是我習慣使用過去的方式呼叫 method。就跟新的 liternal 寫法一樣,這讓我不怎麼舒服。

此外,Xcode 的自動完成功能,也不會幫你補完像是 UIColor.clearColor 這樣的程式。呃。

單元測試

蘋果在 Xcode 5 當中大力推廣單元測試,雖然說看來也不是很有心(什麼?還是沒有 mock 的 framework?)而我之前也提過很多次單元測試的好處

單元測試就是對構成組成軟體的最小單元做測試。為了可以有效率地作單元測試,你應該把每個部分都寫得很小,避免寫出過大的函式。

我為什麼開始用它?

單元測試的價值是兩面的。一方面,我有了自動化測試之後,我在修改既有程式碼時會更有信心;二方面,我的每個函式都變得更小,抽象化的程度會更高,因為這也是讓我比較容易寫單元測試的方式。讓程式更更簡短、清楚,我相信是不會有人有異議的好處。

為什麼很難採用?

就像上面提到的,Objective-C 是一塊訊息導向、物件導向的泥沼,中間又有命令式的 C。對比物件導向的程式,要測試命令式的程式較為困難。

此外,在 iOS 的 MVC 典範下,除了 Model 層之外,其他部分都很難加上單元測試。在我們想要測試 View 的時候,由於 View 都與 UIKit framework 相依(除非你有辦法把整個 UIKit 都用 mock 物件做掉),而 view controller 又很容易一下子就寫了上千行。我們很難從控制 View 的程式碼中,找出可以測試的控制邏輯。但是,把 MVC 切割出來,可以讓你更容易做單元測試。

Autolayout

蘋果在 iOS 6 之後推出了 autolayout,在 Mac OS X 上則更久了。Autolayout 是一種在 runtime 時讓 UIKit 宣告(又出現這個字了)畫面中的物件關係,滿足需求的方式。

Autolayout 原本的目標是可以創造出一塊讓撰寫畫面佈局變得簡單的神奇之地,讓過去的「彈簧與支桿」(auto resizing masks)完全變成過去式。但現實是,Autolayout 有自己的問題,而且對許多開發者來說,Autolayout 的設定介面並不直覺。

我為什麼開始用它?

事先聲名:我並不熟悉 autolayout。我只有在個人的少數專案中用過,因為要上手真的不容易。不過,我可以看出導入的好處。

如果是透過宣告的方式定義介面,你就可以少去很多要維護的程式碼。Autolayout 可以幫助你建立之前用彈簧與支桿無法表達的畫面佈局。

為什麼很難採用?

我已經很熟彈簧與支桿,而 autolayout 則是全新的,而且讓我不舒服。如果你想做的只是很簡單的事情,像是把 view 放在 superview 的垂直中心位置,用 autolayout 又頂難做的,因為 autolayout 在太多地方都做了抽象化。

現在看來不是個把原本的程式換成 autolayout 的好時機。不過,看來以後也不會有。我已經有心理準備了。

相關資源

請參考 Justin Williams 所整理的 Achieving Zen with Autolayout 這一頁。

結論

為什麼這些寫程式的方式會讓人不舒服呢?不外乎,這些方式是新的,而改變始終是困難的。不過,任何一點小改變,都可以讓世界大大不同。

最近我與一位將採用宣告式程式設計設為高度優先的客戶完成一項 in-house 專案,我覺得筋疲力盡。我覺得一整週都在沈重的壓力下-精神上完全無法進入全神貫注的流動狀態。但不久後,我發現了宣告式程式設計確實有價值。

改變是困難的。或許 iOS 開發社群還是會抗拒宣告式程式設計,就像網頁開發社群過去二十年一般。ReactiveCocoa 可能只會有少部分人用在 Objective-C 開發,就跟在 .Net 中使用 ReactiveExtensions、在網頁開發中使用 Lisp 的人一樣少。

但也可能不會。

我們活在開發工具的黃金年代-任何人都可以選擇最適合他們工作的工具-而我上面提到的開發取境都有確切的好處。它們雖然會讓你有輕微地、暫時地不舒服,但是對你會有長期的好處。

如果你只是因為某件事物你不熟悉,或是這件事物否決了你目前覺得最好的作法,你就棄之不理,你就是在危害自己,拒絕了讓你可以免於無知的機會。無論你覺得你現在一切都好,或是覺得有東西該學,你應該要嘗試學習新的事物。