雖然作為結尾也還算切題,但仔細想想或許更應該把它放在這系列的開頭?我想這可能是個雞生蛋蛋生雞的問題。如果不先討論我們為什麼要瞭解Flutter這麼多的實作細節和設計理念,很多人可能就不會想看這個對你日常開發很少有直接幫助的系列。但如果不先體驗過這系列中一些抽絲剝繭、打破沙鍋問到底的案例,即使我們試圖解釋為什麼要問為什麼,可能也不是那麼有說服力。
總之,從一而終的,這會是一篇沒什麼架構、想到什麼寫什麼、跟Flutter不完全相關、吃飽太閒可以看的結尾。
在實際工作開發時,須要自己去實作客製RenderObject,或是須要瞭解Hot Relod如何實作才能解決問題,都是非常罕見的情況,但說真的,有時面試就是會遇到一些問題,對日常開發不見得有幫助,但能夠有效鑑別面試者對於技能的熟悉和理解程度。
畢竟當我們問完「StatefulWidget/StatelessWidget的差別?」「解釋async/await/Future?」「InheritedWidget的用途?」之類的基礎觀念問題,如果我們不想從Flutter數百個Widget中,隨機挑選幾個出來考驗面試者的記憶力,剩下能問的也就是關於框架底層的細節、關於設計模式的使用和其背後的目的、或是關於進階程式架構、軟體工程之類的問題了。第三點沒有出現在這系列,也許可以作為明年的題目,但前面兩點相信你在這系列已經學到許多了。
試著想像一下,當你在面試時被問到Flutter layout的觀念,你不但能夠鉅細靡遺的講解整個流程,甚至還能分析它的資訊流動限制如何衍生出了各種演算法最佳化。或是當面試官問「你有沒有用過Provider做狀態管理和依賴注入?」你可以說「嘿,你知道Provider其實既不是在做狀態管理,也不是在做依賴注入嗎?」。不論你面試的是多資深的職位,像這樣深入的研究、分析、理解,必定都為讓人留下深刻的印象。
有時候可能會覺得,瞭解這些對實際工作沒什麼用,但有時候也許只是我們不知道它們有用而已。畢竟在現實世界裡,一個問題很少會只有一個標準答案,而在程式的世界裡又更是如此。當我們面對一個問題時,可能會想「這題簡單,只要用A+B+C就好了」然而到了code review,卻發現有人問「你怎麼不用X呢?」我們可能從來沒聽過X,或在聽聞X時,因為難以想像這會有什麼用,而和它擦肩而過。當然,如果只有多學了一個X,剛好在我們實際需求中發揮作用的機率是相當低的,但如果你學了一大多A,B,C,D,E,F,G...呢?當你對一項技術,從內部細節到外部生態,各層面的理解逐漸累積起來、彼此相乘,它們實際派上用場的機會將會指數成長,而你也就會成為那個在面對問題時,總是能提出更簡潔、更優雅的解決方案的王牌工程師。
另一方面,有人可能會覺得,程式不就是要一層層的抽象,一層層的封裝嗎?Flutter都已經幫我們準備好從高階到低階的數百個Widget了,難道還不夠我們用嗎?我們真的有必要再深入到Element, RenderObject甚至dart:ui嗎?的確,在大多數的情境中我們只需要使用Widget,也只需要瞭解Widget就足夠了。但別忘了,整個Flutter Framework可是從上到下、從Widget到dart:ui,全部開放讓我們繼承、呼叫、使用的,可以想像實際上是真的有許多人有這樣的需求,Flutter團隊才會開放出來讓大家使用。畢竟API越開放Issue越多,Flutter團隊又何必自找麻煩?
好,那我們能不能等到真的須要用到底層API的時候,再來深入學習呢?這就回到了第一段。當我們面對問題時,不見得會知道我們追尋的答案,其實就在底層API裡。
前面提到過,所有套件、架構、設計模式都是為了解決某個問題而誕生的。當然,廣義來說所有語言、框架、類別、函數甚至每一行程式碼都可以說是為了解決某個問題而誕生的,但畢竟我們已經選了Flutter,日常開發中最常選擇的就剩下套件、架構、設計模式這些了。當我們去問它們為什麼的時候,得到的答案自然就是它們想要解決什麼問題。接著我們就可以去思考,這是我們現在有的問題嗎?這是我們可能會遇到的問題嗎?並根據答案做出適合我們的選擇。如果我們其實沒有這樣的問題,那麼無論是多熱門的套件,無論受到多少吹捧,我們都應該很小心的考量它的必要性。
不僅如此,即使我們真的有遇到這樣的問題,也還可以更進一步去詢問,為什麼會發生這個問題,它的根源是什麼,它發生的條件是什麼?我們有沒有可能直接解決這個問題的根源?這樣是會產生其它問題,還是順便解決其它問題?不斷回頭追問為什麼,最後就會形成一條問題的鎖鏈,而我們只要解決這條鎖鏈上,最容易解決的問題,底端的問題也就自然解決了。
以我們在"key是如何影響updateChildren的?"一文中,範例APP所遇到的問題為例,雖然我們最後學到,當children Element間發生位置變動時,可以透過設定key來保存它們各自的state。但其實我們一開始就不要使用整排的StatefulWidget,而是把狀態提升到上面一層,讓下層的children Element保持Stateless,自然就不會有state消失的問題了。
就像我常說的,深入研究Flutter的某些技術細節之後,總是會發現它非常有趣。例如updateChildren那個乍看之下相當可怕的六大迴圈,在我們把它一行一行解剖開來,滿足了好奇心之後,看起來也是相當精巧可愛。而之後當我們發現其實用幾張簡單的示意圖就可以把它解釋個大概,代表自己是真正將它融會貫通時,也是非常有成就感的。其實就我個人而言,這些才是最重要的原因,可以說之前的所有說辭都只是在合理化我花費在這項娛樂上的時間。
這些樂趣,我相信對於能夠讀這系列讀到最後一篇的你來說也是一樣的。工作這麼忙,人生這麼辛苦,如果不是基於對Flutter的熱愛和好奇,誰有那個美國時間看這麼多枯燥的文字,理解這麼多艱深的概念和技術。好奇是人類的天性,雖然並不是所有人都能夠保有它到終老,但可以說人類科學發展史有很大一部,是建立在科學家們為了理解各種現象為什麼會發生,這世界的底層是如何運作,為了滿足好奇心的探究之上。
誰知道呢?也許在你深入研究Flutter從表層到底層,從如何到為何的過程中,不僅能更加精熟的使用整個框架,或許也能激發一些靈感創意,改善框架本身,甚至創造全新的框架!
覺得你說的很貼切也解釋得很清楚,在使用的時候總是會希望能更了解底層是如何實作的,如果只是拿來實作總覺得有點無聊,透過你的文章也讓我這個剛學習 flutter 的初學者獲益良多,希望之後還能看到你的其他文章。
感謝!沒想到這篇也有人仔細看完哈哈。我平常是從來不寫文章的所以可能明年再看看XD 也恭喜你順利完賽!