一個移動端開發者,對未來的思考

本文轉載自微信訂閱號:鴻洋,有啓發,故轉載。
原作者:舒大飛,鏈接:https://juejin.im/post/5e0d85155188253a8b42e5ba

平常都在寫技術類文章,今天寫篇作爲一個移動端開發者對過去一年的總結和思考吧,既是對過去的回顧,也是對未來的思考。

2019

這一年對於我來說,當然最多的時間還是花在工作上。對於移動端開發來說,2019年依然是動盪的一年,各種跨平臺技術依然層出不窮,原生將死的論調依然在各大公衆號熱炒和營銷。

這一年,隨着工作經驗的提升,自己對技術的看法和對未來的方向也發生了些許改變,分享一下自己這一年的總結與反思吧。

一. 這一年都做了什麼?

這一年還是挺忙碌的,不管是純業務開發還是技術改造或者是對我們產線現有問題或者痛點的解決方案都有一些個人的輸出,技術確實不能是半空建樓閣,依託具體的業務問題,以技術方案去解決,是更加良好的循環和沉澱,還有很多東西值得去提高去學習。

1.上半年產線中的幾個複雜頁面的流暢度在版本迭代中一直會由於開發的不注意導致頻繁出現反覆,分析下來根本原因是由於缺乏必要的監控以及可持續的優化手段,所以2019Q1在業務需求之外主要就是實現了產線內部對於用戶流暢度的監控以及優化。

主要包括:debug下幀率的監控、上線前主流程流暢度的自動化測試、線上用戶真實流暢度監控、實現耗時方法排查工具:MethodTraceMan、一些收益比較大的流暢度優化等,主要目標是從監控到排查問題工具再到卡頓解決形成一個閉環的方案。

https://github.com/zhengcx/MethodTraceMan

對於流暢度監控與優化歸納成文,有興趣的可見:App流暢度優化:利用字節碼插樁實現一個快速排查高耗時方法的工具

2.對於內存上的問題,我們產線其實很早之前就碰到了,線上爆出可觀數量的OOM,當時我對我們app做了一次內存上的分析與優化,效果還是非常明顯的,當時對分析和優化過程做了記錄:

實踐App內存優化:如何有序地做內存分析與優化

後續的幾個版本中我們發現OOM的數量大幅度下降,但是依然會有少數的OOM上報,分析下來發現這部分發生OOM的機型大部分單應用最大可用的內存只有64M,也就是說有部分很老舊的機型內存實在小,所以我們最後上線了內存適配方案,也就是對不同內存大小的機型做不同的內存使用方案,比如對於一些老舊內存非常小的機型,選擇適當去降低圖片的質量,關閉一些花哨的動畫,對於一些大內存的使用更加謹慎,更加及時的去做一些內存的回收等等,收到了不錯的效果。

後面對於內存方面的優化一直沒有補充到上面的那篇文章裏,等有空了,補上後續的一些內存優化手段,供交流分享。

3.Google近年來對Jetpack進行不斷的補充和完善,我也對Jetpack進行一定的學習和引進,特別是lifecycle組件等已經在我們產線中使用很久了,我們使用響應式的編程方式來組織或者重構問題代碼,解決了一些我們產線現有的問題,提高了效率。

還是那句話,不應該以新或者舊來看待技術,而應該以他是否能提高你的效率以及解決你的問題的維度來看待他。

對於響應式編程以及lifecycle組件的一些總結與看法: 響應式編程在Android 中的一些探索
https://juejin.im/post/5c026915f265da615876e42e

4.這一年也對團隊在代碼規範和約束方面做了一些努力,在團隊開發過程中這方面其實非常重要,如何保證代碼質量以及穩定性直接影響了上線app質量,所以我們團隊在挺早之前就建立了警告和報錯的責任制,即上線前每個人要清掉屬於自己的警告和報錯,當然主要還是靠Lint。

但是有一些Lint無法觸及的團隊內部的一些約定,這確實在版本迭代中由於開發的疏忽在線上引起幾次問題,基於這個問題,主要的目標還是希望可以在開發階段就能在編譯器中對於團隊內部約定的規則進行報錯或者警告提示,於是我發起並實現了一個自定義Lint規則的項目,主要是對Lint的拓展,基於AST樹,去實現一些探測器。

比如可以配置禁止使用哪些類,哪些方法,同時提示解決方案,團隊成員也不斷的拓展和自定義規則,現在這些我們團隊內部自定義的規則已經和Lint警告一起作爲我們上線前需要清理的問題。

對於如何實現自定義Lint規則,其實網上有很多資料,有興趣的同學可以看看

二. 技術深度 or 技術廣度

一年是漫長的也是短暫的,這一年團隊全面切到Kotlin開發,自己個人也關注學習了ReactNative和Flutter,同時對JS以及React等前端技術做了一些學習,技術上個人想法是爭取往所謂的T型技術人上去努力吧。

又是那個老生常談的問題,技術是重深度還是廣度,對於這個問題,這一年也有了更深的看法,技術就像是一棵樹,在頂部葉子上各個領域看似毫不相干,但是在一個領域越往下深入,各個領域相互交錯到的知識或者設計方式就越多,所以技術深度和廣度並不是對立面,對技術深度的探索不僅有利於你在特定領域有更深理解,更加可以幫助你輕鬆切換到另一個領域。

特別是像前端的各細分領域的工作,很多領域的知識背後都殊途同歸,而技術的廣度也不是有的人說的那樣不堪,在有技術深度的基礎上,去拓展自己的技術廣度,其實大大有利於你對相關技術更深更飽滿的理解。

在技術廣度方面,舉幾個小例子,比如做Android一直用的是java的時候你可能很能想象會有像Kotlin中拓展函數這種看起來像可以給類動態添加方法的功能,但是如果你對JS有一些的瞭解的話,利用原型其實JS一直就可以很方便的實現這種動態添加方法屬性的功能,當然與Kotlin背後實現的原理完全不一樣。

再比如Android開發中我們實現異步的方式從回調方法到RxJava這種解耦的鏈式調用再到Kotlin協程這種看起來同步的代碼效果,是不是和前端領域實現異步從回調方法到Promise再到aysnc await的歷程挺像的。

不斷的對比和思考,更能夠碰撞出不一樣的火花,比如前端領域大火的響應式UI以及狀態管理模式Redux,好在哪裏,如果移植到原生開發會是什麼樣的形式,會有什麼樣的好處和效果,又有哪些差異和限制?

學一樣新東西時,或多或少慢慢的就會看到原來你已經掌握了的技術的影子,技術的廣度可以幫助你對技術有更深的思考和理解。

技術的深度有利於你更輕易的切換到新的領域,對於我個人而言,這種例子有很多,比如在學習Binder的時候你會發現跨進程通信的本質就是在用戶態的進程間無法共享內存實現通信,而在內核態卻可以,也就是說在用戶態每個進程就像是一個孤島,聯想到幾年前團隊在做app組件化的時候,解耦完後每個產線組件也像一個孤島一樣互不依賴,那最終是怎麼實現通信的呢?

我們把每個組件先在一個數據鏈表裏註冊,之後要通信,由router中間人先在數據鏈表找到對應的目標組件,然後調用目標組件裏的方法實現通信。

那麼binder是怎麼實現的呢?

其實我覺得很相似的,只不過binder將這個所謂的數據鏈表維護在ServiceManager,當然binder要複雜的多,因爲Client、Service、ServiceManager三者處在不同進程,所以兩兩之間每次通信都要經過將通信數據拷貝入內核態的biner驅動,在binder驅動的數據結構裏找到目標進程的對應節點,然後將通信數據放入目標進程節點,之後喚醒目標進程,開始解析並處理,最後將結果返回給Client進程。

這其中還涉及到一個點,每次一個進程將通信數據拷貝入內核態後,自己就會開啓一個while死循環等待回覆,那麼這個和handle消息隊列裏的死循環設計是否一樣呢,是否也是在沒有消息的時候利用epoll實現阻塞呢?

在對一個知識進行比較深入的學習時總是會時不時冒出其他知識的關聯和疑問,也有了更多的思考。

當然以上都是我的個人看法,並不一定準確,都是基於個人的認知的基礎上有感而發的,其中有認知上不對或者不認同的地方還望海涵。

三.解決方案 or 技術難點

這一年,對於技術的看法也發生了一點點改變,有時候做研發做技術會陷入技術怪圈,過分的追求或者陷在技術的難度上,而忽略有時候直接有效的解決方案纔是最有價值的,解決方案是最終的目的,而技術只是工具。

學會不僅僅是鑽在開發角度看問題,跳脫出來,站在用戶角度,站在產品角度,或許會有意外的收穫,這一點我也在不斷努力中。

舉幾個小例子吧,比如早些時候在做一個主流程複雜頁面的TTI(用戶可交互)時間優化時,顯然目的就是降低用戶進入一個重要頁面的等待時間,用戶等待的時間越少相對來說轉化率就越高。

所以從技術角度可能馬上就開始想:

  • 怎麼提高Activity啓動速度?
  • 怎麼減少網絡耗時?
  • 怎麼優化UI渲染速度?
  • 這些做完還不夠,還有沒有黑科技?

但是如果你跳脫出來,站在用戶的角度,他只要我進來能最快的看到內容就行,他不關心你是什麼高深技術優化,所以最終其實最有效的方案是在上一個頁面加一個預加載,可以實現大部分用戶進入下一頁面可以直接看到內容,大大降低TTI時間(當然並不是所有頁面都適合預加載,要自己平衡和評估,這裏只是舉個例子)。

做個預加載,基本沒有技術上的難度,但是對用戶的實際體驗幫助很大。

當然技術上的難度是你需要具備的素質,這些知識到了優化瓶頸的時候都很有用,但是在另一維度也要明白解決方案纔是根本,站在更廣的地方看問題才能收穫更多。

另一個小例子,相信很多團隊都受困於線上的空指針異常問題,這些都是實實在在的崩潰,對你的用戶可能造成很差的影響,很實在的損失。

所以如果去規避屢禁不止的空指針異常呢?

當然Kotlin空安全另說了,如果是java開發,各位一般都是怎麼來規避這類問題的?

我們團隊從早些時候開始,建立了一個服務專門每天跑項目的Lint檢查,跑完將警告彙總分配到對應的負責人身上,並郵件告知他,直到上線。

幾個版本下來,整個團隊都養成了上線前清空警告的習慣,空指針異常基本沒有再發生。這個方案基本和技術難度沒有關係,看起來很簡單的一個事情,但是實踐下來很切實的解決了問題。

這是今年我對技術的一些思考吧,仁者見仁,智者見智,主要就是想說希望深入學習技術的同時有時候也要嘗試跳脫出來,站在更多的維度上看問題。

四.原生開發 or 跨平臺技術

這一年跟着跨平臺技術的浪潮,自己也關注學習了ReactNative和Flutter,當然都不是All in狀態,感受一下這個東西,明白他們的原理和運作方式,寫一些個人小app感受一下。

這些跨平臺技術的層出不窮讓市面上原生將死的論調隔幾天就會營銷一波,但是其實如果你仔細想想或者稍微瞭解一下原理的話,就算是跨平臺做的比較徹底的Flutter(完全自己實現一套閉環的底層UI渲染)最多也只是接管了各平臺的View體系,而原生開發需要的知識不僅僅是UI開發,站在Android系統的角度,我們需要學習的東西太多了,而UI部分只是一部分,Flutter View也是放入在Activity裏去運作,很多原生開發的知識並不會過時。

當然不可否認,有一大部分的需求可能僅僅需要UI開發,所以我覺得原生開發不會死,但是原生UI開發會面臨挑戰。所以學習更加深入的知識,不停留在淺顯的UI開發,會是一種選擇。

2020

對於2020年,自己的很多目標和想法其實在上面的思考與反思中也有提及,比如在技術深度和廣度上繼續努力,爭取成爲T型技術人,還有就是希望自己能在關注技術之餘,學會站在更多維度上去思考解決問題,特別是一些產品思維。

當然去年在Github上開源了我用來排查耗時方法進行流暢度優化的工具:
MethodTraceMan ,獲得了一些star支持,很感謝。

https://github.com/zhengcx/MethodTraceMan

做技術有時候是無趣的,所以要多給自己找點樂趣,希望2020年有好的想法還是可以多在Github上分享。

另外說了這麼多技術學習相關的,莊子說吾生也有涯,而知無涯。以有涯隨無涯,殆已。

新的一年在工作學習之餘還是多鍛鍊身體,多放鬆心情,多享受生活。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章