物聯網應用開發對編程語言的要求
1. 開發語言必須是跨硬件平臺的
所謂跨硬件平臺,指的是編寫的物聯網應用程序,能夠在多種不同的目標硬件設備上運行,而不用重新編譯甚至修改應用程序。這里的不同的目標硬件,主要是指CPU指令集,內存大小,外設的接口類型,外設的訪問方式等等硬件層面的東西。如果開發語言不是跨硬件平臺的,那么針對一種硬件平臺開發的應用程序,就只能運行在這一種硬件設備上。因為硬件平臺的具體細節情況,都體現在目標程序中。最典型的例子是采用C語言開發的應用程序,必須根據不同的目標CPU指令集,編譯成匹配目標指令集的二進制代碼,才能運行。這樣如果切換到另外一種指令集的CPU,則必須重新編譯,甚至要重新修改應用程序。這在硬件標準化程度非常高的個人計算機領域,問題不大,因為通用的CPU類型就那么幾種(Intel,ARM等),而且硬件配置都非常標準,硬盤等存儲設備,顯示器,鍵盤/鼠標等輸入設備,USB接口,網絡接口等等,都是標配。因此針對不同硬件平臺的軟件移植工作量并不大。但到了物聯網時代,這顯然無法滿足物聯網硬件碎片化特征的需要。在物聯網環境中,目標設備CPU的種類是PC時代的數十倍,同時硬件配置也各不相同,大部分物聯網設備的配置都千差萬別,因此,如果仍然采用傳統的不能跨硬件的開發語言來編寫物聯網應用程序,那么對同一種功能的應用程序來說,就需要針對不同的CPU類型,不同的硬件配置,分別進行開發和部署。這顯然是無法逾越的困難。
而采用跨平臺的編程語言,則可以解決這個問題。比如針對智能攝像頭而言,A廠商的攝像頭個的配置,可能是ARM的CPU,USB接口,分辨率是1024*768等,而B廠商的攝像頭可能是基于x86的CPU,SPI接口?;跀z像頭編寫一個人臉識別程序,如果采用跨平臺的編程語言,則針對A廠商設備編寫的應用程序,可以直接在B廠家的設備上使用。但是如果編程語言不是跨硬件平臺的,比如C/C++語言,則針對A廠家的攝像頭編寫的應用程序,必須經過重新編譯(甚至還需要大量的修改)之后,才能在B廠家的攝像頭上運行。物聯網設備的碎片化特征,決定了開發語言必須是跨硬件平臺的。
采用跨硬件平臺開發語言的另外一個好處,就是限制錯誤范圍,不會因為應用程序層面的錯誤,而導致整個系統崩潰。由于物聯網設備硬件配置的巨大差異,由硬件與軟件不匹配導致的錯誤會大大增加。比如,還是上面的智能攝像頭的例子,如果應用程序通過人臉識別,發現可疑人員進入某個特定的范圍,則會引發報警。報警的方式有很多種,比如會給智能攝像頭的后臺發送告警信息,調用本地的揚聲器發出警報,甚至在智能攝像頭的屏幕上輸出告警文字等。很可能有的攝像頭沒有配置本地揚聲裝置,而有的攝像頭則沒有配置本地顯示器。這時候上述應用程序的告警代碼,就會因為無法找到硬件而出現錯誤。如果這種錯誤不被有效隔離或者限制范圍,那么可能會導致整個系統的崩潰。
一般的采用跨平臺編程語言開發的應用程序,都是運行在一個虛擬機或者解釋引擎之上的。虛擬機或者解釋引擎進一步運行在物聯網設備的操作系統上。應用程序層面的錯誤,會被虛擬機或者解釋引擎捕獲,并進行特定的處理,比如終止應用程序的運行,而不會把應用層面的錯誤傳播到系統層面。但是傳統的非跨硬件平臺的編程語言,則無法限制錯誤范圍。比如,采用C語言開發的應用程序,如果因為堆棧溢出或者指針錯誤而導致內存紊亂,則會導致整個系統崩潰,尤其是在內存管理單元(MMU)功能缺失的情況下,而這在物聯網應用中是非常普遍的。
跨硬件平臺編程語言的一個不足,就是其運行效率會比傳統的編譯型語言(C/C++等)要低一些。這是因為大多數跨硬件平臺的語言,都需要一個虛擬機(VM)或解釋引擎的支持才能正常運行。虛擬機或者解釋引擎本身是一個運行在物聯網操作系統之上的一個應用程序,它會讀取應用程序的可執行文件或者源代碼,然后分析解釋,轉換為目標CPU的指令并啟動運行。而傳統的編譯型語言,則直接把源代碼編譯為目標計算機的指令集,可以直接被CPU執行。顯然,這個中間轉換的過程,會降低應用程序的執行效率。但是執行效率降低的程度,與虛擬機或者解釋引擎的實現強相關。有的虛擬機或者解釋引擎,采用一些優化算法,并運用諸如“一次解釋,多次運行”等機制,可以使得這種效率上的損失降到最低。比如Google推出的V8引擎,可以使得JavaScript語言編寫的應用程序,能夠基本達到C/C++程序的水平。因此,與跨硬件平臺編程語言配合的VM或者解釋器,也是至關重要的。
但無論如何優化,JavaScript等跨硬件平臺語言始終無法真正趕上或者超于C/C++等編譯型語言的效率。因此在一些對實時性和執行效率要求及其嚴格的場合,比如飛行控制,比如核電監控等等應用領域,在應用之前必須經過細致詳盡的評估測試。如果跨平臺語言無法滿足目標場景的應用,那么建議還是采用傳統語言來進行應用程序的開發。畢竟,采用跨平臺語言的初衷,是為了更好的擴大物聯網應用程序的運行范圍,能夠降低開發效率和開發難度,快速的形成物聯網生態圈。而這類要求極高的場景,已超出這個范疇。因此,對傳統編程語言和編程API的支持,是物聯網操作系統必須能夠提供的能力。
面向對象是一種程序設計方法,或者說它是一種程序設計范型,其基本思想是使用對象,類,繼承,封裝,消息等基本概念來模擬現實世界,從而完成程序設計任務。而在面向對象編程思想出現之前,軟件行業流行的是模塊化的編程思想,即把一個大的計算機程序(或者代碼),按照功能拆分為一個一個小的源代碼模塊,通過明確定義的接口(API),把不同的功能模塊組裝在一起,形成最終的計算機程序。
而面向對象則是從現實世界中客觀存在的事物(即對象)出發來構造軟件系統,并在系統構造中盡可能運用人類的自然思維方式,強調直接以問題域(現實世界)中的事物為中心來思考問題,認識問題,并根據這些事物的本質特點,把它們抽象地表示為系統中的對象,作為系統的基本構成單位(而不是用一些與現實世界中的事物相關比較遠,并且沒有對應關系的其它概念來構造系統)。這可以使系統直接地映射問題域,保持問題域中事物及其相互關系的本來面貌。
面向對象編程方法,可以讓程序員以更接近實際世界的方式來理解應用場景,建立程序開發模型,同時也可以大大加快開發速度。對于大型的軟件,面向對象思想可以簡化開發維護過程,降低開發成本。在物聯網領域,面向對象編程思想更有價值。因為我們面對的是一個一個的“物”,每個物體都可以抽象為程序開發領域的一個對象,通過不同對象(物)之間的消息交互,可以快速完成復雜應用系統的開發。相比傳統的模塊化編程思想,面向對象編程思想更適合物聯網應用開發。
需要說明的是,面向對象編程思想是一種方法,是一種編程的理念,理論上說,與具體的編程語言是沒有關系的。眾所周知,C語言是面向過程的開發語言,但是完全可以用C語言開發以面向對象思想設計的應用程序。比如HelloX物聯網操作系統,完全采用面向對象的思想設計,但是在實現時,確是采用C語言來實現的。具體來說,就是采用C語言的函數指針,結構體等等語言特性,來模擬出“對象”,“方法”,“消息”,甚至“繼承”等等面向對象的概念。另外一個例子就是,著名的Windows NT操作系統內核,是完全按照面向對象思想設計的,但是其實現,仍然是采用C語言。
但如果采用面向對象的語言,以面向對象的方法來開發物聯網應用程序,會更加事半功倍。之所以用傳統的非面向對象語言來開發應用程序,是一種折中的選擇。因為如果采用C++或者Java等面向對象的語言,則由于語言本身的一些機制,會給操作系統級的開發帶來影響。而且采用面向過程的語言來仿真面向對象編程語言,也是不徹底的,很多機制根本無法模仿,比如函數或方法的重載,動態對象類型等等。如果不是系統級的程序開發,不是必須要用C或者匯編等這一類底層編程語言,那么采用面向對象的編程語言是最好選擇。
而物聯網應用開發則符合這個前提,它是應用層面的開發,不需要對底層硬件進行管理和操作,因此不需要C/匯編等底層語言。這樣采用諸如Java,JavaScript,Python等面向對象的語言,并采用面向對象的思想,顯然是最好選擇。
3. 支持事件驅動機制
與以人為中心的傳統軟件開發模式不同,物聯網時代的軟件,都是受“事件”驅動的。面向物聯網的程序,大多數情況下處理的是一個一個的外部事件,根據外部事件做出響應。比如一個火警探測設備,會針對“探測到起火”等異步事件,做出對應的動作。物聯網軟件開發,很多情況下就是編寫一個一個的事件處理程序,并與事先定義好的事件關聯在一起。這樣一旦外部事件發生,則處理程序就會被調用。這種以“事件”為中心的物聯網編程方法,必須配以能夠支持完善事件驅動機制的開發語言。
需要說明的是,事件驅動是一種程序設計的方法,或者機制。很多語言都可以實現事件驅動的編程機制。比如C語言,通過聯合運用回掉函數,函數指針等等語言特性,可以實現復雜的事件驅動機制。最典型的Windows操作系統,就是采用C語言實現了完整的事件驅動機制。但是不同的語言,實現事件驅動機制的難易程度不同。采用C語言實現事件機制,需要相對復雜的語言特性,而且要設計一套復雜的底層框架來支持。但有的語言,實現事件機制則會相對簡單。比如JavaScript語言,由于其動態類型的特征,以及函數本身就是對象的特點,實現事件驅動機制會非常簡單。
4. Internet親和性
所謂Internet親和性,是指能夠與現有的Internet相關標準兼容,采用這種語言開發的應用程序,能夠簡單容易的集成到Internet上。我們認為,物聯網不會是一個全新的網絡,不會從零開始建立,它必然是基于現有Internet的延伸。支撐Internet的大部分核心協議,比如IP協議,TCP/UDP協議,HTTP/HTTPS協議,都會在物聯網應用中得到重用。同時,Internet上的數據傳輸格式,比如JSON,XML,正則表達式(RegExp),也會被大量重用到物聯網中。這樣物聯網就可以很容易的與現有的Internet互通和集成,重用現有的Internet基礎架構。在此基礎上,再進一步擴展和壯大。
鑒于此,物聯網應用程序開發語言,應該能夠有效支持上述Internet已有的協議和特性。當然,從理論上說,任何編程語言通過有效擴展,都可以實現上述特性的支持。即使匯編語言,我們對其從底層對其進行擴展,比如先實現一個基于匯編語言的TCP/IP協議棧,基于此協議棧再實現一系列的協議,包括HTTP/HTTPS等。對于數據交換格式的支持,我們也通過匯編語言,實現完整的JSON,XML等數據格式的封裝和解析,實現完全的正則表達式。這樣缺少什么,就補充什么,必然能夠達到與Internet完全互通的目的。但是這種代價就太大了,從實現角度,基本上是不可行的。
而有的語言,由于在Internet應用開發中被廣泛應用,從而對上述特性有了成熟廣泛的支持。比如JavaScript,大部分的Intrernet前端應用程序(即在瀏覽器內運行的Internet頁面,腳本,或者插件等)都是采用JavaScript開發。隨著Node.js的流行和壯大,導致現在很多Internet的后端應用,都是采用JavaScript開發的。而且在Internet的數據交互中被廣泛采用的JSON標準,也是直接由JavaScript發展而來。JSON,就是JavaScript Object Notation的縮寫,是JavaScript用于內部標識對象的數據格式。由于這種格式簡單明了,表示能力強,逐漸替代了廣泛使用的XML,成為Internet事實上的數據表示標準。因此,如果采用JavaScript作為Internet的應用開發語言,那就會天然支持Internet已有的協議和標準,從而與Internet做到最大程度的兼容和親和。
所謂的運行環境,是指支撐應用程序正常運行的相關組件,這些組件不屬于某一個特定的應用程序,是所有采用同一種編程語言開發的應用程序都需要的公共組件。比如針對C/C++語言,C運行庫(clib)和C++運行庫就是運行環境的一部分,幾乎所有的C/C++應用程序,都需要C運行庫的支持。操作系統在加載應用程序的時候,同時要加載這些運行庫組件。運行庫提供了應用程序所需的最基本函數和功能調用。
對于Java或者JavaScript,Python等這一類跨平臺的編程語言,除公共代碼庫等組件外,還需要虛擬機或者解釋引擎的支持。對Java語言來說,采用Java語言開發的應用程序首先被編譯為Java字節碼,然后被Java虛擬機加載和執行。而對于JavaScript等腳本語言來說,則直接被解釋引擎加載和解釋。從操作系統的視角來看,虛擬機或者解釋引擎本身就是一個應用程序。
在物聯網環境中,如果某一種開發語言的運行環境太大,在一些資源受限的場合就無法使用。因此,物聯網應用開發語言的運行環境,必須足夠緊湊,占用內存必須足夠少。比如,在最極端的情況下,如果運行環境對內存的最低要不應該超過64K字節。
物聯網操作系統的最核心價值,就是提供一個公共的物聯網運行和開發平臺,使得各種各樣的物聯網應用程序,都可以在這個平臺上開發和運行。這樣逐漸積累,最終會形成一個類似移動互聯網領域的生態鏈,支撐物聯網的大發展。而物聯網應用開發語言是支撐這個生態環境壯大的基礎。
如果物聯網開發模式依然采用傳統的嵌入式開發模式,采用C或者匯編作為主要的開發語言,需要程序員掌握硬件層面的每一個細節,包括CPU的指令集,硬件的I/O接口,甚至需要通過信號分析儀器去分析芯片的管腳輸入和輸出,則是無法推動物聯網生態鏈發展壯大的。這種開發模式的入門門檻太高,而且開發效率太低,針對某一個硬件或者場景開發的代碼,無法復用到其它的場景中。
因此,物聯網開發語言和對應的開發模式必須足夠簡單,足夠方便,把這種傳統的開發門檻徹底降下來。理想的目標是,任何一個具有計算機基礎的人員,經過幾天甚至數小時的學習,就可以開發出實用的物聯網程序。更理想的是,直接對已有的被廣泛使用的編程語言進行改造,使之直接應用于物聯網應用程序的開發。這樣就可以充分利用已有的人才和代碼積累,“站在巨人的肩膀上”。比較典型的例子就是移動互聯網領域的Android操作系統,采用Java語言作為應用程序開發語言,這樣直接就繼承了現有的豐富的Java開發資源,把當前數量龐大的Java工程師一下子變成了“Android程序員”。
同時,對于開發物聯網程序的方法和工具,也應該充分降低門檻。原有的嵌入式開發模式,需要安裝專業的工具(編譯器,連接器,調試器等),同時需要復雜的命令來構筑開發工具鏈。很多對嵌入式開發感興趣的工程師,都因為開發環境的復雜,工具鏈的繁瑣,而望而卻步。物聯網應用開發必須改變這種狀況,對開發人員“足夠友好”。比如,采用單一的工具或集成開發環境,就可以完成程序的編寫,編譯,調試,模擬運行等所有開發工作。更簡單的方式是,直接采用腳本語言,開發人員甚至不需要安裝任何開發工具,直接通過記事本等文本編輯器編輯代碼,然后直接上傳到物聯網設備中即可運行。這樣開發門檻降下來了,自然會有大量的程序員加入進來。再建立一種代碼分享機制,就會形成滾雪球效應,最終促進物聯網生態環境的大發展。
從這個角度看,傳統的編譯型語言,比如C/C++,已經不適合物聯網應用的開發。而腳本語言,比如JavaScript,則更有優勢。
二. 常見計算機開發語言對比分析
下面對當前常見的計算機程序設計語言進行分析,比對物聯網應用開發對編程語言的要求,看看哪一種編程語言更適合物聯網的需求。下面的表格示意了常見編程語言的對比:
對比角度/編程語言 |
C |
C++ |
Java |
JavaScript |
Python |
跨硬件平臺 |
不支持 |
不支持 |
支持 |
支持 |
支持 |
面向對象 |
不支持 |
支持 |
支持 |
支持 |
支持 |
事件驅動機制 |
一般支持 |
一般支持 |
一般支持 |
良好支持 |
一般支持 |
Internet親和性 |
低 |
低 |
中 |
高 |
中 |
運行環境緊湊程度 |
高 |
高 |
中 |
中 |
低 |
從這個對比表中可以看出,JavaScript是最適合物聯網應用開發的。首先,把不能支持“跨硬件平臺”特性的語言排除掉,這樣C/C++語言就被排除出可選范圍。再對比事件驅動機制和Internet親和性兩個角度,發現JavaScript語言最具有優勢。對于運行環境的緊湊程度,Java和JavaScript不相上下,而Python語言目前不具有優勢。因此綜合對比下來,JavaScript語言最適合物聯網應用的開發。
下面對每種語言,進行簡單分析。
首先看C語言,這是目前物聯網和嵌入式領域應用開發的主流語言。但是由于C語言是一種編譯型語言,必須由編譯器根據目標硬件的CPU指令集,把C語言編譯成適應特定硬件的可執行代碼。這樣的問題是,必須針對所有的目標硬件,都要對C語言進行編譯和鏈接。同時由于硬件層面的差異性,在一種硬件平臺上開發的C語言應用,在移植到另外一個硬件平臺上時,必須修改源代碼。這顯然大大限制了C程序的應用范圍。實際上,現在有大量的C語言代碼,但是這些代碼都是針對特定硬件開發的,因此無法直接移植。C++語言的情況與此類似。
C語言是一種面向過程的語言,沒有內置的面向對象機制。這不像C++語言,C++語言提供了完整的面向對象編程語法和機制,比如class關鍵字,template關鍵字,類的繼承,虛函數和函數重載等。這些豐富的面向對象的語言特性,可以使得C++語言很好的支持面向對象的開發。但C語言就沒有提供此類內置特性,因此不是一種面向對象的編程語言。
雖然采用C語言的函數指針,回掉函數,結構體(struct)等語言特性,可以實現簡單的面向對象機制和事件驅動機制,但是與其它內置這些特性的開發語言相比,實現起來非常繁瑣,且有的特性根本無法實現。
雖然C語言有這些不足,但是始終無法否認C語言是“編程語言之王”的崇高地位。正是C語言及C語言開發的軟件,比如UNIX操作系統,Linux操作系統等,奠定了計算機領域的核心軟件基礎。支撐國計民生的核心系統中運行的核心程序,比如電力系統,航空航天系統,鐵路運輸系統,核電控制系統,通信網絡系統等等,大部分都是采用C語言開發。毫不夸張的說,是C語言支撐起了當前的計算機和網絡世界。其它語言的底層運行環境,比如Java虛擬機,JavaScript解釋引擎,Python解釋引擎等等,都是采用C語言開發。即使C語言滿足不了我們在這里定義的物聯網編程語言的要求,但是在一些性能和實時性要求極端的場合,C語言仍然是唯一選擇。
C++語言的大部分情況與C語言類似。但與C語言不同的是,C++提供了豐富完整的面向對象編程機制。但正是這些面向對象機制,使得C++語言的運行環境變得比C復雜和不確定,在對目標可執行代碼要求嚴格的嵌入式及操作系統領域,C++并不如C語言合適。比如,為了實現C++語言的對象構造函數和析構函數,異常機制,虛函數等特性,C++語言編譯器在編譯的目標代碼中,植入了程序員不可見的代碼。這對系統級的編程是非常致命的,因為這些不可見的內置代碼,系統程序員無法感知,出了問題也無從查起。但是由于C++語言的面向對象及編譯型語言的高效快速等特征,使得C++語言非常適合對性能要求較高的應用程序開發,比如游戲應用,Internet瀏覽器等性能要求較高的大型應用程序。但是由于C++語言不能跨硬件平臺,因此不適合物聯網應用開發。
Java作為一種面向對象和跨平臺語言,是比較適合物聯網應用對開發語言的要求的。但是由于Java語言的開放程度并不如其它語言高,涉及到一些知識產權的糾葛。同時Oracle公司對Java的支持力度越來越低,因此Java語言呈現出逐漸式微的態勢。同時,在Internet親和性及事件驅動機制的支持力度上,Java并不如JavaScript,因此在我們的對比中,Java也被淘汰出局。
Python語言也是一種被廣泛應用的腳本編程語言,尤其是在大數據分析,數學處理領域,得到廣泛應用。但是其Internet親和性并不如JavaScript,同時截至目前,Python解釋器并沒有被優化到可以支持資源受限系統應用的水平,因此Python仍然不如JavaScript。
綜合比對下來,在物聯網應用開發領域,JavaScript最終勝出。接下來,我們對JavaScript語言進行更加詳細的闡述。需要說明的是,這僅僅是在“物聯網應用”開發領域,JavaScript具備優勢。在對性能和可靠性要求極度苛刻的物聯網系統級開發場景,JavaScript仍然不適合,C語言仍然是這種場景的唯一選擇。
還有其它一些比較流行的語言,比如C#,VB,VBScript,GO,Delphi,Object-C等編程語言,我們并沒有進行重點分析和比對。這是因為有些語言的開放性不足,比如C#或者Object-C,都只能在廠商特定的平臺或工具上開發,還有一些語言的應用場景比較局限,因此暫時不作為重點分析對象。
因此,綜上所述,就目前來說,我們認為JavaScript是比較適合物聯網應用開發的編程語言。隨著物聯網的發展,未來或許有更加合適的編程語言被開發出來。