詳解引擎技術之約定式編程的實現理念(1)
2016-02-20 19:33:35 來源: 曲毅 51CTO.com 評論:0 點擊:
在前端世界里,我們經常會聽說某某引擎,某某框架,那么到底什么樣子的東西可以稱之為引擎呢?如果我們自己希望編寫引擎應該如何做呢?在編寫引擎的時候,我們至少需要注意哪些方面呢?引擎技術到底能給我們帶來什么呢?
本文皆旨在平時的學習交流中遇見很多值得討論的問題,抽取部分有價值的觀點,和大家一起談論學習。
作者簡介
曲毅,51 CTO WOT峰會特邀嘉賓,曾為第七屆WOT移動互聯網開發者大會的特約講師。從事互聯網研發工作11年。曾在高陽,空中網,樂蜂網等互聯網公司擔任構架師,高級技術經理,技術總監等職位。近4年專注移動互聯網,是國內資深HTML 5專家和研究者,對HTML 5技術有非常深刻的認識和理解,有著豐富的實踐經驗,是HTML 5引擎Crow 5的創造者。多次受邀在中關村在線,iweb峰會和GITC全球互聯網大會上擔任嘉賓和專家。
七樂康高級技術總監
一、到底什么是引擎?什么是輕量級框架?什么是重量級框架?
其實引擎并沒有我們想的那么神奇,可以理解成封裝的更方便用的框架。引擎技術其實也是框架技術。兩者沒有本質上的區別。前端我們適用的框架,大家熟知的有jquery,zepto,sea,Kissy等都是優秀的框架。這些框架使用簡單,輕量,學習門檻很低。這些都是優點。這些框架就像小積木一樣,每一種框架都有自己的特點,針對具體的使用場景,解決開發中遇見的痛點問題。例如jquery封裝了大量的Javascript的方法,解放工程師的重復編碼,瀏覽器兼容,動畫特效處理。但是我們在做移動方面的項目的時候會發現Jquery這樣的庫,不太實用,很顯然Jquery解決了很多PC瀏覽器兼容方便的事情,相對移動設備來說體積太大,很多兼容問題不復存在。那么就出現了zepto框架。zepto定位就是移動設備,這樣它的體積就小了很多。在例如我們處理javascript模塊加載問題的時候可以使用Sea.js。sea是一個遵循CommonJS規范的javascript模塊加載框架,可以實現javascript的模塊開發及加載框架。
每一種框架都有自給的一種設計理念和針對痛點給出的解決方法。盡可能的用少的代碼量,去解決更多的問題,同時給出一個方便使用的API。這些都是輕量級框架的優點。但是這樣對于我們開發工程師來說,就面臨一個問題。我們在做一個項目的時候,會遇見很多很多問題,除了要模塊開發,還要動態加載,還要有模版技術,還有動畫處理。還有緩存處理,如果做的功能復雜點,還需要調用地理位置,重力感應。需要許許多多的的小框架。如果不使用庫,自己去寫那么就要萬丈高樓從地起,一個一個的坑自己填。使用庫就像玩卡牌游戲一樣各種拼湊才能搞定。那么有沒有一個什么好的框架能一下搞定我們所有呢?
這個世界就是很奇妙,只要你有需要,就會有人解決你的需求。答案是有的,在前端的世界,在開源的世界里,想要什么都有現成的東西。說的優點絕對了,但是我們從來不缺少工具。那么就出現了很多重量級框架,例如YUI,EXT,Anglar.js,Bootstrap等等。這些都屬于重量級框架,使用他們的好處是,大一統車同軌,書同文,統一度量衡。除了你要加載他們的核心庫以外,你想要什么,這些重量級框架還給你提供了很多很多插件,讓你用的爽歪歪。但是問題來了,首先這么重的東西,我們真的能用多少功能?而且重量級框架都有一個通病就是綁架了碼農,碼農的思維被束縛住了。只能按照他們的方式去編寫代碼。需要什么功能就是機械的去找插件,沒有完全匹配的就得擴展插件,一個不小心一個小問題搞半天。運氣再差點,出現個什么坑,還很難解決。很多靈活性就這樣的被吞噬了,現在我們都知道,開發速度意味著什么。還有就是重量級框架的學習無疑像學了一門語言一樣,對于團隊的學習成本也是很高的。出于種種原因,重量框架在實際中使用情況并不是特別的多。反正還是拼拼湊湊,不好用了自己換換來的實際。程序員寧愿自己拼湊,也不太想弄個套餐。所以才有了包括YUI這樣的重量級框架已經不在更新的事情。
時代和觀念一直在改變和修正,重量級框架有太多的優點但是不能真正的占據絕對份額,除了使用也還受限網絡等諸多原因。
簡言之,重量級框架集成了很多輕量級框架的特點,提供了統一的編碼規則。集成了很多小框架,避免了拼湊。但是它失去了靈活,綁架了開發,阻礙了擴展。增加了學習成本。
那么引擎到底是什么呢?首先引擎是框架。然后引擎要具備輕量級的優點小,快,是個插件,是個模式。還要具備重量級框架的思想,可以給出統一的方法論,避免拼湊。同時引擎不應該像重量級框架一樣去綁架開發,應該可以提供靈活的方式去讓開發人員去使用。
二、引擎技術是怎么誕生的?
引擎技術要發揚輕量級框架的優勢。插件開發而且是不侵入式開發,是面向切面的,在愿意使用的時候使用,不愿意的時候也能較為方便的抽離,引擎要繼續向重量級框架學習統一的思想,能給出完整的解決方案去盡可能的解決問題。
我們在編碼的時候,最常用的一個思想就是封裝,這也是框架和引擎技術的重要思想。我們把操作類的,動畫類的,渲染類的,業務類的都封裝完,然后看看是否還能再抽取一些更小的粒度,最后把這些封裝成一個一個類庫,最后按照一個良好的目錄和命名規則存放。方便引用,然后再給出一個合適的加載和調度的方式,去組合代碼。程序員在開放的時候,會不斷的擴充各種粒度庫。以后的開發就有點像搭積木了。那么,一個簡單的適用于我們項目的小框架就已經有了雛形。
但是有這些遠遠不夠,因為還至少缺失一個重要的東西,就是規則。雖然編寫代碼的時候可以按照搭積木的方式去壘代碼,已經少了很多硬生生的編寫。但是還是有壘代碼的操作。最后,我們會發現,在做一個功能的時候,大體上總是會有加載模版資源,請求數據,渲染處理,事件處理等等看上去不太一樣,但是方法論無數遍重復的工作。試想一下,如果我們能把這些重復的方式也變成了規則,讓代碼可以自動按照某種關系去自動執行這些重復,我們就可以省去很多機械的重復的壘代碼的過程。
基于這個思想,我設計了規則引擎。Crow5就是在這樣的指導思想下誕生的。雖然不能完全實現代碼自動去生成代碼,但是應該盡可能的讓代碼趨近于生成更多的代碼。那么代碼憑什么可以自己按照某種邏輯去生成代碼呢?很簡單,我寫了一個內核,這個內核啥也不干,就是去讀取我下達的指令,通過我下達的指令去完成壘代碼的過程。那么,指令是什么呢?就是我給這個內核的一個配置文件。在這樣的一個思索過程中就有了以下的設計。
按照模塊開發,我們以前是control,service,module,dao分層去處理功能,最后模式發生了改變。分層最后是由內核去拼裝代碼,最后我們只要給出指令就好了。
可以看到上圖,我們在編寫代碼的時候,方式發生了改變,以前需要寫邏輯控制代碼,功能代碼等。現在只需要提供一個叫做配置文件的指令。
三、如何抽取出適用我們的引擎?
對核心引用的庫抽取,對邏輯控制抽取,對展現抽取,對業務進行抽取。
四、我們如果要編寫引擎,至少要完成哪些功能?(能稱之為引擎至少要具備的條件)
雖然沒有明文規定做一個引擎到底需要多少東西,但是這里我給出一個參考方案。如果一個引擎可以提供給別人使用,至少需要有以下處理機制,或者說設計好以下處理機制,可以把自己寫的庫很好的給其他人使用。
代碼約定模式,交互抽離模式,數據封裝模式,加密混淆機制,工具類包,插件管理模塊,加載器,攔截器,動畫處理模塊,緩存控制器,超時監聽器,模版控制引擎,性能處理模塊(懶加載,按需加載,加速器),業務邏輯控制工廠,操作日志管理。
當然根據不同的項目還有很多特殊的模塊,例如做客戶端涉及到解壓縮這樣的,可以設計一個請求代理模塊。
對外還要提供一個給開發人員配置或者編寫的API層。當然還需要一個盡可能完整的使用說明。
五、什么是約定式編程?它和引擎技術有什么關系?
我們在編程的時候,如果盡可能的減少代碼量,最直觀的方式就是約定了。例如spring種就有約定模式的影子。所以在設計Crow5的時候,我大量的采用了約定的模式。
簡單的描述,如果頁面叫index.html,那么控制器的調用可以叫UI.index。那么,頁面請求的接口可以約定成romote_index。調用的模版名字可以叫做index_tpl。如果是ajax處理的事件綁定函數可以約定成 ___index 等等。所有的處理邏輯入口和調用的名字都是可以約定的。如果有了這個約定的方式,那么所有類似的編碼就有了規則,這樣就可以抽象成規則引擎。那么以后我們只需要傳輸參數,配置。代碼就按照規則自動生成了。
上面的頁面都是用引擎自動生成的,我們可以看一下代碼。
編寫的代碼就是配置文件,其余所有代碼由引擎自動搞定。所有的性能處理都可以配置。這樣最大的減少重復編碼。
六、你對引擎技術的研究后續會是什么樣子?
對于未來繼續研究的是語義方面的抽取,所有引擎的代碼部分是可以通過云平臺自動實現按需分配,生成項目的引擎核心。根據平臺的配置自動實現配置文件的自動生成。這樣在做APP或者demo的時候,可以實現自動生成。
探索無止境,需要很多靈感,很多設計靈感就是從動物身上得到的,例如在設計心跳保持技術的時候,就是觀察青蛙冬眠這個事情上,抽取總結心跳加速,減速,停止,蘇醒等。希望能把引擎技術繼續往語義方向上突破,可能那個時候的編程就變成了問答。
【編輯推薦】
