Xcode autocomplete真慢!高效Swift類型配對Code Style

當你的project慢慢變大,你必定抱怨過Xcode慢慢變得慢慢起來。

有沒有想過那是因為Xcode開始開始看不懂你寫的Code呢?

在此先「溫馨提示」,「看不懂」是依賴於臨界點,當你突破和沒突破的那一線之間,所有問題才會一次爆發。

好了,正正經經說內容。

Swift 是一門強類型(Strong typing)的language。而何謂強類型呢?便是萬物皆有分類 ,不一定是Class,可以是Structure、Enum、Tuple、Function、Protocol⋯⋯

而Swift的type哪裡也在,但你有很多時候也沒多看見它。那是因為Swift有強大的類型推斷系統,讓你寫Strong typing的時候也能像寫Weak typing一般舒適自在有如在海邊緩步,迎著海風,咳咳⋯⋯

回到正題,Type Casting是Swift的利劍,可是CPU這身份卻未必跟得上大招連連的對陣。如果一個程式(其實是Module,後述)之內有過多(或複雜)的類型及推斷,LLVM便很容易會飛上天去。

你可能會問,有這麼複雜嗎?如果你不介意長文,請看:

http://www.cocoawithlove.com/blog/2016/07/12/type-checker-issues.html

別看是Swift2 的內容,即使O(n^2)的問題進化到O(n)的解,亂用n次,效率是相等的低下。 ~ Matthew Lui

或者有個簡單的例子你看:

func + (lhs: Float, rhs: Double) -> Double { ... }
func + (lhs: Double, rhs: Int) -> Double { ... }
func + (lhs: Int, rhs: Double) -> Double { ... }
func + (lhs: Double, rhs: Int) -> Int { ... }

let i: Int = 1 + (1.0 + (2 + 2.3))

請問以上expression有沒有有效的解呢?

你的程序內部有越多很多很長的類型鎖鏈(Type casting chain),便越容易觸發類型要重新計算。

所以有時候,當你將一些expression分拆作多個表達式,限制其解,其推斷難度低了,明明autocomplete 失靈的場景,突然又function了(或者相反,很看類型基制)。

那麼當大家知道界限在哪,便容易迴避。

不是說放棄typecasting的妙處,但為了長遠效率,把類型變化作為設計的考量之一卻十分重要。

這裡有一些簡單的準則,不費多大功夫便有成效:

1)使用Linter,規範的作用保證人類理解的難度,也某程度控制了Compiler理解的難度。

2)顯式Generic type類型。試想像Array<T>經map T -> U 而 T -> U其實是另一Generic function的其中一個解,當鏈一長,類型轉換要面對的變數便多了。有時什至會在使用時的類型去嘗試重新推斷,久而久之,可想而知。

3)簡短而有效地轉換類型。 又例如mapping,如果其body內有大量分支,type system要嘗試的分支便會幾何提升。這裡最簡單的做法是顯式聲明返回類型,但我更推薦把類型轉換和大量邏輯判斷分開。

4)減少type⋯⋯不是說該用不用,但減少重複的type或限制type的能見度是極有效減低compiler負擔的舉動。

5)Embedded type的level不要深,特別是外界會觸碰到的。考慮使用protocol把他展平。

6)Module。把類型推斷盡可能地封印在Module內,是限制類型的其中要點。

7)Contribute to Swift!

沒想到特別結語好講,以上。