2015 移動技術白皮書

(一)Android篇

這裏我不談Google IO大會的各種新概念新思想,不談Android 5.0和高逼格的Material Design,那些都是浮雲,熱鬧過後,能沉澱下來用於App應用的乾貨並不多。我只談這一年來,我認爲Android技術界最激動人心的三件事。最後再聊一聊八卦。


首先是插件化技術的百家爭鳴。在此之前,關於Android插件化的介紹鳳毛麟角,Android程序員即使想去研究也無從下手。2015年,幾家大的互聯網公司陸續開放了自己的插件化編程的項目源碼,值得注意的是,各家的實現思想還都不同,各有特色。 
1)DL插件化體系 
第一個要介紹的是DL插件化框架,GitHub地址爲:https://github.com/singwhatiwanna/dynamic-load-apk。 
這個框架早在2014年3月就在Github上了,直到2015年才基本穩定下來,開始有越來越多的Android開發人員關注這個項目。它是由“民間”三位Android開發者共同研發出來的,分別是任玉剛、田嘯、宋思宇。 
這個項目的特色是,通過宿主程序中一個叫做proxy的Activity,去調用插件中的Activity。 
以下圖片摘取自任玉剛的博客,形象的表達了DL的核心思想:

圖片描述

DL框架面臨兩個棘手的問題:

  • 首先是通過proxy調用插件中的Activity,那麼插件中的Activity就是一個普通的類了,不再具有原有的生命週期,爲此需要重寫插件中的Activity的所有生命週期方法,proxy手動去管理插件中每個Activity的onCreate、onResume這樣的方法。

  • 其次是插件中的資源,不能再通過R來訪問,爲此要重寫Context中的getAssets方法和getResources方法。

DL框架最有名的發明創造。莫過於that語法了。在插件中,我們將盡量使用that關鍵字來替代this。 
DL目前還有很多不完善的地方。但據我所知,已經有大型移動互聯網公司的Android插件化體系就是基於DL的。

2)Fragment系

https://github.com/mmin18/AndroidDynamicLoader 
早在2012年7月,就有大衆點評的屠毅敏在Github上發佈了一個名爲AndroidDynamicLoader的開源項目,這應該是第一個Android插件化的項目,它的亮點在於大規模的使用Fragment來代替Activity。所有的Fragment都運行在一個Activity上,從而在Manifest文件中只事先聲明這個Activity就夠了,這樣就避免了每次新增一個Activity都要修改Manifest文件的尷尬。

2015年也有類似的一款基於Fragment的插件化框架問世,詳情請參見以下地址:

3)阿里系插件化體系 
阿里其實幾年前就在搞插件化編程了,代號爲Atlas,只是2015年才把這套技術公佈於衆。先是命名爲OpenAtlas,然後改名爲ACDD,最後不知道爲什麼又把GitHub的地址改爲ACDDExtension——其實這3個項目是一回事,相關地址請參見:

Atlas的亮點在於對R進行分區,從而確保資源相互獨立互不衝突。爲此,把功夫做足在aapt這個命令層面,需要額外修改aapt中的邏輯,以確保資源分區沒有問題。

4)攜程 
https://github.com/CtripMobile/DynamicAPK 
攜程的插件化思想和阿里的Atlas有很多相同的地方,由此可見這是一套通用的技術解決方案,所謂的“正統思想”,主要包括以下幾點:

1.aapt上的改造 
2.gradle上的改造 
3.資源ID分區 
4.修改Context的getAssets方法和getResources方法,解決R文件的讀取問題。

5)對插件本身沒有限制的新思路 
https://github.com/houkx/android-pluginmgr 
看慣了前面的各種插件化技術,細心的朋友是否發現,我們對插件做的太重了,比如說要遵守各種人爲的規定,重寫aapt指令,資源分區,that語法等等。 
這個世界總是太浮躁,讓我們靜下心來做減法,閉上眼睛思考我們究竟想要什麼,而不是各種跟風。是否可以搭建這樣的一個Android宿主程序,它可以把任何未經安裝、默默躺在SD卡上的apk程序都作爲插件加載進來。這樣就降低了插件編寫的難度。 
本篇要介紹的pluginmgr就是這樣的思想,作者在試圖搭建這樣的一個萬能的Android宿主程序。 
pluginmgrd的核心思想有2點:

  • 一是把插件中所有的Activity都動態生成一個相對應的PluginActivity。啓動插件的某個Activity時,先找PluginActivity,再找對應的Activity——所謂的依賴反轉的思想。這就不需要把插件中的Activity還要在宿主中的Manifest文件中註冊。

  • 二是在啓動插件的Activity時,不是通過自己寫程序手動去new一個Activity,而是由Android系統來new這個Activity。我們將宿主的ClassLoader替換爲FrameworkClassLoader。

注意,所有的插件apk都是不需要安裝的,只需要靜靜的躺在SD卡上即可。由萬能的pluginmgrd在運行時將這些apk加載進來。

6)更優雅的修bug:AndFix 
https://github.com/alibaba/AndFix 
Android插件化是爲了解決什麼問題?

  • 65536方法數爆棚。

  • 減少apk體積。

  • 不通過發版就能發佈新功能

  • 不通過發版就能修復線上bug和崩潰。

但我們經過實踐發現,插件化更多的運用於修復線上bug和崩潰。這是一個很輕量的需求,卻爲此花費了大量的人力和財力去運行這樣一套龐大的架構體系,是相當不划算的。爲此,2015年github上出現了AndFix,這款Android輕量級線上bug修復工具。 
AndFix的核心思想是,把app中的方法B替換爲新的方法B ‘,爲此,我們把新方法B’所在的代碼進行重新打包,並和就的apk包進行差分比較,得到一個差分包,放到服務器提供舊版apk下載,那麼apk在接收到差分包後,就會執行新的方法B’了,如下圖所示:

圖片描述

這類似於iOS的JSPatch實現。只不過Objective-C是一門動態語言,天生就支持這樣的特性。而在Android中,則需要修改Native底層了。 
在Native底層,有一個dalvik_dispatcher方法負責最終執行哪個方法。就是在這裏做一些手腳,把舊方法替換爲新方法。

對於功能不是很多的App而言,AndFix是首選,可以快速修復線上bug而不用發新版,而實現成本也很低。對於規模不大的團隊而言,相當划算。

這裏不得不說到dexposed。dexposed和AndFix都是阿里推出的開源框架,用以解決Android熱修復的兩種實現,原理兩者類似,都是在在Native底層的dalvik_dispatcher方法做文章。但是dexposed有一個硬傷,就是不支持art,這使得很多粉絲轉而去投標AndFix陣營。dexposed的github地址爲: 
https://github.com/alibaba/dexposed

8)360系插件化 
https://github.com/Qihoo360/DroidPlugin 
縱覽了前面的所有插件化技術,你會發現,它們都是基於單進程的。這就是說,插件更新只能等到App重新啓動才能生效。 
但是我們的用戶大都是不懂得如何重啓App的。這就導致了插件升級後的更新率並不高,兩週時間也就50%的升級率,然後App就又發大版本了。 
對於這個問題,360推出了DroidPlugin的插件化技術,它是基於多進程的思想。比如說一個App中有吃喝玩樂4個插件,如果“吃”這個插件有升級,DroidPlugin就可以把正在運行的“吃”的舊版本的這個進程殺掉,然後運行新的插件版本。 
目前看起來,對於電商、O2O、OTA這樣多業務線、並偏重於閉環的App而言,DroidPlugin是一個終極解決方案。


第二個激動人心的是Facebook開源的Fresco,這是一款強大的圖片加載組件,github地址:https://github.com/facebook/fresco。 
Android領域最讓程序員苦惱的莫過於內存不足夠導致的OOM異常了,這大都是由於加載大量圖片而沒有及時回收導致的。爲了解決這個問題,Android有很多專門用於加載圖片的組件,比較著名的有ImageLoader、Picaso等,它們只能在Android層面通過及時回收圖片資源來緩解Android的內存使用,來減緩OOM的發生頻率。 
接下來我們說Fresco,它引進了三級緩存的概念(Bitmap緩存、內存緩存和硬盤緩存),它比其他圖片下載組件消耗的內存小,就在於這個全新的緩存設計。三級緩存中,尤以Bitmap緩存最亮眼。在Android 4.x和更低的系統,Bitmap緩存位於ashmem中,而不是位於Java的堆(heap)中。這意味着圖片的創建和回收不會引發過多的GC。 
關於Fresco的更多介紹,請參見Fresco的官方文檔:http://fresco-cn.org/docs/index.html


最後,是針對於Android的線上崩潰的收集整理和分析修復。其實收集整理這件事,要麼是使用第三方平臺的系統,要麼是自己做,但是收集到數據並去重後,如果分析這些崩潰信息並修復,是件很棘手的事情。要針對於機型、使用場景,具體問題具體分析,社區上(比如CSDN或Stackflow)針對於每個崩潰信息的分析和修復方案,魚目混雜,或隻言片語,或空穴來風,要逐一訂正是件很費神的事情。 
我曾經試圖來整理這些崩潰的原因和修復方案,耗費半年時間,也才完成84個(可以參見《App研發錄》第6章)。就在我幹這件事的同時,騰訊有一個團隊Bugly也在做類似的事情,他們在11月搞了這樣的一個活動“騰訊 Bugly Android 異常案例解決方案徵集”(活動的詳細地址參加http://www.oschina.net/news/67914/tencent-bugly-projects),試圖通過社區的力量來建立一個Android的崩潰倉庫。天地萬物皆有時,崩潰倉庫在2015年只是一個萌芽,能否做大做全,我們期待2016年。


前面說了Android太多普大喜奔的事情,接下來說一說Android在2015年遇到的一個安全問題。 
我敢打賭說,大部分公司的Android項目,會爲了方便,而把簽名密鑰放在了項目中,所有開發人員都可以看到。隨着這幾年開發人員的流動,密鑰已不再是密鑰了。 
把密鑰從項目中移除,保存在1-2個人手中,是個不錯的辦法。但是仍不能避免之前的同事手中握有這份密鑰。密鑰一旦被流傳到市場上,就會有不懷好意的人在原先的App加一些惡意的功能,然後重新簽名。 
更換密鑰嗎?這是個餿主意,這會導致生成一個新的App,而不再是原先的那個App了。 
其實這個問題早就存在,只是現在才擺上檯面而已。目前還沒有更好的解決辦法,也只能縮小直到密鑰的人員。


末了插播一條新聞。2015年6月,Google宣佈將在年底前停止對Eclipse Android開發工具的一切支持,從此我們只能使用Android Studio開發Android。對於一個使用Eclipse3年的開發者而言,我感到非常不適應。相信和我有相同感受的朋友不在少數。從此,Gradle成爲標配。 
ADT的沒落完全是咎由自取,自身的不努力,導致Google不再花費時間和精力去支持。這樣也好,集中精力先把一個IDE做好,目前看起來,Android Studio比微軟的Visual Studio還差很多很多。

(二)iOS篇

2015年,iOS有太多的事情發生,每一次事件都促進了iOS技術的一次飛躍。


首先是蘋果宣佈從2015年2月1日開始,所有上傳至App Store官方商店的新iOS應用都必須支持64位。爲此,所有的App在打包時要兼容32位和64位,雖然某些機型上速度快了不少,但是App的體積卻大了不少。 
2015年應該是iOS的“瘦身年”。各大公司在發現自己的iOS App超過了50M之後,紛紛開始組織iOS團隊對App進行減肥,然後我們就會發現,體積變大,不光是兼容64位導致的,兼容64位只會導致.a文件的增加,而資源文件是導致體積變大的另一個因素。 
先說資源文件,包括以下幾點:

  • 減少圖片和音頻文件的大小(這一點攜程的App做的不錯,每個圖片都不超過100k,甚至50-100k之間的圖片都很少,而很多App之所以體積大,是因爲其中有很多1M以上的圖片)。

  • 對於PNG圖片,由於它內部保存了額外的分層和透明通道信息,統稱爲EXIF,所以它會比JPG圖片大一些。App開發推薦使用PNG圖片是因爲XCode會在打包時壓縮PNG圖片的大小。我們可以寫一個腳本,在打包前,把PNG圖片中這些多餘的信息,刪除掉。

  • 單***片使用使用字體文件。關於字體文件的技術,也就是IconFont,網上有很多例子,同時適用於Andorid和iOS,我這裏就不多說了。

  • 使用.9圖。之所周知.9圖是Android的技術,能極大減小圖片的體積,殊不知,iOS也有類似的實現方式。

  • 動態下載表情包。把聊天時用到的表情圖片,做成從服務器下載zip包的方式,而不是打包在App中。

  • 清除不再使用的圖片。每次迭代做新需求,都會導致一些舊圖片不再使用了。XCode不提供檢查未使用圖片的功能,那我們就需要自己寫一個腳本,每次發版前,對整個工程檢查一次。

再說.a文件。.a文件是編譯文件,這個文件大,說明代碼多。於是我們檢查項目中的代碼,真的要寫那麼多行嗎?其實有很多優化的空間。

  • 冗餘的類和方法。這些冗餘仍然是因爲做新需求導致的,忘記刪除不用的類和方法,需要寫腳本查找,定期刪除。

  • 相似度極高的代碼片段。初級程序員在寫代碼時,喜歡把一段代碼從A類粘貼到B類中,然後修改其中的幾個變量名稱,這個功能就算做完了。於是兩段相似度極高的代碼就產生了。 
    稍微懂得些面向對象思想的人,都知道這時候需要把這樣的代碼抽象出來,比如說在Utils類中新建一個方法,然後要用到這段邏輯的人調用Utils類的這個方法即可。 
    但並不是所有的程序員都有這樣的境界,即使是有幾年經驗的人,也會因爲急着下班二人世界或者給孩子換尿布而採用複製粘貼大法敷衍了事。久而久之,冗餘代碼就多了,包的體積自然就大了。爲此,我們需要有一個檢查代碼相似度的工具。在iOS領域,我推薦Simian這個工具。有興趣的讀者可以嘗試一下,對你們的項目使用一下這個工具,看能找出來多少相似的代碼來

  • 使用代碼生成UI,而不是使用Xib或Storyboard。經過測試,對於同一個頁面,使用代碼而導致的.a文件增加的體積,大於Xib的體積。是時候該返璞歸真,考慮使用Xib來佈局了。Xib之所以廣受詬病,是因爲XCode這個IDE工具很爛,另一個原因是我們使用的少,人總是會抵觸陌生的事物,在使用Xib的過程中遇到障礙了,就又轉到寫代碼的路線了。

  • 使用Hybird方案來代替iOS原生代碼。我做過嘗試,一個功能模塊,導致.a文件增加3M,但使用Hybird卻只有1-2M的樣子,而且這1-2M中有一部分打包放在App中,另一部分則做成增量下載,從而從整體上減少App包的大小。其中Hybird的增量包技術是關鍵。

  • 編譯選項的優化。比如說Strip Link Product設爲Yes啊,Make Strings Read-Only設爲Yes啊,去掉異常支持啊,都能減少包的大小。此外,經常檢查LinkMap文件,也是控制瘦身的一個辦法。

微信團隊2015年9月中旬發佈了iOS微信安裝包的瘦身經驗,其中有很多實際經驗。文章地址如下: 
http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207986417&idx=1&sn=77ea7d8e4f8ab7b59111e78c86ccfe66&3rd=MzA3MDU4NTYzMw==&scene=6#rd


其次是春節期間,某款知名App的後門泄露事件。所謂後門,就是App開發期間,方便開發人員和測試人員的一些功能,比如說: 
開發人員和測試人員可以隨意切換到任意服務器(線上環境、測試環境)進行開發測試工作。傳統的做法,這些地址是寫死的,每次打包出來的App只能在固定的一個環境下運行,我們迫切需要一個後門頁面,能夠靈活配置。當然,線上用戶是不能看到這個後門的,必須做一個類似於彩蛋的功能,比如在設置頁的某個位置連續點100次,纔會彈出一個密碼輸入框,只有輸入正確了,才能進入後門頁面配置服務器地址。 
考慮到發佈到線上的App,存在這樣的彩蛋是非常危險的。於是我們需要一個Flag標記,在發佈App時要把這個值設置爲false,從而關閉後門入口。但人總是會犯錯誤的,即使有測試團隊把關也還是會有紕漏。於是,國內某款著名的App在春節期間就把這樣的後門漏出來了,也許是開發或測試人員急着回家過年。這是這次無心之失,讓我們領略了這款App強大的後門裏隱藏的功能。比如說,

  • 服務器切換功能(上午已經介紹過)。

  • 記錄App的崩潰信息。有這樣一種場景,測試人員在測試過程中發現的一個崩潰,雖然也記錄在Bug倉庫中了,但是等開發人員去修復的時候,卻難以再現這個崩潰了。如果能把崩潰記錄到App本地,那麼測試同學提bug的時候,就可以把崩潰信息一起貼出來。

  • 提供一個後門頁面供Html5團隊進行調試,該頁面內置一個WebView,加載Html5團隊正在開發的Html頁面,要支持調試。

  • 對App進行流量測試,統計某個頁面所花費的流量,包括調用MobileAPI、下載圖片、上傳文件、XMPP聊天等等。其中,從App啓動到首頁加載完成所花費的流量是我們關心的一個關鍵點,而手機待機時,App所花費的流量也是我們所關心的。我們需要這樣一個後門頁面,看到這些數據統計。

  • 對App進行電池電量消耗測試。需要有個後門頁面記錄每次打開App和退出App的時間,以及這段時間內我們的App所消耗的電量。爲了確保數據的準確性,需要確保手機上只安裝了一個App,而且處於相同的網絡環境下,比如3G。

  • 測試某個頁面請求了哪些MobileAPI接口,打印出調用這些接口時輸入的參數和返回JSON數據。這樣就能夠在線上App發現某個頁面有問題時,及時在App後門中檢查數據是否正常,而不用App開發人員和MobileAPI開發人員坐在一起逐行聯調代碼,極大的節省了人力。

在窺探到後門中這許多先進技術之後,各家無線團隊紛紛在自己的App中增加類似的功能,只是不知道最初把後門漏出來的那個哥們離職了沒有?


2015年最犀利的技術首推JSPatch,使用這門技術,iOS可以快速修復線上bug而不需要重新提交AppStore審覈。 
這門技術最早起源於大衆點評的屠毅敏的一個開源項目WaxPatch。它是通過重寫runtime的class_replaceMethod方法,從而可以修改任何一個類的任何一個方法,該項目的GitHub地址爲:https://github.com/mmin18/WaxPatch 
WaxPatch上支持的語言爲Lua,也就是說,建立了一套Objective C和Lua語言之間大部分語法的映射關係,我們只要熟記這些轉換語法,就能快速把一個Objective C方法翻譯爲Lua方法。然後我們把需要修改的Lua方法所在的類文件打包成zip,由App在啓動的時候下載zip包並解壓到本地目錄,於是我們會看到,當運行到舊的Objective C方法時,實際執行的是下載到的Lua方法。這一切都因爲Objective是一門動態語言,我們可以基於此製造一些“黑魔法”。 
但是WaxPatch從2013年10月起就不再更新了。當2015年2月蘋果宣佈所有上傳至App Store官方商店的新iOS應用都必須支持64位,這時我們發現WaxPatch並不支持64位。這就間接導致了很多已經在項目中使用了WaxPatch的App,必須砍掉WaxPatch熱修復功能,後來社區有人給出了WaxPatch的64位解決方案,才讓熱修復技術能繼續向前發展,這個項目的的GitHub地址爲:https://github.com/maxfong/WaxPatch_X64/commits/master 
儘管如此,WaxPatch還是有很多侷限性。比如說它不支持多線程、不支持Block,不支持結構體和結構體指針這兩個類型,這就導致了當我們在程序中使用了這些語法時,是沒有機會把這些語法轉換爲Lua代碼的。 
通過上文的分析,我們知道,只要重寫runtime的class_replaceMethod方法,就可以熱修復Objective C中的任何類的任何方法,WaxPatch只不過使用了Lua作爲新方法的語言載體,我們完全可以使用Python、JavaScript這樣的腳本再寫出一個新的Patch。 
這時終於輪到JSPatch登場了,它是由騰訊的陳振焯(英文名Bang)於2015年5月編寫的開源項目,從名字就能猜出來,它使用的是JavaScript語言作爲新方法的語言載體,GitHub地址爲:https://github.com/bang590/JSPatch。這個項目解決了上述WaxPatch所不支持的那些語法。目前這個項目還在每週持續更新中。 
JSPatch還有一個亮眼的功能,就是支持一鍵生成,把一個Objective C方法翻譯爲JavaScript的方法。按照這個思路再往前走一步,就是iOS的“插件化編程”。我們可以把一個模塊所涉及的所有頁面都使用Objective C先實現了,然後一鍵生成JavaScript方法代碼,打包成一個zip包,這就是插件化編程。不得不說的是,對大量的代碼執行反射操作,性能是一個問題,究竟能往前走多遠,2016年,我們拭目以待。


2015年註定是iOS領域不平凡的一年,比如說,在9月份大規模爆發的XCodeGhost病毒。IDE也能攜帶病毒,這是我一個.NET出身、用慣了Visual Studio的程序員所不可理解的一件事。只要是非官方下載的XCode,都有可能通過CoreService庫文件進行感染,使用有毒XCode開發的App,都會感染病毒。這就像給病人動手術,結果手術刀沒消毒,病人就會有生命危險。 
關鍵是AppStore還無法檢測出病毒,傳聞將近800款App感染了這一病毒。 
儘管事後立即有人站出來,聲明自己是XCodeGhost的作者,並宣稱是個“苦X程序員的”、“無害的”、“實驗”,同時承認自己出於私心,在代碼里加入了廣告功能,並說自己在10天前,已主動關閉服務器,並刪除所有數據。 
但很多證據表明,這是一個蓄謀已久的惡性事件。 
當號稱“封閉安全”的AppStore也不再安全,我們還能相信誰?


接下來介紹React Native。這是Facebook在React.js Conf 2015 大會上推出了基於JavaScript的開源框架。同時支持iOS和Android,Github地址爲: 
http://facebook.github.io/react-native/ 
首先,React Native不是依賴於WebView的,所以它不是Hybird。React Native是把js翻譯爲Objective-C,倒是與JSPatch有些淵源 
我一直在關注着這門技術的發展。但目前看起來,還很不成熟。儘管在2015年的各種技術大會上,React Native出盡了風頭,但據我所示,目前也就BAT這種公司願意燒錢讓團隊去嘗試使用。 
有關React Native的更詳細介紹,推薦大家看下面這兩篇文章:


2015年iOS的最後一件“振奮人心”的事情是Swift的開源。 
Swift從面世伊始,就號稱要取代Obejctive C成爲新的iOS開發語言,但是幾年過後卻還是一個很小衆的語言。沒聽說有哪家大公司的代碼全都切換到Swift了。也許是我孤陋寡聞了,至少在App應用領域是這樣。 
從2015年12月初Swift開源,截止到本文寫作期間,這個項目的Watch(郵件提醒)爲1484、Star爲22569,Fork爲2652,火得一塌糊塗。但是熱鬧過後,又會有多少人真正關注?蘋果官方給出了開源後的諸多好處和美妙的前瞻,這不過是官方的PR稿子,這不由得讓我想起了.NET當初開源,也是叫好聲一片,但實際效果並不理想,參見以下報道:

圖片描述

作爲有着十多年編程經驗的碼農,我不能潑太多冷水。我不想澆滅剛入行的小朋友的社區熱情。究竟Swift開源後能產生什麼驚天地泣鬼神的作用,2016年,請用事實驗證吧。

(三)App項目管理

2015年,在App項目管理領域,仍沒有太大的進展。我悲觀的認爲,App項目管理,已經到了糟糕透頂的地步。 
從事傳統項目管理的工作人員,並沒有與時俱進,還在把舊的項目管理方式直接套用在App項目管理上。主要體現爲傳統項目管理只涉及到產品經理、開發和測試三個團隊,開發完畢介入測試,測試完畢隨時可以發佈上線,如果一個團隊延期,另一個團隊可以做下一次迭代的工作。 
但是App開發就不同了,涉及到產品經理、Android、iOS、服務器、測試共計5個團隊的協作,有時還會牽扯進H5前端團隊,那就更復雜了。 
App區別於傳統項目的另一點就在於它有發版時間限制。2周或4周的迭代時間,到了最後一天就必須要提交APpStore審覈或發佈到各大Android市場,一般不能延期,否則不光影響技術團隊,市場推廣團隊也會受到影響。哪個做不完或者測不完,就只能等下次發版再上,那就是一個月之後了。 
既然迭代週期是固定的,App項目管理所關心的,就在於如何能在有限的時間內完成儘可能多的需求,而不是每天糾結於“敏捷白板上的小紙條哪裏格式不對了”這種形式主義的東西。 
如果有可能,我真心想把每個公司所使用的項目管理工具(比如Wiki)廢棄了,工程師們往往是在項目完成後才更新Wiki上的項目狀態,而做不到即時更新。我只能在每次App發版後纔看到大量項目的狀態變更。那我還要這種工具幹什麼呢?而過度的要求工程師實時使用Wiki來更新項目狀態,那無疑是重流程的軟件公司的打法,不適用於互聯網高速發展的文化。越是大公司,這種官僚文化越嚴重,迭代速度遠低於創業公司。因爲互聯網公司現在錢很多,很多軟件公司的項目管理人員都跳槽到了大型互聯網公司,無形中就把這種文化也帶過來了。 
說真的,我不喜歡循規蹈矩。我喜歡時刻去改變去嘗試,直到找到一條切實的解決方案,所以我經常會到一線去,和團隊一起加班一起熬夜。在4年的App項目管理經驗中,我觀察到的是,對於10人左右的小團隊,每天可以在晨會上把產品、Android、iOS、Server、QA的進度都過一遍,控制在10分鐘以內。而對於40人左右的中型團隊,這時一般會按照Android、iOS這樣的技術工種細分爲多個小團隊,每天晨會問技術經理團隊的項目進度,他一般不會知曉團隊中每個成員的工作狀態,所以這樣的晨會是很沒有效率的。這時需要把團隊按照需求拆分爲若干虛擬小團隊,每個需求的虛擬團隊都由產品經理、具體的iOS開發、Android開發、Server開發和測試人員組成,採取產品經理負責制,每天組織各自的晨會併發會議紀要。 
項目管理人員手中應該有一份所有人的名單,減去產品經理日報中涉及的人力輸出,那麼剩下來的人力,要麼是請假了,要麼是在做技術需求,還剩下來的人,就是真的沒事做了,浪費掉了。 
這時團隊每個人的工作狀態就都一目瞭然了。我們不苛求每天都把人力充分使用,但至少要做到啞巴吃餃子——心裏有數。 
那種靠每週發週報的項目管理方式,屬於事後補救,難道我們要在一週之後才知道人員利用率不高而導致的項目風險嗎?這對於兩週發一次版本的App而言,多少有些可笑了。 
我們不可能安排一個開發人員一個迭代只做一個需求,也許這個需求兩天就做完了,難道剩下的時間全都用於修bug嗎?這種敷衍的說法,用於哄弄那些不懂技術的老闆的。剩下的時間應該去做更多的需求,那麼就會有人問什麼時間修bug?兩週的迭代週期要怎麼安排比較合理? 
下面我給出兩週的迭代週期圖,這在我所從事的一家大型互聯網公司一直堅持到現在,兩年多了一直風雨無阻:

圖片描述

由上圖我們可以看出,

1)開發只有第1週週二到第2週週三共計7天時間。 
2)測試團隊要在開發人員提測後立即介入,而不是等到所有項目都完成後統一測試。 
3)開發人力不足,一般是第1周加班;測試人力不足,一般是第2周加班,但沒有定式。 
4)第2週週三晚上爲Code Complete,週五晚上爲Code Freeze,這兩個點很關鍵,直接決定了是否要加班以及是否會延期。

當一個Task的開發時間,從3天(粗略評估)被壓縮到2天(精準評估)後,多出的1天時間做什麼?

首先是看還能不能消化更多的需求。 
其次,就是重構,做技術需求。App領域有太多的技術需要升級,我分析過100多款國內比較知名的App,發現各自的瑕疵都還是有很多的。Android的技術工作會更多,比如每次迭代要擠出1-2天時間來修復線上千奇百怪的崩潰。 
最後,就是研究新技術。要時刻了解市面上的新思想和新技術。

上述這若干文字,都是在詮釋一個詞,節奏。 
團隊多了自然就會有溝通上的障礙,從而導致效率大幅下降。而我的觀察是,只要讓所有團隊踩準了節奏,App和Server團隊同一時間聯調而不是互相等待,按時提測而不耽誤測試人員的進度,提前介入測試而不是前鬆後緊,當所有的團隊能夠踩住這幾個節奏,那麼我們就能在有限的時間內按時完成足夠多的需求。 
2016年,我們應該重點關注App的項目管理,多開幾次會各個公司分享一下經驗,總結出一條好的方式來。

(四)綜合篇

接下來的篇幅,不限於Android或iOS。

2015年,各大互聯網公司開始經營自己技術團隊的微信公衆號。以下是我收集到的幾個(排名不分先後哦),歡迎讀者補充更多的技術團隊公衆號:

  • 淘寶:TaobaoTech

  • 天貓:tmalltech

  • 手淘:AlibabaMTT

  • 微信:WeMobileDev

  • QQ空間前端:QzoneWeb

  • Bugly:weixinBugly

  • 京東:JDTechEd

  • 美團:meituantech

  • 攜程:ctriptech

  • 去哪兒:QunarTL

  • 途牛:tuniutech

  • 噹噹:噹噹Tech

此外還有技術社區的公衆號(排名不分先後哦):

  • InfoQ:infoqchina

  • CSDN:mobilehub

  • OSChina 開源中國:gh_430521f7587e

  • 51CTO技術博客:blog51cto

  • CocoaChina:cocoachinabbs

  • 極客學院:jikexueyuan00

通過持續關注這些公衆號,尤其是無線相關的內容,可以大致知道業界最新的技術趨勢,比如Android插件化編程,比如iOS瘦身。


2015年,對無線領域的技術分析正式擺上了檯面。之前肯定有公司也在小規模的做這個事情,只是不能多做宣傳罷了。 
競品分析的手段一般分爲幾種: 
1)iOS的代碼是無法反編譯的,但是Android卻可以,大多數App做了代碼混淆,但也有的App直接裸奔就發到了市場上。即使代碼做了混淆,我們也能從關鍵片段中看出端倪來。關於這個技術我不能再講下去了,否則就要教壞小朋友了。目前看起來,對Android進行加固是一個好的辦法,也有一些公司從事這個領域,但還沒有廣泛應用起來,比如說愛加密和梆梆。 
2)所有的apk或ipa文件,都是壓縮包,我們將其後綴修改爲zip格式,就可以解壓並看到其中的文件了。通過分析這些文件,我們可以學習到優秀的公司是如何解決App體積大小、性能優化新技術,一般的話,一個新的思想或新的技術,都會伴隨一個配置文件在App包中,比如ABTest。 
此外,我們知道,Android App中的動畫,會放在Apk包res/anim目錄中,當我們喜歡某款App的動畫效果時,按圖索驥,直接可以在上述目錄中找到相應的動畫文件;但是,當我們在ipa包中也看到類似的動畫文件時,那十有八九是這款App的iOS版本中,存在一個動畫引擎,iOS程序員可以把Android團隊的動畫文件直接複製過來就可以使用了。 
關於競品分析的更多介紹,請參見我發表在CSDN上的系列文章: 
http://blog.csdn.net/JspAndAsp/article/details/49339363


2015年,我終於看到美團在App中使用ABTest來做產品。產品經理可以根據線上A和B兩種策略各自的轉化率來迅速決策哪種策略更適合。 
也許ABTest這門技術,其他公司早就開始在做了,只是沒有聲張而已,在此請不要笑話我的孤陋寡聞。我把自己在實施ABTest的一些經驗分享出來,請參見下面這篇文章:http://blog.csdn.net/jspandasp/article/details/49339443 
數據驅動產品——我認爲這纔是做產品的方式,而不是靠拍腦袋。稍微高級一點的產品經理,會收集有利的數據來支撐自己要做的需求,而有意識的忽略那些不利的數據。這多少有些偷奸耍滑,需求上線後的結果也是聽天由命大都結局不好。 
產品需求分爲兩個方向,一是剛需,二是交互和UI設計。 
對於第一個方向,需要對這個領域浸染很多年,才能真正知道用戶和供應鏈上的真正痛點,目前我見過這個方向最好的產品經理就是楊威。也許以後還能遇到更好的,但是目前就是他了。2015年我有幸見到了他是怎麼在幾個月內從謀劃到調動整個部門完成了機票整個流程的改造,最後做出來一套逆向報價系統。 
對於第二個方向,則多少有些自說自話了。一套好的UI設計怎麼評定?首先是老闆喜歡,這是因爲一套設計不可能讓所有人都滿意,但只要老闆滿意,就是好的設計,搞定了老闆,後面的都好談;其次是風格要統一;再次是要時刻關注競爭對手的App改版。 
對於好的交互設計又怎麼評定?首先不能設計出“反人類”的交互;其次要看PV和UV數據,看哪裏的轉化率低;再次看用戶反饋,廣泛吸取各方意見;最後看競品,取長補短。 
無論哪個方向,都需要數據說話。運營纔是王道,因爲只有他們才能通過調整策略得到不同的數據,分析數據最終做出判斷。運營人員欠缺的就是不知道如何把需求組織成文檔給開發人員,這時候就輪到產品經理出場了。 
產品經理應該學點數學,能根據運營妹紙提供的數據,總結成公式,纔是好的產品經理。數據驅動產品,重要的事情說三遍,不寫出來了,心中默唸三遍即可。


接下來介紹一款由騰訊團隊於2015年發佈的App尾隨測試的神器,GT(隨身調)。


2015年的最後一門技術,那就是App緩存命中率。 
從事App開發的同學可能不清楚緩存命中率的概念。這一般是做在數據庫層面,對於頻繁訪問的數據,會放入緩存中,從而下次訪問時不會再執行SQL語句,極大地節省了性能,但是也不能把所有的數據都放在緩存上哦,沒有那麼大的控件。對此,我們的妥協方案是,設置一個閾值,大於這個閾值,緩存的時間會長一些;否則,就只有3分鐘後緩存就會失效。 
其實這個思想也可以做在App層面,把相同的邏輯搬到App應用中,從而減少訪問服務器的頻率。有些公司已經在App所使用的服務器接口層面做了類似的緩存策略,但是還沒有在App中嘗試實施這種策略。

(五)結束語

本人從事App開發4年時間。當初比較貪心,iOS和Android是一起學的,這就導致了精力要一分爲二,結果哪門技術都做不到非常精深,而我又額外花費了很多時間在項目管理上,這也是我所喜愛的一個領域。所以上述若干文字,盤點了2015年App領域的若干新技術和新思想,但難免掛一漏萬,或文中觀點有所偏頗,還請各位讀者多多指教。 
最後,再奉獻給讀者們一個建議。微信這個工具大家經常使用吧,我們經常收藏朋友圈中別人分享的一些好的技術文章,但當時看的並不是很仔細,是時候把2015年收藏的所有技術文章重新翻出來研讀一遍了,我這幾天就在幹這個事情,收穫還是很大的。

轉自:http://geek.csdn.net/news/detail/49303



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