4 IoT 平臺(tái)衡量標(biāo)準(zhǔn)
在討論 IoT 平臺(tái)之前,我們需要知道有哪些衡量標(biāo)準(zhǔn)來(lái)判斷一個(gè) IoT 平臺(tái)的優(yōu)劣。下面是我提出的三個(gè)衡量標(biāo)準(zhǔn)
? 現(xiàn)代程序設(shè)計(jì)語(yǔ)言
? 面向應(yīng)用的抽象
? 提供生產(chǎn)支持
4.1 現(xiàn)代程序設(shè)計(jì)語(yǔ)言
鑒于摩爾定律的存在,在現(xiàn)代軟件開(kāi)發(fā)中,開(kāi)發(fā)的效率比代碼執(zhí)行的效率要重要。所以,一個(gè)好的 IoT 平臺(tái),需要有一門(mén)現(xiàn)代的程序設(shè)計(jì)語(yǔ)言。
我們不妨先看看 C/C++ 這個(gè)傳統(tǒng)的嵌入式開(kāi)發(fā)語(yǔ)言在現(xiàn)代程序設(shè)計(jì)語(yǔ)言所需特性上的表現(xiàn),如表1。
表1 C/C++在現(xiàn)代程序設(shè)計(jì)語(yǔ)言所需特性上的表現(xiàn)
再來(lái)看看 Ruff 選擇的 JavaScript 在這些特性上的表現(xiàn),如表2。
表2 Ruff 選擇的 JavaScript 在這些特性上的表現(xiàn)
通過(guò)對(duì)比,不難發(fā)現(xiàn),雖然 C/C++ 依然戰(zhàn)斗力十足,但作為“現(xiàn)代程序設(shè)計(jì)語(yǔ)言”,它們顯得不那么“現(xiàn)代”了。或許你會(huì)好奇,Ruff 為什么選擇其它的“現(xiàn)代程序設(shè)計(jì)語(yǔ)言”,主要有下面幾點(diǎn)考量。
4.2 面向應(yīng)用的抽象
什么是面向應(yīng)用的抽象?對(duì)比兩段代碼,我們便不難發(fā)現(xiàn),這兩段代碼完成是同樣的工作,點(diǎn)亮一盞燈。
先是傳統(tǒng)嵌入式風(fēng)格,簡(jiǎn)單起見(jiàn),我們用了 Python 代碼做示例:
GPIO.output(11, GPIO.HIGH)
再是 Ruff 的代碼,用的是 JavaScript 語(yǔ)言
$(‘#led’).turnOn();
我們?yōu)槭裁葱枰布橄竽兀恳驗(yàn)槲覀兛吹秸麄€(gè)軟件開(kāi)發(fā)的趨勢(shì)就是抽象度越來(lái)越高,從匯編到 C 語(yǔ)言,再到Java,今天還會(huì)有各種各樣的 DSL (Domain Specific Language,領(lǐng)域特定語(yǔ)言)。早年間,編寫(xiě)代碼,我們可能會(huì)質(zhì)疑編譯器是否正確,手寫(xiě)匯編效率會(huì)更高,但今天,我們肯定不會(huì)這么做,開(kāi)發(fā)效率太低,因?yàn)橛辛顺橄螅讓拥臇|西可以不斷優(yōu)化,越做越好。之所以抽象程度能不斷提升,還要拜摩爾定律所賜,硬件能力越來(lái)越強(qiáng),一些執(zhí)行上的性能損失,我們是可以承受的。
那我們需要怎樣的抽象呢?從發(fā)展趨勢(shì)可以看出,抽象的趨勢(shì)一定是越來(lái)越接近問(wèn)題領(lǐng)域。對(duì)于 IoT 平臺(tái)而言,一定是越來(lái)越接近于應(yīng)用開(kāi)發(fā)。在 IoT 平臺(tái)的嘗試中,我們看到了幾種不同的抽象。
? 無(wú)抽象
傳統(tǒng)的嵌入式開(kāi)發(fā)按照這個(gè)標(biāo)準(zhǔn),就是無(wú)抽象的,其特點(diǎn)是面向硬件接口編程。
GPIO.output(11, GPIO.HIGH)
? 編程接口抽象
諸如 Ruff、Tessel、Jonny-Five、Cylon.js 等一些 IoT 平臺(tái)開(kāi)始提供面向應(yīng)用的編程接口抽象,讓開(kāi)發(fā)者無(wú)需關(guān)注底層的實(shí)現(xiàn)細(xì)節(jié)。
board.on(“ready”, function() {
var led = new five.Led(13);
led.strobe();
});
但在這里,我們不難發(fā)現(xiàn),我們依然要對(duì)底層的接口有了解,否則,你便不知道,這段代碼中的13是做什么用的。
? 隔離硬件配置的抽象
Ruff 在提供面向應(yīng)用的編程接口抽象基礎(chǔ)上,更進(jìn)了一步,將硬件配置隔離出去。在 Ruff 代碼中,我們甚至看不出硬件配置是什么樣的。
$.ready(function (error) {
$(‘#led’).turnOn();
});
Ruff 之所以要提供隔離硬件配置的抽象,主要是為了提供生產(chǎn)支持。
4.3 提供生產(chǎn)支持
大家對(duì)于新出現(xiàn)的 IoT 平臺(tái),普遍有一個(gè)誤解,這些平臺(tái)只能用在原型研發(fā)上,因?yàn)樗鼈兛吹降氖牵捎?JavaScript 的硬件要求都很高,與現(xiàn)在普遍的硬件開(kāi)發(fā)狀況不符。現(xiàn)在 JavaScript 已經(jīng)可以運(yùn)行在一些資源有限的系統(tǒng)上,比如 MCU,Ruff 就有自己的 MCU 版本,支持了幾款不同的 MCU。
Ruff 所做的事情更進(jìn)了一步,它將硬件配置與應(yīng)用本身分離開(kāi)來(lái),這樣的做法帶來(lái)一些好處是
? 應(yīng)用開(kāi)發(fā)者無(wú)需關(guān)注硬件如何配置,可以將更多的將注意力放在應(yīng)用邏輯本身
? 硬件具體的配置方式可以在具體的部署時(shí)決定
一旦硬件配置可以在部署時(shí)決定,便出現(xiàn)了另外一種可能,也就是,同一個(gè)應(yīng)用可以運(yùn)行在不同的硬件上,也就是跨硬件應(yīng)用就出現(xiàn)了,這也就讓前面提及的“重復(fù)造輪子”的情況得到一定程度的緩解。
伴隨跨硬件應(yīng)用的出現(xiàn),還會(huì)有一個(gè)額外的作用:測(cè)試。以往硬件測(cè)試一定要在硬件上完成,因?yàn)榍懊嫣峒暗姆N種原因,硬件測(cè)試往往要部署一個(gè)包括系統(tǒng)在內(nèi)的應(yīng)用,所以,效率是極低的。而我們知道,應(yīng)用開(kāi)發(fā)中,大量的測(cè)試實(shí)際上是應(yīng)用邏輯的測(cè)試,屬于軟件測(cè)試的部分,理論上是可以在開(kāi)發(fā)機(jī)上完成的。因?yàn)橛辛擞布綦x,Ruff 就提供了在開(kāi)發(fā)機(jī)上做軟件測(cè)試的能力,開(kāi)發(fā)的效率由此得以提升。
下面是一個(gè) Ruff 測(cè)試代碼的例子,可以在開(kāi)發(fā)機(jī)上運(yùn)行:
var runner = require(‘ruff-app-runner’);
var verify = require(‘ruff-mock’).verify;
exports[‘test should call turn on while application is ready’] = function() {
runner.run(appPath, function() {
verify($(‘#led’)).turnOn();
});
};
require(‘test’).run(exports);
評(píng)論
查看更多