HERO 一個更好的移動跨平臺開發方案
hero移動開發方案源起於點融網LB業務部門的一次無心的嘗試,在點融的黑幫文化中發展出來的一個業界領先的開發方案。
先來一個類似產品的對比
react native | weex | 小程序 | ionic | hero |
---|---|---|---|---|
性能 | 良 | 良 | 尚可 | 尚可 |
佈局 | 無序性能差 | 無序性能差 | 尚可 | 無序 |
設備能力 | 完全 | 完全 | 不完全 | 完全 |
開發成本 | 高級跨平臺工程師 | 不詳 | 高級web工程師 | 高級web工程師 |
開發工具 | 多種 | 不詳 | 微信web開發工具 | 多種 |
框架代碼量 | 巨大 | 巨大 | 非開源 | 大 |
入門難度 | 難 | 難 | 普通 | 有點難 |
解釋上述表格
- 性能
react native和weex界面表現層是原生的,但是構造元素本身的操作,和元素的所有邏輯在js中,導致性能有影響。小程序還有一個h5 canvas轉原生性能莫名其妙的慢的問題。Hero中元素的所有操作都在原生代碼中,只有業務明確需要某個操作結果纔會調用到js代碼。 - 佈局能力
CSS幾乎可以表示一切形式的界面,無設計語言約束,但是最終效果有時候與平臺的衝突會造成編程的困惑與體驗的變差,react native 和weex的css依賴webview的渲染,再將結果發送給原生導致性能損失很大。微信在自家產品中的約束樣式反而還不錯。Hero是另闢蹊徑定義了一套擴展後的frame佈局,並且在各平臺原生實現這套方案,佈局能力達到併兼容原生app。 - 設備能力
微信提供了有限受控的設備能力,其它皆有完全的設備能力(系統支持) - 開發成本
由於react native開發門檻較高,學習曲線很陡,特別是對移動開發人員,很難適應web開發模式,而web工程師對iOS本身的接口不熟悉,很難做出原生體驗的app出來,weex應該也類似。還有不管是react native 還是weex所開發出來的頁面不是完全跨平臺的,它們只是開發方式是跨平臺的,具體頁面還是要分開開發。導致開發人員需求依舊那麼多,甚至更多。而hero是一種依賴 定義<->實現 的開發方案,所開發的界面是平臺無關的,再加上統一的元素定義格式,對於具體的頁面開發人員來說,只是在配製顯示的元素,非常簡單。 - 開發工具
目前Hero的開發沒有限定開發工具,sublime和atom都可以,調試就在chrome裏面調試web頁面就好了。集成編碼、調試、託管服務端的Hero開發者工具正在開發過程當中。開發者工具本身也是用hero框架開發,目錄在hero-js/heroapp當中。只需要切換到heroapp目錄,使用nwjs .即可打開預覽版本。 - 框架代碼量
hero框架技術上並不複雜,核心邏輯代碼不過200行。 - 入門難度
Hero框架中只有一個固定的controller,其它全部都是element,相比其它的MVP、MVVM、MVC有着複雜的邏輯關係,Hero中的模式就是** e , **ee, eeeeee…,通通都是element,controller除了用來顯示element,給element傳遞json數據之外就沒有額外的邏輯了。element 中只有一個函數處理json對象,除此之外再無其它接口。每個element 都是絕對獨立的,與其它元素毫無瓜葛。這樣開發、測試元素都是及其簡單的。
Hero 框架圖
快速開始
- 下載Hero代碼,使用node her.js啓動服務端。
- 打開http://localhost:3000 可以看到一個Hero的主頁,這裏面有hero的概念展示、API doc等常用信息。
- iOS版本中集成https://github.com/dianrong/hero-ios 這個SDK,然後用HeroViewController打開一個包含Hero元素的頁面即可。
- android版本中集成https://github.com/dianrong/hero-android 這個SDK,使用HeroActivity打開一個包含Hero元素的頁面即可。
快速開始做頁面
- 在chrome中訪問http://localhost:3000/start.html
- 使用sublime2 打開start代碼文件夾,嘗試修改index.html
{
class:"HeroLabel",
name:"name",
textColor:"ffffff",
text:"Hello hero !",
size:22,
frame:{"w":"1x",h:"80"},
alignment:"center"
},
class 一個界面元素必須包含的部分是,這指定了使用原生類的類型,
frame 指定了元素在界面中的佈局,這個佈局是三個平臺上統一實現的
name 如果這個元素需要接收數據,那麼給它設置一個name
其它option的屬性,取決於元素是否實現
setTimeout(function() {
API.out({command:'refresh'});
}, 2000);
開發過程中使用定時刷新實現即時性效果,開發完成後註釋掉
setTimeout(function() {
API.out({globle:{key:'finishLoading'}});
}, 100);
每個APP的第一個頁面需要使用通過globle通知發送finishLoading告訴app關閉封面,上新功能的時候也可以發送一個showLoading來展示一個新功能slider,展示期間可以緩存新的HTML頁面
快速開始新的元素
- 新建一個元素只需要繼承自原生元素中有類似功能的一個元素,然後實現一個on方法,與此元素相關的一切功能都通過on方法中傳遞過來的json對象來實現。
- on方法需要調用父類的on方法,基礎的佈局,背景,邊框,hidden等屬性都是在HeroView中已經實現好了,一般元素類只需要實現此元素特有的幾個屬性即可。
- 例:
@implementation HeroLabel
-(void)on:(NSDictionary *)json{
[super on:json];
if (json[@"text"]) {
self.text = json[@"text"];
}
if (json[@"alignment"]) {
NSString *alignment = json[@"alignment"];
if ([alignment isEqualToString:@"center"]) {
self.textAlignment = NSTextAlignmentCenter;
}else if ([alignment isEqualToString:@"left"]){
self.textAlignment = NSTextAlignmentLeft;
}else if ([alignment isEqualToString:@"right"]){
self.textAlignment = NSTextAlignmentRight;
}
}
if (json[@"size"]) {
double size = ((NSNumber*)json[@"size"]).doubleValue;
self.font = [UIFont systemFontOfSize:size];
}
if (json[@"textColor"]) {
self.textColor = UIColorFromStr(json[@"textColor"]);
}
if (json[@"font"]) {
double size = ((NSNumber*)json[@"size"]).doubleValue;
if ([@"bold" isEqualToString:json[@"font"]]) {
self.font = [UIFont boldSystemFontOfSize:size];
}
}
}
@end
**android的實現稍微有一點不同,由於java沒法多繼承,也沒辦法往系統庫中注入方法,所以在android中實現一個基礎類需要在on方法中調用的HeroView的靜態方法on(view,json)來完成view的初始化。如果新元素繼承了Hero元素則只需要和iOS一樣調用super.on(json)即可。**
Hero 不止是一個開發框架,而是一個開發方案
開發過程管理
- 新的框架需求可以提交代碼到hero-js/test/test/unit_test/目錄,具體的提交內容是一個json文件類似
{
class:"MyLabel", //新功能的元素名
p1:"xxxxx", //新熟悉接受什麼樣的參數,結果如何
text:"Hello hero !",
size:22,
frame:{"w":"1x",h:"80"},
alignment:"center"
},
測試系統會自動爲這個元素生成測試用例,如果各個平臺上打開此測試用例結果都正確,表明這個元素實現完成。單元測試如下圖
- 測試驅動開發,由於任何新的功能都是先有測試用例才能開始,這是先天性的測試驅動開發。
- 全平臺自動化測試,如圖
用戶行爲分析
在Hero框架中有一個理念,頁面上不應該有任何的邏輯,頁面(view controller\activity\page)只負責顯示元素,元素本身只接json數據,界面顯示成什麼樣子完全由接收到的json數據來決定,而且頁面本身只有 in 和 out 兩個函數分別對應元素反饋數據,和給元素的數據。我們在js中重載這兩個函數,並將數據發送到日誌服務器。就可以知道一個用戶的所有操作,並可以對操作進行完整的回放。我們截取了一段不包含敏感數據的截屏如下圖:
hero不只是一個前端框架
Hero的核心理念是任何一個功能元素有且只有一個接口與外界交換數據。我曾經寫了一個工具去檢測一般項目中類之間的關係,方法是先找出當前項目的類列表,如果一個類中出現其它列表中的類就加1,結果是50個類平均結果是200左右,100個類平均結果是800左右,而且這個數以大於正比例曲線增長。大家可以想象一下一個新人面對一個大項目時候的囧迫,這簡直是一張大網。傳統的面向對象編程也許本身沒有問題,但是在實際的的實踐中遭遇了巨大的挑戰,函數式編程是一種,而Hero是另外一種。
在服務端,Hero也有一個初步但是完整的實踐,目錄在hero-js/server當中。這裏不再展開敘述。
Hero milestone
貢獻
提交到
https://github.com/dianrong/Hero
https://github.com/dianrong/Hero-ios
https://github.com/dianrong/Hero-android