技術人員在轉向移動開發過程中有哪些經驗和教訓值得大家借鑒?
希望能結合自己的經驗談得具體一些。前端和後端可以分別談。
註:問題來自「知乎圓桌」· 非移動開發者向移動轉型:非移動開發者向移動轉型的主題討論,由CSDN 和《程序員》雜誌總編輯劉江老師提問。參與嘉賓包括:
- 劉鐵鋒 海豚瀏覽器 CTO
- 季逸超 Peak-Labs創始人/CEO
- 覃超 Facebook工程師
- 陳彧堃 友盟技術總監
- 李建忠 Slideidea 創始人
本題已收錄至知乎圓桌 ? 非移動開發者向移動轉型,更多關於移動開發的話題歡迎關注討論。
後端方面請拜讀彧堃同學的回答,非常贊!我就從前端/客戶端說說自己的拙見吧;-)
記得當時iPhone出來後,讓人們看到了一個與傳統的「窗口」完全不同概念的邏輯:界面方面一個應用佔滿整塊屏幕,程序方面代碼也都是在嚴格的沙箱內運行。當時我就意識到這將是一整套全新的規則體系,後來漸漸從表面往深層看,寫了幾年爛代碼慢慢我也有了點心得:
1.淡化文件的存在,而凸顯應用和工作流。
2.盡量避讓主線程/UI線程,避免鎖界面。因為桌面應用鎖UI的話只不過是一個窗口,而移動應用會給人感覺是「手機」這個整體掛了...
3.能迅速完成的操作/運算就不要指望後台,自己的程序隨時可能被kill掉。後台只留給VOIP、網路操作之類的。
4.盡量加快啟動速度。移動產品用的頻繁,但單次使用遠比桌面要短,所以不要出現Photoshop那樣讓用戶傻等的情況。即使用個「假象」也要讓用戶覺得啟動挺快的。
5.同一個功能最好有多種交互/操作方式。不像Windows一統桌面江湖,現在各個版本的android、iOS用戶之間使用習慣迥異,最好能讓人們的習慣都能work。
6.最好不要讓UI控制項太顯眼(比如街機遊戲中碩大的搖桿遮住了人物),但也別太隱晦(猛獁瀏覽器4,哈哈哈)。
7.用戶其實很在意耗電和發熱量,桌面用戶從不在乎…
8.很多功能別人說做不到或說平台不允許不開放的時候,總有人用匪夷所思的奇葩手段實現了…
個人拙見請勿輕信哈~
還有個最近的風氣,個人覺得有些糾結:每次各種app更新完後,一啟動就是幾幅小清新圖片+幾句看不太懂的憂桑文字,其中最後一張帶個按鈕"開始體驗"...而且不點掉"分享到微博"的話你就中招了...應邀作答,拋磚引玉了。
對於技術人員來說,怎麼從互聯網向移動互聯網轉型?基礎技術是相通的,C++/Java/LAMP這些基本功,如果拿到移動上就不能用了,碼農的日子未免太苦逼。
似乎「技術轉型」一說太重,我更傾向於說「工種轉型」。
技術為產品服務,產品依託於生態系統。第一,在移動生態系統中,手機對於人的可識別度是超過傳統互聯網的,傳統的cookie跟蹤方法帶來用戶定位的模糊性,給數據清洗和挖掘帶來了很大的限制。而在移動上,imei和udid是更乾淨的用戶標識方式,基於此,可想像的數據挖掘空間更大。第二,移動設備佔據的是用戶的碎片化時間,用戶行為更豐富;第三,用戶目前還習慣於一個應用只干一件事,需要App非常體貼用戶才能長期佔有用戶的時間。
舉個例子,地圖應用中的Local Search,用戶隨時根據自己的位置查詢附近的餐廳POI(Place of Interest)。這個在Web上當然很常見,但移動環境中用戶位置高頻變化,越來越習慣隨時隨地查詢,這就難搞了。甚至出現了新的查詢方式:查詢周圍的人。人的位置不斷變化,給後端查詢的索引系統在時間和空間複雜度,擴展性等指標提出了更高的挑戰。Quad-Tree,R-Tree這些高維空間索引結構也越來越多應用在工業產品中,MongoDB和MySQL對R-Tree的支持就是例子。
這三個特點集中體現在社交應用或者包含社交元素的應用中,這和友盟最近的觀察是不謀而合的:移動應用的社交化正在成為趨勢。社交元素的加入,使移動應用的社區化和用戶粘性得到大幅提升。矽谷一個投資人Fred Wilson以前提了一種說法叫「Mobile
First Web Second」:http://www.avc.com/a_vc/2010/09/mobile-first-web-second.html,最近他又跳出來寫了篇文章叫「Rethinking
Mobile First」:http://www.avc.com/a_vc/2012/12/rethinking-mobile-first.html,就是在強調移動對於消費者和社交導向產品的重要程度,這和我們的觀察契合。
第三方信息抓取技術,個性化推薦,和社交關係圖譜
在社交化之後,用戶的興趣和標籤可以從站內行為分析,也可以通過多個社交平台的API取得用戶公開的數據進行交叉挖掘和分析,這是個性化推薦的基礎。個性化推薦會讓應用變得情感化,一個讓用戶覺得有感情的應用,當然在設備上留存的時間也變長了。每個應用都有自己的用戶體系和用戶行為,有一套自己的用戶模型。但不能只依靠站內行為,原因有二:
- 站內行為不能解決冷啟動問題
- 社交平台上(如新浪微博,騰訊微博等)上有大量的用戶數據,和站內行為互補,甚至遠遠超越站內用戶行為。用戶的挖掘工作可深可淺,淺的簡單抓用戶自定義標籤,把設備和人等同起來;深的可以考慮:第一,為用戶標籤建立語義化模型。一堆標籤不足以代表用戶,想了解一個人需要建立層次化,歸類化的用戶屬性模型;第二,考慮設備和人的多對多關係,目前主要指單用戶使用多設備,手機,平板,用戶行為有很大差異;第三,區分用戶的轉發和原創等細節行為的語義區別;第四,應用內用戶屬性的擴散挖掘。社交用戶比例不太可能是100%。但可以通過已知社交用戶數據和站內信息交叉來擴散,用戶會和信息交互,會產生大量的用戶和信息之間的關係,也初步構建了站內的社交關係圖譜,站內社交關係一旦生成,便可以將大量的社交信息擴散到非社交用戶上,成為個性化推薦的基礎。談到個性化推薦,就不得不提Amazon在十多年前提出的協同過濾,經過這麼多年的發展,目前已經成為工業界個性化推薦的標配技術,以及學術圈中一大研究方向。協同過濾的無數變種和改進也被廣泛應用在不同的產品中,但殘酷的是,推薦演算法的應用是個騎驢找馬的長期抗戰過程,會參合進用戶屬性,用戶習慣,用戶歷史行為等很多因素,是需要長期反覆訓練才能不斷完善的。
簡單來說,用戶挖掘關鍵在於站內用戶行為分析,用戶—內容的關係圖譜,用戶—用戶關係圖譜。
碎片化時間,複雜環境使用體驗,和海量數據根據友盟最近的統計數據,移動互聯網真正進入高速發展不超過3年,國內Android設備到達1.4億,iOS設備到達6千萬,用戶增長速度遠高於PC。移動設備佔據了用戶的碎片化時間,用戶的啟動次數和使用環境更為複雜。這對開發人員有幾點考驗:
- 客戶端適配複雜使用環境,比如要考慮強光弱光和交通工具振動環境下的可用性。
- 用戶行為構成大量流數據,對後台的數據處理,分析,以及產品迭代都造成了更大壓力, Hadoop被廣泛應用在移動系統的分散式數據處理工作中,另外近期Google的Dremel和Cloudera的Impala也在為更實時的海量數據查詢系統探路。
- 用戶使用時間的分散也會給運維人員施壓。根據友盟的數據報告,夜裡22時,用戶的使用會達到高峰,大量的使用會持續到凌晨2點。留給運維的用戶透明時間明顯縮短了,這也要求開發出更加自動化,智能監控的運維繫統。
- 產品的開發模式要變革,用戶對於應用和內容新鮮感的需求更強烈。Scrum,測試驅動,站會等不一定滿足快速迭代的需求,但單槍匹馬不可能保持持續的戰鬥力,所以需要團隊在打磨中能摸索出符合自己產品的開發方式。
看上去我談的是偏後端數據處理,好像在PC和Mobile上沒什麼純技術區別,這就見仁見智了。總的來說,用戶標識方式乾淨,使用戶挖掘更有想像空間,所以用戶數據挖掘這個工種會更重要;用戶使用場景複雜,讓Mobile的數據更豐富,處理,分析和反饋的實時性需求更高。使用頻次和環境複雜度的量變引起技術需求上的質變,這就是跟PC的大面上的技術區別。
說「轉型」可能我還不夠資格,因為我從工作開始就直接在做mobile,只是之前在大學裡面搞過一些程序競賽和TopCoder的組件開發在桌面電腦上面,所以從一開始我就是還沒完全定型的程序員,基本上什麼東西都需要從頭學習。第一次真正開發mobile程序還是在CMU讀master的時候,那時做畢業論文,研究Android系統的安全性,於是第一次裝了Android的文檔和自己照著樣例寫了一個,感覺還挺不錯(其實就是寫Java)再後來就是進入Facebook後,從Boot camp畢業後就進入Mobile team,當時公司裡面大部分人還是搞PHP的,但是公司鼓勵大家做Mobile開發,說是以後的方向,於是我從一入職就開始了全面的Mobile開發。
個人的經驗如下:
技術方面: 我個人感覺Mobile上面更加註重程序的效率,程序要簡潔,速度快,同時複雜度要盡量低。另外就是在寫程序時具體要注意的事項,由於Mobile的處理能力不及桌面電腦,所以要格外注意將非UI相關的操作放入到worker thread。相比開發桌面程序或者web app,亦或者是現在的iOS或者Android開發,MVC模式已經深入人心,它的本質就是把代碼按照其做的事情分類,坐不同工作的代碼在不同的模塊里; Thread分類和它也類似。剛開始進行Android Facebook和Facebook Messenger開發的時候,我們的Tech Lead -- Jon Perlow 就在code review中不斷指出我的很多操作還是像桌面程序一樣放在主線程中,而Android下主線程即 UI thread,這樣就很可能降低程序的流暢性。而且很多時候,也其中蘊藏著一定的平衡和折中。因為移入worker thread後,程序會出現很多async method call和callback function/class, 這樣對代碼的可讀性和以後的維護都是挑戰,同時線程的切換和對於共享資源的同步也是會帶來性能的損失,所以在寫的時候要具體問題具體分析。比如說大規模I/O操作和上百萬次的循環,自然不用說;但是在很多情況下,就沒有如此明顯吧,比如說判斷一個文件是否存在, new File(getDucumentFolder + "/xyz").exist() 也算I/O操作,那到底要不要移入worker thread呢?另外很多時候,你最開始的函數裡面,可能操作非常簡單,就直接在Main thread里就可,可是後來其他人在refactor的時候,將這些操作放開到好幾個function裡面去做,然後在以後的版本中,由於加入了新的feature,每個function裡面都比之前要做更多操作的時候,就逐漸逐漸地讓Main thread的負擔加重,搞到最後給用戶的感覺就是這個App功能是變多了,但也越來越笨重,越來越容易crash。所以說,不要在UI thread里做事這點,想必只要智商上80的人都懂,但是真正要執行的時候並不是如此得顯而易見,而同時,公司里的項目都是多人作戰,每個人一般都著眼於自己做的那一塊,這樣很容易就造成最後UI Thread裡面的工作量遠比開始設計的要多。
現在主要的手機平台就是Android和iOS,所以建議兩個都要去了解,然後專註於一個平台。如果Android的話,除了看Google官網外(http://developer.android.com/training/index.html ), 很多時候當你具體要調用一個API,但是文檔上面有疑惑的時候,最好的辦法肯定還是能回到代碼裡面去確認。通篇瀏覽Android的代碼肯定不現實,我個人(也是公司裡面)覺得最有用的辦法就是安裝plugin:https://chrome.google.com/webstore/detail/android-sdk-reference-sea/hgcbffeicehlpmgmnhnkjbjoldkfhoin ,然後搜到文檔後,頁面上直接有一個鏈接 (View Source)來方便查看代碼。回到上面那個線程切換的問題,Android有三種辦法:AsyncTask, Handler, Executor. 在代碼裡面(還有Stack Overflow上面的討論),AsyncTask是最差的辦法,它屬於Google自己加入的一個Hack,大量在自己的Android App裡面使用會發生阻礙程序性能的奇怪問題(因為你對它的worker thread pool沒有任何控制);Handler比較簡單,適合將單個任務快速丟到另外的thread裡面執行,但是從源代碼就可以看出Handler本質上也是在調用executor。最後就是Executor自己了,它的壞處是比較複雜,不注意容易出錯,但是好處就是性能好,而且功能強大。可以自己定義queue的屬性,指定thread pool的大小,和篩選並處理
或者取消還沒被執行的任務等等。所以只有在源代碼裡面去確認後,才會對每個模塊在使用有直接和全面的了解。這樣就能理解為什麼公司裡面Android的編程規範裡面來一句「Don"t use AsyncTask"是什麼意思。(很多人問我為什麼不能用AsyncTask,其實在Android API的document裡面就有http://developer.android.com/reference/android/os/AsyncTask.html#execute(Params...) , 看它自己的注釋。另外還有一個blog:http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html ) 多提一句,如果兩個平台都做的話,還可以比較在iOS下面對線程切換的做法,iOS上鼓勵的是使用GCD (grand-central-dispatch)。他們各有自己的特點,但是個人認為iOS的GCD更加簡單,也更加符合人的思維。
另外就是UI方面,我做過Facebook Messenger for iOS的UI,但是設計畢竟不是來自本人之手,所以只當是自己的拙見。個人覺得UI越簡潔越好,另外就是在設計UI的不要進入誤區:認為app的Android版本和iPhone版本UI要一模一樣。還有一些自己在做UI的時候,designer給我的細節性的建議:「比如text一般加一個pixel的半透明的shadow「, 按鈕(透明)的實際大小一般比貼圖再大一些,這樣更方便用戶觸摸。
上面都是在討論的時候,即興想到的東西,沒有太多整理。不過這兩年在FB的打磨讓我覺得最重要的不是你的技術多牛,寫代碼寫得多快,而是適應力要強,能夠也願意push自己去轉型。我見過不少人,之前對某一技術或者某一領域爐火純青了,就一直想呆在自己的領域裡,說是精益求精也好,說是吃老本也好,更有甚者就是想用老本的技術來用於新的領域。Mobile上面跑HTML5的離線App我覺得就是其中一個,具體細節我整理一下,放到另外一個問題里。因為具體的開發場景不一樣,目標的讀者的經驗各不一。因此,沒有具體分享特別具體的技術經驗和教訓,分享一點轉型過程中,所需要補充的知識點和邏輯上的轉變。
移動開發和PC上的開發帶來了哪些不一樣?
在我看來,從2002年之後,傳統桌面的開發者基本都轉向了J2EE/.NET/LAMP等以Web技術或者伺服器端開發技術為主的開發方式。使用C/C++/MFC/Delphi等開發C/S模式的用戶越來越少,甚至工作的需求也開始變得越來越少。
這樣在技術體系上,開發者的經驗開始基本上覆蓋在:
- HTML + CSS + JavaScript
- 各種腳本語言(PHP/http://ASP.NET/JSP/Python/Ruby)操作伺服器API
- 伺服器數據處理邏輯(O/R Mapping, 資料庫連接池,各種如AOP等設計模式,甚至DSL等等)
- 大型伺服器的架構設計(分散式架構,各種負載均衡,伺服器連接優化)
- 資料庫(分散式資料庫,事務處理,大規模數據的存儲、查詢優化)
- 大數據處理(Hadoop, Hive)等等。
那對於移動開發上需要什麼?
不管是Android / iOS /WP , 其實對於開發的需求上逐漸回到了2002年之前,大概類比MFC/Delphi的時代,更加合適。
移動開發者的技能需求發生了轉變,需要的經驗變成了:
充分理解各移動平台的進程架構和程序生命周期邏輯(程序啟動,程序被系統suspend/kill, Services)
- 界面設計(各種UI控制項,事件處理)
- 數據處理邏輯(客戶端緩存、多線程並發)
- 網路數據處理
- 平台相關特性(系統API調用,系統通知機制等)
- 各種性能處理。
因此,在學習的路線和需要的經驗上有了不同。
如果需要從非移動開發者往移動開發者進行轉型,哪怕同樣使用的是Java語言,需要的就是了解不同的庫以及處理不同領域的具體問題。
在移動設備的開發上,我歸結為三大類問題:性能的問題,界面響應的問題,產品的穩定性。這些是技術人員可以需要最為注意和保障的。
從桌面端轉向移動端,一定要認識到二者不同的側重點。桌面端包括web更側重於邏輯複雜,高級的任務,而移動端的娛樂性明顯更強。
就從操作方式說起吧,桌面端主要靠滑鼠鍵盤和touchpad,所以操作精度要高得多,很容易將很多功能集成到一個界面里;但同樣的思路就完全不適用於移動端了(反例我是實在想不起來了,大家可以幫忙想想),相信一個cluttered ui的app,就算功能再強大,用戶盯著你的界面超過3s就會頭暈,點擊某個button要點好幾下才會成功,也必定是一個糟糕的app。
那什麼樣的操作方式是適用於移動端的呢?ListView的滑動操作就是一個很好的例子,不需要用戶任何的思考,只需順著期待的內容出現的方向滑動,這樣intuitive的設計便是王道。類似的設計還有來自Tweetie的下拉刷新,Android 4.0引入標準庫的ViewPager等等。上述的操作都有一個共同特點——手勢操作。既然移動端(不管是手機還是平板)是拿在手上的設備,那手勢操作成為其殺手鐧就毫不奇怪了,自然也就成了區分移動端和桌面端的一個重要特質。PeakJi大神的猛獁瀏覽器和輸入法(忘記名字了)同樣也體現了這一點。
有了簡單直觀的手勢操作,還有一個不得不提的feature——push notification。用戶很懶,一台機器裝了上百個app,可能一個月你的app也就被打開一兩次,這當然不是你希望看到的。如果你的app是網站客戶端性質的,那麼push notification就是一個很好地利器了。怎麼做呢?我總結了下面的流程:
1. 與社交網路連接,獲取用戶資料,分析用戶興趣
2. 記錄用戶在你的網站或客戶端的使用習慣,逐漸逼近用戶真正的興趣
3. 根據得到的用戶興趣,推送他感興趣的內容
可以看到,不僅僅是「通知」那麼簡單,像新浪微博那樣的,一天一條的palm news,多了只能讓人感到annoying,並不能起到和用戶很好的溝通的效果;只有推送用戶感興趣的內容,才會引起他們的注意,增加你的app在用戶心中的權重。
最後一點我認為很重要的,就是consistency,和操作系統要保持操作習慣的一致性。比如左上角的返回button,Android 4.0的ViewPager滑動換標籤等,這樣做最大的好處就是降低了用戶的學習成本,讓你的app和OS融為一體。當然在OS的大框架下,也不乏有新意的app,比如Android下的一款類siri應用Maluuba,大膽地採用了Metro風格的設計,但操作起來並不會覺得陌生,最大的原因就是ViewPager的滑動操作被保留了下來。這樣的例子還有很多,一時想不起來了,歡迎大家補充。
話癆打開了就有點收不住了,就這麼多吧。千萬要注意自己的身體!!!!!
千萬要注意自己的身體!!!!!
千萬要注意自己的身體!!!!!
推薦閱讀:
※高速移動上網推行普及的瓶頸是不是資費,4G LTE 可能降低資費嗎?
※互聯網企業為什麼要研究《三體》?
※為什麼有的飛機上能上網?
※Google Latitude 為什麼沒火起來?
※為什麼獵豹安全大師受到谷歌嚴懲,被 Google Play 全球榜單除名?