發表文章

目前顯示的是 2012的文章

Release GContext Node.js Module!

How to write a native desktop application in Node.js? Perhaps you know many modules can do that easily, something's like node-gui and jsdx-toolkit. In order to develop system program, DBus module is the most important thing you must have as well. With Dbus module, you can handle all communications between programs. Furthermore, you can control low-level functions system provided via DBus, which includes hardware, networking and operation system features. Unfortunately, all things do not work at all since new version of Node.js. Many system libraries are based on GLib, and work with GLib event loop. For writing a node.js binding with such libraries, libev is the only way to integrate event loop between node.js event loop and GLib main context. The problem is that libev is deprecated since 0.8 node.js cause modules which depends on libev will be broken on latest and higher version. Nothing works if there is no libev. In fact, upstream announced that libuv is being only one way to

AppHouse 簡報釋出!

昨日應邀參加『 企業雲端環境建置與應用技術研討會 』,給予一場『AppHouse - 國產 PaaS』的簡報分享,聽眾相當熱情,在會後也一起相互討論了許多技術與非技術等議題。這次的分享,主要在說明 AppHouse Project 的細節,並闡述了 PaaS 在雲端產業中的定位。為了讓聽眾更能理解,也特意以小弟的淺見和觀點,用簡單明瞭的方式描述『什麼是雲端』。 後記 會後與不少人交流,發現過去很多人被『雲端』一詞搞糊塗了,不能理解。如果你也有此困擾,不妨可以看看此簡報。 若您有任何疑問,或需要協助的地方,歡迎與我聯絡。:-)

jsdx-power 讓你使用 JavaScript 實現電源管理

既然會成立新創公司,總有些自己的想法,也期望做一些和其他人不一樣的事,對我們而言,改變世界事小,留下長久價值更重要。也許你有點印象,筆者今年度到處給予的 Talk,多半都是與 Node.js 相關,也透漏許多正在執行的計劃。因此,有些人可能聽過筆者提及『JSDX Framework』,這是『 Mandice 』的長期計劃,也是將 JavaScript 落實在系統、桌面和嵌入式裝置的解決方案。 由於 JSDX 是一個開放原始碼專案,市場上也已經有一些產品和公司專案導入使用,但因為合約的關係,我不能透漏太多細節,所以本文將只討論些許技術細節。說到這,也許你還是沒什麼概念,但若是真要舉出最直接與其相關的專案,就是今年 8 月,於 COSCUP 一場議程中所公開的『JUICE Desktop Environment』(簡報檔詳見舊文: 【COSCUP 2012】閉幕!簡報釋出! ),完全以 JavaScript 實作的 3D 桌面環境。 JSDX 包括許多元件,從 GUI Toolkit(使用者界面)、Multimedia Player(多媒體播放)、Network Manager(網路管理)到 Sound Manager(聲音管理)等,提供了各類系統控制或硬體相關的 APIs。程式開發者只需要會 JavaScript 語言,就可以使用這些 JSDX 所提供的 APIs ,開發各類應用程式或系統程式。 回應本文標題,JSDX 如果可以拿來開發桌面環境,當然也有電源管理相關的 APIs 可使用。所以在這邊我們要討論的元件是『 jsdx-power 』,你可以在 github 上取的他的 Source Code,亦或是直接透過 npm 安裝。 npm install jsdx-power 這邊簡單示範如何使用 JavaScript 透過『jsdx-power』命令作業系統休眠: var Power = require('jsdx-power'); var power = new Power; power.init(function() { power.suspend(); }); 後記 JUICE DE 的 juice-panel 電量顯示,就是使用了 jsdx-power,有興趣的人可以參考其 Source Code。

Node.js 裡的 JavaScript Array 非同步操作

如果你原本是一個專業的前端工程師,或許在 Node.js 出來之後,便開始嘗試了 Server 程式的開發。然後發現,使用 JavaScript 開發 Server 程式的過程中,有很多的細節應該注意,尤其是碰上處理大量資料和 I/O 操作時,更要對 JavaScript 引擎的運作原理有一定程度的理解。因為,絕大多數的問題,都是出在非同步(Asynchronize)與同步(Synchronize)的機制上。 許多開發人員,都會認同在開發 Node.js 程式時,盡可能、甚至絕對不要使用『同步』的方法和 API,因為,那會打亂 JavaScript 事件引擎的運作,產生各種詭異的後疑症,而且非常難以除錯。如果你發現你的程式會莫明自己結束,或是程式運作的流程不如預期,可能就是掉入了『同步』與『非同步』的陷阱了。 如果你稍微翻過文件,就會發現,其實 Node.js 本身對很多的 API,已經同時提供了『同步』與『非同步』兩種版本供開發者使用。不過,雖然 Node.js API 都有提供『非同步』版本,但是有些根本東西,卻欠缺『非同步』的方法,像是本文標題所提到的『Array』,就是其中之一。 針對 Array 的諸多操作,最常見的莫過於 forEach 方法,用來處理每一個 Array item: var arr = [ 1, 2, 3, 4 ]; arr.forEach(function(element, index, arr) { // Processing }); console.log('Completed'); 然而,這個方法是『同步(Synchronize)』,也就是會讓整個程式阻塞,等所有 Array item 讀出和處理完之後,才顯示最後的『Completed』字串。 類似的東西,不少人也會使用純 for-loop 來實作,但也都是一樣的狀況: var arr = [ 1, 2, 3, 4 ]; for (var i in arr) { // Processing } console.log('Completed'); 想想看,如果 Array item 的數量相當多,又或者是每個 item 的處理時間相當長,整支程式會像死當一樣沒反應。要知道,讓一段程式跑太久,是 Event

探究如何整合 GLib Main Event Loop 和 Node.js 的 libuv

圖片
在普通情況下,整合 GLib Main Event Loop 和 libuv 不是件平常人會做的事,因為,一般人使用著 GTK+、Clutter、DBus 等等函式庫(Library)時,永遠只會使用 GLib 而不會使用到第二套事件引擎。但是,在 Node.js 中,其事件引擎並不是 GLib,而是使用自己的『libuv』,想同時運行兩套事件引擎是不可能的,所以這將注定我們無法以 Node.js 去引入 GTK+、Clutter、DBus 等函式庫來使用。不過,天下文章一大抄,世界上所有事件引擎的設計差異不大,在理解 GLib Context 的運作後,我們還是可以嘗試將兩者整合在一起,協同運行。 簡單理解一下事件引擎,其說白了就是一個跑到天荒地老的無窮迴圈,不停的去檢查是否有事件被喚醒。所以,由此可知,兩套事件引擎不能被同時跑起來,因為任何一個事件處理的無窮迴圈,都將導致另一個事件處理的迴圈無法正常運作。所以,首要解決的課題,就是讓兩個無窮迴圈可以同時運作。 為了解決這樣的問題,你可能會想到去使用 Thread (執行緒/線程),只要在建立兩個 Thread,然後各自跑不同的事件引擎就可以了。但是這樣做,問題馬上就會出現。由於程式正在運作的過程中,事件數量相當多,事件被安插和喚醒的次數非常頻繁,這將導致兩個 Thread 之間很難維持穩定的資料交換,你得實作 Mutex Lock 等機制來達成 Thread-safe,更還要想辦法解決兩邊各類大小資料交換的需求。種種原因,都會造成兩個事件引擎大量的彼此等待,而效能不彰。此外,也不易同時控制兩邊的事件觸發順序,以及事件被喚醒時間的精確度,如計時器(Timer)。 既然使用 Thread 是不好的做法,是否有其他方式可以解決我們一開始的課題?解決方法是有的,從事件引擎的運作細節,我們可以發現一些端倪。 一般來說,大部份的事件引擎都包括了幾個部份: 從 Initial 出發, Event Loop 的迴圈每運行一次,都經歷了『prepared』、『Polling』和『Dispatching』三種狀態,若用白話來說,他們所代表的意義就是『已準備好事件清單』、『監控事件』、『喚醒、分配並處理事件』。 如果你去參考事件引擎程式碼,會發現在三個狀態之間,分別有『prepare()』、『query(

MongoDB Replication 簡記

就在幾天前,MongoDB 邁入了 2.2.0 的穩定版本。我們若回頭來看,MongoDB 一直到了 2.0 前後,比起早期版本,已經有長足的進步,並且支援了相當多的功能,也對規模化和資料庫系統管理下了很多功夫。對於大多數的資料庫應用,已經非常適合。 若你對資料庫相關技術有些了解,就會知道,當資料庫的資料發展一定規模程度,或是要確保系統不當機時,我們就需要用到 Master/Slave 的方式去備份和備援,當主要(Master)伺服器出了問題,次要(Slave)伺服器便即時補上,保持系統運作。但是,既然已經有 Master/Slave 機制,是否可以有更多台備援呢?更或者進一步,將讀寫分開在不同伺服器,以分攤流量和系統負載,並加速讀寫速度。而 Replication 就是這樣的機制,可以用來動態同步多台資料庫伺服器的資料,也可以當主要伺服器因故下線時,讓其他伺服器即時替補主要機器的位置。 在 Debian 上設定 MongoDB 的 Replication 相當容易,首先在想要變成主要(Primary)的機器上,打開設定檔(/etc/mongodb.conf),並為我們的 Replication 群組命名(在 MongoDB 中稱為 ReplSet,一些書籍內翻譯成『複製組』): replSet = mydb 重新啟動 MongoDB: $ sudo service mongodb restart 使用指令 mongo,進入 MongoDB 命令模式: $ mongo 於 MongoDB 命令模式中執行: # 初使化 replSet rs.initiate(null) # 加入自己的 IP 位置 rs.add("192.168.11.1:27017") 若是回應成功,請先稍待數秒鐘,等伺服器偵測和初使化。然後會發現 MongoDB 的命令提示字元從『SECONDARY』變成『PRIMARY』,此時,代表這台機器已經變成 ReplSet(複製組) 中的主要機器。 同樣的,你可以開始為 ReplSet 加入其他次要的資料庫伺服器: rs.add("192.168.11.2:27017") rs.add("192.168.11.3:27017") rs.add("192.

夢想偉大,但步伐短小的 DBHouse

數個月前開始做一個計劃『AppHouse』,實作如 Google App Engine(GAE) 般的 PaaS,其志在打造自己的 Node.js 雲端軟體平台。然後發現,除了讓雲端服務可以在平台上跑起來外,資料庫管理也必需有個便於使用的機制和規劃,仔細想想,一個沒有資料庫配合的雲端服務,可沒有什麼太大的價值,於是,『DBHouse』便應運而生。 你可以在 github 上找到這個專案: https://github.com/Mandice/node-dbhouse DBHouse 起初的開發目的,是讓使用 AppHouse 架設以及開發自己雲端服務的人,可以很容易存取資料庫。此外,對我們而言更便於管理資料庫資源,面對許多不同的服務,不需要特別為他們開設資料庫權限,亦或是買許多硬體和主機,建立起許多 VM 並做各種安全性規劃。其實,如果把 DBHouse 的用途,想像成 Google 在做的事,就很容易明白:『在 GAE 上你可以使用統一的 Database APIs,存取 Google 提供的資料庫系統(BigTable)。』,同理,我們也是在做同樣的事。 只不過,學 Google 開發自己的一套資料庫太過於困難,不是一個可以達成的目標,所以我們仍然選用 MongoDB 當做 PaaS 的資料庫底層。僅管資料庫不是自己開發的,我們還是可以提供統一的 API,讓開發者存取。統一的 API 有個好處,若能做到當開發者在使用的時候,不需要知道自己在使用什麼資料庫,日後就可以在這 API 之後串接或替換不同的資料庫系統,有很大的彈性可以擴充。 當然,更遠大的目標是希望在一個 Table(Collection) 內,因應不同的欄位需求,而交由不同資料庫處理,更進一步發揮不同資料庫的特色。但是,這夢想遠大,技術上也有很多盲點待討論,所以能不能實現那是另外一回事,至少,短期內在我們的能力範圍和經濟狀況下,暫時無法達成這一步。 雖然 DBHouse 有這樣的初衷和夢一般的計劃,但不代表 DBHouse 一定得和 AppHouse 配合使用,更準確的說,他們本來就是獨立各自發展的專案,各自可獨立運作。說穿了,DBHouse 本身就只是一個 Database API,你可以在 Node.js 裡使用 DBHouse API 去操作自己的 MongoDB(目前只有支

【COSCUP 2012】閉幕!簡報釋出!

國內一年一度最大的開放原始碼(Open Source)活動,再次順利落幕。很多人都意猶未盡,所以每當活動結束,便會開始思考明年要分享什麼、反省今年哪裡做的不夠,有人會在活動過後的連續幾天,電腦上開著簡報編輯器,盯著空白的內容,靜靜的發著呆。可惜的是,最後總是因為沒有任何想法而放棄。一直到了明年 COSCUP 的徵稿消息發出,一堆人又開始拾起空白了近一年的想法,擠出一個題目,逼著自己在一兩個月內完成,上台發表。就如同學校的期中、期末考,沒有死到臨頭,大多數同學都沒有唸書的動力,也不會激發自己 120% 的腦力和體力。所以,Event-Driven 的開發模式,一直是在很多開發者促使自己進步的方式。 別以為兩個月時間很充足,大家都有外務、有工作、要過生活,所剩的時間實在有限,所以每當到了 COSCUP 的前夕,總是會聽到很多講者在拼命趕工的聲音。其實,這樣都還算是常態,頂多拼命一點,少睡一點,都還可以頂得過去。可是,今年一次給『兩個 Talk』,就真的讓人會虛脫到不行,還好,熱情能戰勝一切。:-) 由於今年活動承辦的分工方式比較特殊,所以被選上了兩個稿,分別是: JavaScript 全面逆襲!使用 Node.js 打造桌面環境! 用最潮的 JavaScript 盡情開發 KDE/Qt 程式 前者是總結這一年來,我們團隊所開發出來的各種 Node.js APIs,並整合成為一個如同 GNOME/KDE 的桌面環境(Desktop Environment),並展示使用 JavaScript 開發出來的 Juice Desktop Environment(果汁桌面環境)。後者則是為符合 KDE 的議程方向,探討使用 Node.js 開發 Qt 程式的可能。 後記 退學不是件好的事情,請勿模仿。:-S

一起來用 Courser 吧!管理 Route 的利器!

跳脫出前端應用之後的 JavaScript 語言,所遭遇的挑戰極大,至今還沒有一個非常好的開發模型和原則,讓人不免抱怨。因為沒有前人可學習,也沒有太多文獻可以參考,所以,為了讓自己能夠更快完全領會 JavaScript 在各種極端環境之下的開發情況,在這一年來,花了相當多的時間投入去做各種不同類型的 Project,從 Web service、Embedded System、System Programming 到各式雲端技術開發,嘗試從中累積更多用 JavaScript 打天下的經驗。唉,慣 C 都不慣 C 了。 不過,做了許多東西後,就會開始有機會重覆開發相同的功能,這時就會希望能重覆利用舊的程式碼,讓同一段程式,不用每次都重寫一次而浪費時間。於是,開始慢慢把之前做過的專案整理,然後整併許多功能,獨立出來變成一個個 Node.js 模組。 Courser 就是這樣被獨立出來的專案,而功能是為 Express Web Framework 提供一個管理 HTTP Routing 的方案。你可以從 github 上找到專案首頁: https://github.com/cfsghost/courser Express 範例的傳統做法,是每次增加一個 API 或頁面,就要更動一次主程式檔案(app.js),以管理 HTTP Routing,相當麻煩,尤其當有許多人協同開發時,更多不必要的程式碼衝突便出現了。此外,管理專案中的 Handler 也是件麻煩事,因為我們總不可能將所有的 Handler 寫在同一支檔案裡,必須適當分類分檔,才能便於維護。隨著專案規模越來越大,需求越來越複雜,這便是件苦差事。 這些問題當然有解決方案,Express Source Code 裡的範例,就提供了幾種不同的方法,供開發者參考,只不過,這些方法大部份很簡陋、不通用,多半還是要靠專案開發者自行想辦法,開發一套機制,才能解決需求。因此,之前為了專案的需要,就實作了 Courser 去管理專案下的 HTTP Routing 和所有的 Handler,嘗試讓 routes 不要每次開發出來,都是這麼醜。 Courser 目前已經釋出 v0.0.2,你可以從 NPM 上直接安裝它: npm install courser 假設你已經會使用 Express Web Fram

GNOME.Asia Summit 2012 香港遊之簡報釋出

最近因為忙錄,遲遲未寫下今年六月初飛去香港(Hong Kong)參加 GNOME.Asia 2012 的心得,以及將當時在活動中的簡報檔釋出。:-) 對一個台灣來的人而言,香港不會讓人感到陌生,若不說新發展的地方,走在街頭,讓人有走在台北西門町的感覺,或是像台灣一些繁華的老市區以及夜市,站在路中央看過去,當下可以感受到早期台灣和香港之間的微妙關係,其共同點難以言喻。事實上,除了廣東話,還有那些銅板和五花八門的紙鈔外,沒有什麼會讓台灣人不習慣的地方。 話說回來,今年的 GNOME.Asia 2012 是在香港城市大學舉行,據當地朋友所說,這是一個與大型商場(百貨公司)纏綿的學校,由於學校、商場和交通樞紐的動線很密切,走在裡面,你會感覺到商場就像學校的一部份,走沒有幾步路,就會走入了商人的魔掌,錯進了名牌服飾的專櫃。 不過,身為一個宅宅開發者,當然不會被這些名牌服飾所迷惑,它們是嚇不倒我的!活動,當然才更重要! 我能了解,很多人在今天看到 GNOME 幾個大字就興趣缺缺,GNOME 讓大家又愛又恨,許多人不喜歡 GNOME 3 將桌面大改,像是 Linux 之父 Linus Torvalds 前些日子跳出來劈天蓋地的砲轟;也有很多人(像是我)對於許多元件被改壞或是效能不彰而感到很不悅。但由於歷史因素,太多人無法逃脫出 GNOME 所設計出來的大框架,就算你不想用 GNOME 的桌面環境,在 Linux 等 Unix-like 系統中,你還是免不了要去使用基於 GTK+/GLib 所設計的軟體,可以說 GNOME 無處不在,已經不是單單『桌面環境』一詞可以概括。 喜不喜歡新一代的 GNOME 桌面環境是其次,對於我而言, GNOME 是一座作業系統『操作機制』的兵工廠,他生產了太多元件讓我們可以自由使用,然後提供方法讓使用者和開發者可以用『人的角度』去控制作業系統。所以,如果你真的不滿意新的 GNOME 圖形介面設計,自己將 UI 打掉重練也不會是件難事。 這次去香港參加活動,見到了不同地方的開發者和使用者,尤以『中文輸入法(包括輸入框架)』這個議題特別引起討論。這些同是非英語系的 CJK 開發者和使用者們,有頗多的交流。雖然有些議程全程是以廣東話進行討論,我完全聽不懂,但好在有些坐旁邊的香港朋友自動自發充當即時翻譯,還順便介紹了許多當地輸入法開發

Node.js v0.8 大變革?!Native Module 開發者的福音!

最近 Node.js 推出了 v0.8 穩定版,除了改善 I/O 的效能和一些 API 外,最大的變動就是跨平台開發環境的改進。包括了決定徹底使用 GYP 取代 node-waf(wscript)、宣布 libev 將死。或許,這些變動這對大部份的 Node.js 使用者來說不是什麼問題,但對於我們這些寫 Native API 和底層的開發者來說,關係到自己程式能不能跑在未來 Node.js 的新版本上,而且產生了很多移植性的工作。但是整體來說,好處其實大於壞處,因為以後我們的程式更容易跨平台了。 轉用 GYP GYP 是 Google 發展出來的 Build script tools,就像是傳統 Autotools、Makefile 或 CMake 這類的工具。GYP 最早被應用在廣為人知的 Google Chrome/Chromium Project ,是個跨平台的解決方案,這也是為什麼 Node.js 決定要採用的主要原因。 在以前,不同的平台上,你需要為 C/C++ Addon 製作不同的 Build script,沒有統一的方法和途徑去設置和編譯程式,這讓跨平台的工作非常麻煩。使用 GYP 後,可以大幅減少這樣的問題。 棄 libev ,轉用 libuv 首先,有一點要注意,Node.js 開發者打算在下一個穩定版(應該是 v1.0)拿掉 libev 的支援,所以請所有的開發者盡快轉用 libuv。 libev 是 Node.js 在非 Windows 平台上所使用的 Event loop 解決方案,讓 C/C++ 開發者可以開發 Event-driven 的程式,除了可以用來監聽 FileSystem 等用途,也更容易整合 Thread 進 Event-driven 的設計模式中,要是你有印象,GLib 其實也是類似的解決方案之一,只不過 libev 更為輕量。不過, libev 主要還是被應用在 Unix-like 的系統上,若 Node.js 要支援多個平台,在其他系統上,就必需尋求別的解決方案,如 Windows 的 IOCP。 而過去這樣的情況,對我們 Node.js Native Module 開發者來說,是個莫大的挑戰,你必需在不同系統上,採用不同的寫法,導致開發上很困難。所以 Node.js 自行開發了 libu

現實中,我的創業,問題,解答,手札。

最近看到一些網友轉貼的文章,還有聽聞了一些朋友的創業故事,加上自己也是在創業,因此有感而發。其實,過去就一直想寫下『在我眼中的創業』,一方面重新整理自己在創業生涯中的思緒,另一方面鼓勵自己不能倒下。此外,如果可以,讓更多人知道創業的現實面,也不是什麼壞事。這邊要先感謝許多同是創業人的朋友,無論他們現在是否還在這條路上,都給予我很多幫助和啟發,更感激許多親身跳下去『證明』的人,讓我知曉許多悲慘的事實。 依然強調,我尚未成功,也還年輕,我說的話可能影響不了什麼人,也沒什麼說服力,只是單純地將我所見的一切,如實的描述出來。如果你對我所說的一切不以為然,如果你仍然覺得你自己原本想法是對的,請堅持自己所想,無論最後是成功還是失敗,開心或痛苦的,你都能因此得到實質的經驗和正面的回報。 因為我還沒成功,所以我不會告訴你怎麼成功,更不會告訴你創業一定要做到的成功守則有哪些,這些事我都沒有答案。如果你有這樣的困擾,你應該去問的是那些研究創業的部落客專家,或是書報周刊。在這我只會告訴你,我在創業中遭遇到或看到的問題。 首先,恭喜自己。經歷過兩年的努力,好不容易還活著,這是我是創業至今最值得開心的事。相信我,這是真的,在經歷過痛苦磨難、倒閉危機和理想於現實搏鬥後,你會非常慶幸,自己還撐的下去。這一切不像是某些知名的『談創業』部落格文章中,所輕描淡寫的這麼簡單,也不像書店架上滿滿的『各類成功學』所提到的這麼有跡可循,因為你永遠可能被任何一個創業的細節所打倒,一切是這麼出乎意料,現實中的『啊!你已經死了!』天天都可能上演。所以,如果你克服了這些細節,不管落地動作好看與否,你都應該先為自己鼓掌。 問一下自己,什麼才叫做『成功』? 既然提創業,就得提大家都想要成功這件事。包括我自己,很多人不曉得 創業最中最大的問題,就是『不知道什麼才是成功』 。對許多創業人來說,看到 Facebook 有今天的地位會感覺到相當興奮,為自己『創業的理想』注入了一劑莫大的強心針。是的,因為你認為他是成功的,所以你感覺到了『我也有機會成功!』,夢想實現也近在眼前。 但是,我們應該先問一下自己,什麼才叫做『成功』? 是上市上櫃?手上握有幾百億美元資產?還是不缺錢用?握有極大的權力?又或者是走到世界各地,都能有人認出你來?如果你回答不出來這個問題,那請試著去想個更簡單的問題,你認為 F

實作 X11 底下的 Popup Menu

既然要投入 JavaScript 的發展,一個很重要的目標就是讓 JavaScript 能被用來開發 Native 桌面程式。而為了達成這樣的願景,我們的團隊沒日沒夜的發展各類基礎技術和擴充底階 API,甚至是將以 JavaScript 開發整個桌面環境(Desktop Environment, 如:GNOME、KDE、LXDE 或 XFCE 這類專案)為終極目標。 當然,跳出瀏覽器之後的 JavaScript,缺少了繪圖引擎,所以要拿來做圖型化使用者介面,會更為困難。慶幸的是,前些日子發展出的 jsdx-toolkit 已經解決了大多數的問題,除了有 3D、動畫等支援,也已經有了許多現代桌面有的UI元件(如:Entry、Label、Button... 等),以致我們完全可以放心的開發屬於自己的圖型化應用程式。 不過,目前的情況,在手機、平板或是特定用途的嵌入式系統中完全夠用,一旦回到更為複雜的桌面環境下,就會遭遇到許多的問題。像是回到 XWindow 底下後,會遇到許多 X11 的視窗管理機制,其視窗之間錯縱複雜的交互關係,就是我們要處理的。尤其是當我們在開發桌面環境時,就會發現在一般的桌面環境下,使用者可能會同時開無數個視窗和程式,並且隨機又大量的切換使用,這迫使我們必須去修改 jsdx-toolkit 以處理 X11 底下的更多狀況,符合並更完整支援一般桌面環境下的操作習慣。 你可能用過 GTK+/Qt 這類常見的 Toolkit,也知道在 X11 之下有很多種類型的視窗(Window),像是 Dialog、Splash、Menu、Popup Menu 等等,但你可能不知道這些現代 Toolkit 內部做了多少事。事實上,X11 本身雖定義了各類視窗的類型,但實際上 XWindow 和 Window Manager 並不會完全去照定義去處理你的視窗行為,更準確的說法是,X11 HWMH 中的基本定義和我們實際的認知是有出入的,該定義只是說希望達成的行為,但沒說是由誰(XWindow、Window Manage 還是 GUI Toolkit)去處理。 舉例來說,我們現在寫一支程式,該程式不使用任何現代的 GUI Toolkit,然後單純使用 X11 API 把一個 Window 的類型設成 Popup Menu。但是你會發現,它的實際行為並不像我

【心得分享】軟體人甘苦談

很抱歉,因為台北大雨來襲,導致班機延誤,讓小弟無法及時從香港趕回台灣參加 FreedomHEC 2012。相當對不起主辦單位,就這樣讓當天議程開了天窗。但是,之後我有空時,仍會整理資料,依舊會公開原先預定要給予的簡報。 不幸的是,活動第二天被客戶抓住,所以也沒辦法到場聽講。不過,雖然沒參加到 FreedomHEC 2012,為了賠罪,第三天當了司機(Be a driver, not writing driver :-S),開著車載著外國講者們一路到了宜蘭大學,給予學生機會直接面對面與 Kernel 開發者交流。 除了面對面問答解惑,其中當然也有保留一點時間,讓講者們可以自我介紹,也分享一些經驗。我也給予了一份簡短的心得分享,由於對象是學生,時間也有限,所以就不直接討論艱澀的技術,而是以輕鬆的角度切入,分享一下創業的經驗和業界的感想,還有描述就算在面對不利軟體業的環境之下,身為一個軟體人所需要的熱情和自我要求。 衷心期盼我們能培養軟體開發的熱忱,然後才有機會做出軟體的價值。:-)

如何當一個優秀的救火員之打蛇打七寸

經歷過許多救火任務(這邊當然是指軟體系統專案的問題),從 Kernel、Driver、Porting 到各類系統應用程式、Web 應用程式,幾乎無所不救,有社群內的朋友嘲笑著說:『在國內大概沒有團隊,像我們一樣什麼火都救。』。有許多的感觸是肯定的,從問題發生的那一面看去,加以急迫時間的摧化之下,感受到許多程式開發者最真實的思維和邏輯,當然,還有發案老闆的著急,以及清楚看到許多關係人暗地裡的算盤。我不敢說自己是優秀的救火員,但至少一旦承諾並接下案子,有再大的困難和阻礙也總是使命必達,哪怕連續數個月每天平均只睡兩小時,三四天只睡一次,也不會倒下。我想,最少我可以談談如何救火,還有從火堆中看到的許多『人』的問題。 其實,救火沒什麼訣竅,撲滅它是其次,主要是確保不會再燃起。俗話說『打蛇打七寸』,解問題時也要解到夠力才行。但是,或許你常聽有人說:『產品要出貨,能動最優先,好不好其次。』,似乎恰恰與我所提到的相反。沒錯,因為要確保火不會再燃起,理論上是要找出問題根源,從根源著手和解決,很多人乍聽之下,都會覺得是費工又花時間的工作。但是,每次的經驗都告訴我,實際上,找出問題根源,並解決他,往往比修補來得快很多,而且一勞永逸。尤其是碰到死線(deadline)將至,卻一直解不掉的一大坨 Bugs(指同類相關或互相影響的問題),從根本上並深入解決問題才是最快的辦法。 這邊有個簡單的案例: 有一個應用程式,與 Library、System API 和 Driver 都有相關,他們相依關係是: 應用程式 -> Library -> System API -> Driver 假設現在有個問題,這支應用程式出現了一個 Bug,而這個問題最終被發現是 Driver 缺少一些功能,而造成功能不正常。那我們應該從哪裡去解決? 一般人的做法,若是為了因應『產品要出貨,能動最優先』,所採取的方法當然是拿掉應用程式上的某些受影響的功能,或是改寫應用程式以另循途徑的方法達成同功能。但是,若你選擇這樣的做法,最可怕問題是,如果應用程式太過複雜,修改起來會有更多的副作用(Side effect),你要花更多時間去處理更多原先不存在的問題。 況且,這都還沒講到,我們根本都還不知道 Driver 造成的影響範圍有多大,有哪些 System API 、Library API 和

簡單理解 JavaScript 的記憶體管理機制

不像其他的語言,JavaScript 開發者永遠沒有辦法自己去釋放記憶體,頂多只能移除物件的 Reference (代表這物件已經沒有人在使用),而且這物件所佔的記憶體並不會馬上被釋放,而是 Garbage Collection 在滿足某些條件的情況下,才在背景自動去尋找沒有被使用的物件,然後釋放。若你嘗試過尋找釋放記憶體或移除物件 Reference 的方法,得到的解答,應該不外乎是使用 delete 關鍵字或是將變數設為 null,但是你真的了解它的意義嗎?事實上,有很多人都是在不瞭解的情況下使用它們,還可能因此產生 Memory leaks 的狀況。欲弄清楚這一切,我們必須先簡單理解一下 JavaScript 的記憶體管理機制,更準確的說,是物件的管理機制。 從 JavaScript 開發者角度來看,JavaScript Engine 在運作時,記憶體使用是呈現樹狀結構,也就是所有命名或建立的變數或物件,都是存放在一個全域(global)的 Object 中。在 Node.js 中,你可以直接讀取 global 變數看到目前 Context 的環境狀態: console.log(global); 我們可以做個實驗理解一下: var myVar = 'Hello'; function myFunc() { return 123; } var myObj = { a: 1, b: 2 }; console.log(global); 執行以上程式,你應該可以從 global 中找到我們自己定義的變數和函式: { ...(已省略基本預設的環境變數)... myVar: 'Hello', myFunc: [function], myObj: { a: 1, b: 2 }, ... } 從結果可以發現,所有的物件都以樹狀的形式被 global Object 保存著,無論是變數還是任何一種類型的物件,都是一組組 Key/Value 的存在。而 Value 就是各種不同形態的物件,如字串、函數、陣列、數值等。 所以,移除某物件的 Reference,就意味著將把物件從這棵樹上拔除掉。因此,我們可以直接將該變數設為 nul

【JSDC.tw 2012 簡報檔釋出】Non-MVC Web Framework

由於一些因素,被徵招去救火,在 JSDC.tw 2012 (JavaScript Developer Conference 2012) 給與了一場 Talk,由於準備時間相當緊迫,就把最近在研究和試驗的半成品匆匆拿上場展示和說明,題目是『Non-MVC Web Framework』。你可能在議程上沒有看到這場 Talk,實際上是因為主辦單位的一些小疏忽,議程上仍是寫著之前的舊題目『Build Node.js Module』,而且小弟的名字也打錯了,從 Fred 變成了 Frend,差一點就變成二十世紀少年的友民黨教主。:-) 本次議程其實和前幾天發的舊文『 前端工程師也可以淡定的開發網站應用!RedTea Web Framework! 』息息相關,探討的是改善 MVC 的開發流程,和引入 JavaScript/Node.js 後的大膽嘗試,而且進一步討論實作細節。此外,因為 RedTea 本身只是一個實驗性的專案,目的只在於驗證可行性,還不到實際使用程度,所以藉著這次機會,公開並宣布新專案『 Kamalan Web Framework(葛瑪蘭) 』,Kamalan 引入了 Express Web Framework 為基礎,然後將結合 RedTea 的成果,並更進一步簡化其中細節和使用方法,讓前端工程師能真正無痛上手。 雖然還沒完全將 RedTea 的機制完全整合進 Kamalan,但目前 Kamalan 最少可以和 Express 一樣使用,你如果有用 Express 寫的程式,直接將 require() 引入的模組名改成 Kamalan 即可。由於 Kamalan 在根本上就是 Express,甚至是可以使用 Express 的所有 Middleware。 後記 這場 Talk 後,引起了一些 JavaScript Developer 趕的迴響,一些建議和聽眾的期待相當令人開心,討論過程也非常愉快。感謝大家的參與。:-)

【GNOME.Asia 2012】Enjoy Writing a Modern Desktop Application in JavaScript

圖片
依稀記得,當年去越南(Vietnam)參加 GNOME.Asia Summit 2009 的情景,當時甚至寫了一篇[ 遊記心得 ]。因為那是首次以講者身份參加國外的 Open Source 研討會活動,意義非凡。更重要的是,那也是當時和 Penk 組成的 ULLab(/usr/local/lab) 第一次出征,如今這樣的組合雖不復存在,但仍在心中藏有很多回憶。 今年度的『 GNOME.Asia Summit 2012 』將在 6/9 - 6/10 於香港舉行,很感謝 GNOME Foundation 再次贊助,讓小弟幸運的又能以講者身份飛去參加這次活動,而這次要給予的主題是『Enjoy Writing a Modern Desktop Application in JavaScript』。 今日科技變革相當快速,但桌面應用的開發一直跟不上節奏,原因是『開發效率差』和『入門門檻高』一直都是 C/C++ 這類中低階的語言的痛處,不足因應這個時代對應用的大量需求。因此使用有高生產力的腳本(Script)語言來開發桌面應用程式,便是目前可行的解決之道。 JavaScript 自 World Wide Web 澎渤發展以來,一直處於相當重要的地位,用於處理 User Interface 的工作,已經有快要二十年的時間,可說是非常成熟。事實上,GLib/GTK+/Clutter 等底層的事件模型,就與 JavaScript Engine 本身的機制大同小異,在同樣解決使用者介面的工作上,可說是殊途同歸。因此,有這樣豐富的前線作戰經驗當後盾,我們可以確信,JavaScript 非常適合被用於開發桌面應用程式。若是與 GTK+/Clutter 這類底層 Toolkit 相結合,跳脫出瀏覽器,寫原生的桌面應用程式也未嘗不可。 這次的議程,小弟將提及: 回顧 JavaScript 歷史和發展 探討如何使用 JavaScript 開發原生的桌面應用程式(搭配 GTK+/Clutter/Mx) 既然這次活動的主角是 GNOME,主要將以探討原生的桌面程式為主,當然也會因應未來發展,提及 Web Application 的部份。 期待與香港和世界各地前來的朋友相見。:-)

前端工程師也可以淡定的開發網站應用!RedTea Web Framework!

還記得,尚未投入 Node.js 前,一直覺得 Node.js 帶來了未來,讓我們可以用 JavaScript 同時開發 Web 前端(Front-end)和後端(Back-end),等到真的投入 Node.js 後,發現雖然事實的確是如此,但由於前端和後端應用所需要的背景知識不盡相同,開發模式和概念更是大異其趣,所以,雖然同樣是使用大家熟悉的 JavaScript 語言,但前端開發者仍然不見得能夠如願地來開發後端應用。 這樣的情況讓我想起有位來台灣工作的外國朋友,曾告訴過我一個多年前發生在他身上的笑話。故事是: 他原本是個美術方面的設計師,然後,但有一天老闆對他說:『你從現在起,去做開發程式的工作吧。』 他問:『為什麼?』 老闆回答:『寫程式是用英文寫,而你又會英文,不就可以寫嗎?』 是的,同樣道理,雖然對前端工程師而言,JavaScript 是最熟悉的程式語言,而 Node.js 又可以讓你使用 JavaScript 寫整個 Web 應用,但這不代表對這些人而言,就可以輕易上手 Web service 的後端開發。要真正讓前後端開發合而為一,不只是語言要統一,開發經驗也要相同才是,這才是所有 Web 開發者最期盼的事。 於是筆者基於 Node.js,開發了『 紅茶(RedTea) 』,這是一個和現有的網站框架(Web Framework)所不一樣的全新的嘗試。以前端開發者視角和經驗為出發點,專門設計給前端工程師上手使用的網站框架,讓前端工程師也可以『淡定』的開發網站應用。由於 RedTea 不是傳統 MVC 模型的 Framework(至於 RedTea 採用的是哪種開發模型,筆者一時也說不上來。),所以,如果你是一個已經被 MVC 涂毒已深的開發者,可能要先花點時間重新理解一下。:-) 此外,RedTea 有一個最大的特點,就是支援了在瀏覽器環境下,呼叫後端 JavaScript Class/Function 的功能,就像在使用本地端的 JavaScript 物件般。因此,前後台交換資料,不用再以 GET/POST、URL Path Routing 或 Ajax 相關的方法實作,只要學會怎麼使用 JavaScript Class 即可。重點是,即使你沒有任何 HTTP 通訊協定的知識,或後前後端資料處理的經驗,依然可以開發出網站程式。

想寫好 JavaScript,遞迴技能要練好

V8 JavaScript Engine 的運作,主要是以事件驅動(Event-driven)來執行所有的程式碼,如果你有開發過 GTK+ 程式的經驗,使用上應該不陌生。不過這對一般人其實相當不好理解,因為事件驅動會讓你的程式看起來像是多工在運作(如使用執行緒),所以有些人對於 JavaScript 的理解是,有些東西可以丟背景執行。 要了解事件驅動,可以先從 JavaScript 的行為說起。如果你正在使用 Node.js,你就會發現 Node.js 通常對同樣功能提供了兩個 API,分為『同步(Synchronize)』和『非同步(Asynchronize)』兩種類型。例如下面這刪除特定檔案的例子: 同步(Synchronize) API: fs.unlinkSync('/home/fred/badfile'); ... 非同步(Asynchronize) API: fs.unlink('/home/fred/badfile', function(err) { if (err) { console.log('Failed to delete file.'); return; } console.log('Successfully delete a file.'); }); ... 簡單觀察同步與非同步的執行結果,可以知道前者(同步)會停住並阻塞在此 API,等檔案刪除成功後才繼續下一行程式;而後者(非同步)有如將刪除檔案的工作丟到背景執行,並繼續往下一行程式執行,完全不會像同步 API 一樣停住。等刪除檔案的工作完成後,便觸發事件去呼叫 Callback function。而這樣非同步的機制就全靠事件驅動(Event-driven)來達成,雖看起來像是把程式丟到背景跑,實際上是在 JavaScript Engine 上註冊了一個事件,等到工作完成以後,事件被觸發時才接續執行 callback function。 非同步的做法通常會用在需要花大量時間的 API 上,如檔案系統、資料庫系統的操作等,以避免因為單一 API 造成整個程式鎖死或卡住不會動的問題,尤以前端和需要即時反應的工作上,特別需要。 至於這樣的事件驅動是怎

【OSDC.tw 2012 Hackathon 成果分享】用 JavaScript 打電話囉!

圖片
以為 OSDC.tw 2012 在 4/15 號時就結束了嗎?其實並沒有。在活動的一個星期後,於 4/21 星期六,OSDC.tw 接著舉行了 Hackathon 的活動。很多人可能不知道 Hackathon 是什麼,有人叫他『駭客鬆』、『駭客松』或是『駭客爽』,其實總歸來說,就是讓開發人員盡情開發程式的活動。 這類活動的規則是,參加的開發者可以自由組隊,提交想法,然後當場實作。最後,在活動結束前,讓各隊伍一一上台展示成果。由於開發者的創意常常天馬行空,又能看到實際成果,所以這類活動都相當有意思。這次,OSDC.tw 提供了無限量供應的食物還有場地,活動時間是從當天早上 9:00 到下午 6:00,成果發表是從下午 4:30 開始,每個隊伍約有七個半小時實作自己的提案。 這次 Hackathon 活動,我與『魏藥』組隊,選的主題是『使用 JavaScript 打電話』,意即使用 JavaScript 開發出一支 Linux 應用程式,可以像手機一樣撥出電話並與對方通話。選這主題是因為我們的機器上剛好有 3G 數據卡(Modem),所以這個提案的目的,主要是撰寫一個 Node.js 模組『jsdx-ofono』,去提供控制 Modem 的 JavaScript API,讓開發者可以透過這組 APIs 撥打甚至是傳接 SMS/MMS 之類的訊息。最後,為了驗證並展示,運用了之前開發的『jsdx-toolkit』,用 JavaScript 撰寫了一個簡單的撥號介面『jsdx-app-voicecall』。 註:因為時間太趕,後來才發現,撥號 UI 忘了放倒退按鈕,所以撥錯號時要把程式重啟。:-P 如專案名,其主要整合了 oFone ,應用了之前開發的 node-dbus,所以省下了不少時間,最後再以 jsdx-toolkit 快速實作了一個 UI。原本希望,如果時間再充足一些,我們計劃幫 jsdx-ofono 加上 SMS/MMS 和讀寫 SIM 卡電話簿的功能,可惜最後沒來得及。 註:因為時間也不足,我們還來不及將 Linux 上的麥克風接上 oFone,所以目前接通後,只能聽到對方手機傳來的聲音。 此外,這次展示的兩個元件『jsdx-ofono』和『jsdx-app-voicecall』都有在 github 釋出,歡迎取用: https

我所慣用的討論問題之方法

在處理技術問題時,我喜歡和他人討論,因為這是有助於大家提升技術的機會,也是種讓自己覺得不孤獨的方式,互相放下身段然後交換意見,每次都能不亦樂乎。這無關乎誰技術高低,只要大家能夠共同解決問題,除了是種樂趣也是種團隊集思廣益的機會。 由於有些人可以接受反證的方式,而有一些人比較能接受列舉推導的證明方式。所以,難免會碰到種情況,就是有人會大玩文字遊戲,讓你分不清他到底是真心想要找出問題,還是為辯而辯。其實,他們常常只是因為無法接受其他人的證明手段而已,所以互挑對方的骨頭。造成公說公有理,婆說婆有理,沒有交集點的局面。 一旦碰到這種情況,為避免文字遊戲混淆主題,我總是會請在乎『文詞精確』的人,先自己定義一些文字和用詞,然後再行討論。或是請有一些想法的人,針對問題先列舉出他們自己認為的所有可能性,然後接著追加自己認為的可能性,最後再行討論。這樣做的目的是,試圖採用他們們各自喜歡的證明方法,正反舉證,然後以交集去找出問題,除了讓兩邊都沒有話說之外,也能更快讓大家有『同樣的語言』可以溝通。此外,有時候為使討論順利進行,我也會一項項以詢問的方式進行,有時問題相當愚蠢,甚至會穿插基本面的問題。 很幸運的,使用這種方法後,在多數情況下,在大家列舉和回答問題之後,通常都能透過排除矛盾的方式,將問題給釐清,找到可能的疑點或是直接得到問題的解答。 不過世界不是這麼美好,既然過程中有愚蠢或基本面的問題,有些自認有本事的人被問到時,難免會覺得你在污辱他或是瞎扯蛋,有些人會回嗆:『自己去看 Spec』 、『連這麼基本的問題都不會,還問、還想討論?』。一旦扯到人的問題,就會讓整個討論進行不下去。 而有些人,在討論不下去後,會搬出多年來死背活背的聖經,在你面前推導了無數公式,繞了一大圈,最後『告訴你無解』或『證明自己沒有錯』。好一點的狀況,他們最後會『猜測問題』所在,回到討論的主題;不好一點的情況,他們就會告訴你『絕對不會有問題,是個無法解釋的靈異事件』,終結討論。 值得注意的是,如果問題的原因是:『執行那本聖經的理論時出現了 Bug』,你會更容易從他們口中得到『無解』和『不可能』的回答,因為這是『完美的聖經理論』內不會記載的東西。 不過,當碰到這種人時就沒辦法了,只能等他們自己想通後給你解答,亦或是另請高明。所以,如果你是他們的主管,又不想得罪他們,你需要給他們更多時間讓

【OSDC.TW 2012】Let's Enjoy Node.js - All Development in JavaScript 簡報檔釋出

感謝各位捧場,上周六在『 OSDC.TW 2012 』所分享的『Let's Enjoy Node.js - All Development in JavaScript』,旨在介紹『 Node.js 』這新興的 Open Source 專案,我們可以預見,其將帶來軟體業相當重大的變革,並為 JavaScript 程式語言開拓了嶄新的局面。目前簡報檔釋出,歡迎各界取用和參閱。 自 2009 年 Node.js 公開發表以來,備受世界各地開發者囑目,在 2011 年 12 月更一度榮登 github 關注排行的第一位,超越了 Ruby on rails。Node.js 的出現意味著 JavaScript 語言從前端應用走進了 Server 的殿堂,除了效能表現不俗之外,使用其開發應用也相當迅速,未來 Web 開發者可以完全使用 JavaScript 語言打造網站服務,甚至是可大規模括展的雲端應用,堪稱 Web 開發者的夢想。 值得一提的是,Node.js 其實不僅限於 Web 應用,甚至可以用於各類系統程式開發,比較廣為人知的例子是 HP WebOS(前身是 Palm WebOS)。其採用了 Node.js ,做為系統服務的開發途徑之一。此外,Node.js 有模組化的設計,讓開發人員可以輕易使用各類其他語言(C/C++/Python... etc)為其擴充功能,彈性相當高,更讓 Node.js 不受限於任何開發領域。

【Node.js Taiwan 心得分享】How to Write Node.js Module 簡報檔釋出

於本週四所分享的『 Node.js Taiwan 社群聚會 - How to Write Node.js Module 心得分享 』,簡報檔經整理後釋出,對 Node.js Module 開發有興趣的人可以自行參閱。若有不瞭解之處,可與小弟聯絡和討論。如有發現問題,請不吝賜教。 本次分享主要有三大部份: 使用 JavaScript 開發 Node.js Module 學習使用 NPM 註冊帳號和上傳模組(Module)  進階議題:開發 Node.js 的 C/C++ Addon 簡報展示: 後記 由於小弟於 people.linux.org.tw 上的 SSH Key 遺失了,短期內沒空處理,所以無法像過去一樣直接上傳 PDF 供大家取用。因此,日後會使用 slideshare 來分享簡報。

各式 JavaScript Class 的效能比較

圖片
我們在做 JavaScript 開發時,常會使用到類別(Class) 的設計方法,但事實上,JavaScript 根本沒有所謂的類別(Class) 概念,此功能完全是靠動態物件(Object) 所模擬出來。因此,在 JavaScript 中,有數種方法可以定義和設計我們自己的類別(Class) 。可是哪一種方法的效能比較好呢?這便是本文的主題。 為免空口白話,筆者在 jsperf.com 建立了一個 Test Case『 Prototype Operator Performance 』以便實驗,並邀請各方網友使用瀏覽器前來測試,比較使用和未使用 Prototype 兩種情況,以及不同寫法的速度。(若你有興趣幫忙做實驗,進入該網站後, 請點選 Run Tests 開始測試) 註:在測試過程中,請確定你的瀏覽器,沒去跑其他的吃重的網頁,以確保實驗結果的準確性。 你可以在該網站上,觀察其他網友們的測試結果。但是,由於本次目的,主要測試的是同一種 JavaScript 引擎,處理不同建構方法的速度,所以,大家只要專注於在同一個瀏覽器下,其測試結果就可以。不同電腦,不同系統和不同瀏覽器的速度,並不是我們這次比較的重點。此外,因為 Node.js 使用的是 V8 JavaScript Engine,在本文中主要會拿 Chrome (因為 Chrome 使用的是 V8 JavaScript Engine)的結果討論。 這個測試有兩組實驗,第一組是測試呼叫類別(Class) 中方法(Method) 的速度,我們分別測試三種,用不同方法建構出來的類別(Class): 未使用原型(Prototype),直接在 Constructor 內定義 方法(Method) A = function() { this.message = function(s) { var msg = s + ''; }; this.addition = function(i, j) { return (i * 2 + j * 2) / 2; }; }; A_instance = new A(); A_instance.message('Hi'); A_instance.addition(i, 2); 使用原型(Prototype

Node.js Taiwan 社群聚會 - How to Write Node.js Module 心得分享

無論你是否已經相當熟悉,還是想要嘗試入門 Node.js,應該都想要尋找興趣同好,找機會共同研究和分享彼此心得。已經辦了多次聚會和心得分享的『 Node.js Taiwan 社群 』,將於 4/12 (星期四)舉辦第五次的 Node.js 聚會,邀請廣大朋友們參加。 小弟有幸受邀,將於這次聚會交流心得分享,主題是『How to Write Node.js Module』。 在不久的文章『 我為什麼大舉投入 JavaScript 的相關開發 』內有提到,今天的 JavaScript 已經不再只是網頁前端的專利,除了能開發網站後端,也可以撰寫系統程式,甚至是嵌入式系統和跨平台的各類應用。而 Node.js 因為實作了許多基本的 JavaScript 函式庫,讓 JavaScript 可勝任許多的應用,所以近年來受到不少關注。此外,Node.js 的模組(Module)機制,更是讓我們能輕易擴充各種不同的功能,以及使用 C/C++ 為 Node.js 實作低階的 API。所以,想要完全不受限制的運用 JavaScript 開發各類應用,學會寫 Node.js Modules 是個必需要經歷的過程。 有鑑於此,本次的分享內容會提及: Node.js Ecosystem Pure JavaScript Module Development NPM(Node.js Package Manager) C/C++ Addon Development 若時間允許,會進一步探討 C/C++ Addon 所衍生的應用範例: System Programming in JavaScript Desktop Programming in JavaScript 詳細 Node.js Taiwan Party 聚會訊息如下: 官方公告: http://nodejs.tw/post/20631976641/nodeparty20120412 時間:2012/04/12 (星期四) 19:30 – 22:00 地點:台北市大安區金華街 122 號正對面 d.cafe 地下室 W-B05 室(創立方) (政治大學城區部,可從旁邊的小門直接進到地下室,找不到的人『 看圖 』) 有興趣的朋友們,歡迎前來參加,不吝指教。:-)

用 Node.js 實作多個 Process 監聽並處理同一個 Port

Node.js 實作了一個內建的模組『cluster』,目的在於提供開發者一個容易的方式,針對多核心機器進行支援。可惜的是,截至今天 Node.js v0.6.14 版本,『cluster』功能還是不夠完整,從官方文件上可以得知,其 API 仍處於實驗(Experimental)階段,在日後會有極大的變動(Drastic changes in future versions)。 而就 git repository 上最新的 Node.js 開發版本來看,『cluster』模組已經大幅度更改,也從簡單的 function call 變成了物件的設計。所以,目前非常不建議在自家產品中大量使用 『cluster』,至少短期內,他都不是穩定可用的,會有很大的改動空間。 不過,你如果是要實作 Web Service,會想要使用『cluster』的目的就顯而易見:『透過多個 Process 分擔流量和工作量』。若只是單單要做到這一點,我們可以自己來實作。 通常我們有兩種方式達成這個需求: 反向代理(Reverse Proxy) 技術 使用多個程序(Process) 監聽並處理同一個 Port 前者的做法,是建立一個常駐程式或機器,統一處理所有連線的需求,然後將這些連線做流量平衡(Load Balance),轉送並分配給後端多個程序或機器處理,待處理完成後,再將後端的回應送回給使用者。這樣的 Proxy 機制,你可以用已經相當成熟的解決方案達成,像是 Nginx 或 Apache。亦或是自己使用 Node.js 撰寫,但由於這不是本文的重點,日後再來討論這個實作的細節。 而後者,使用多個程序(Process) 監聽並處理同一個 Port,是本文的主題,也是『cluster』模組正在做的事。如果你有看過『cluster』的程式碼,就會發現它其實主要運用了兩個技術:『取得 net._handle』和『利用 process.send() 傳送 Handle 給子行程(child process)』。 知道了關鍵後,實作上就不是什麼大問題,主要流程是: 運用『net』建立一個 Server,目的在於監聽(listen) 80 Port 建立多個子行程(child process) 準備處理連線 將『net』的內建 Handle 傳給子行程(ch

發佈 AppHouse-Manager 圖型化管理介面!

圖片
繼前文『 不靠別人!親手佈建自家的雲端服務平台 AppHouse 』所提到,我們以當今主流的雲端平台的佈建習慣為參考,開發了一個自己的 Hosting Platform,做為投入雲端產業的基礎建設。雖然與許多雲端業界的老前輩(如:Google、Amazon 等等)比起來,仍然不夠看,但研發仍逐步朝完整的解決方案前進。 在使用『 AppHouse 』時發現,網站應用程式的佈建雖然相當快速,但若是要直接在 AppHouse 上開發應用程式,會有相當多的麻煩,也不夠便捷。於是,撰寫並釋出了一套圖型化的管理程式『 AppHouse-Manager 』,用來管理 AppHouse 上所有的應用程式(Application)。 目前提供了功能,可以重啟特定的應用程式,讓開發者可以在撰寫和測試服務時,依自己的需要重新啟動自己的程式。 也實作了即時監控 Console ,我們可以透過瀏覽器即時偵錯(Debug)。 目前 AppHouse-Manager 還相當不足,只能說堪用而已,並還有許多欠缺改進的地方。不過,已經足夠讓工程師在 AppHouse 上進行開發工作。

不靠別人!親手佈建自家的雲端服務平台 AppHouse

現在,凡事只要扯上『雲端』兩字,價值就上漲好多倍,所以,任誰都想狹著『軟體奈米』之勢,大做文章。此外,在大多數人的印象中,雲端就是 Google App Engine(GAE) 、 Amazon E2 或 Microsoft Windows Azure 的代名詞,無論是誰,只要是能將服務放在上面,或是將公司搬到了台北 101 的 Google 樓上,就叫做上了雲端。而那些所謂專家說的 IaaS 、 PaaS 、 SaaS 專有名詞,其實都是舊瓶新酒,只是商業界幫雲端和網路生態的各個部份做了劃分,方便於解釋給投資人或政府單位的『難懂標題』而已。 簡單來說,雲端對一般的企業,最重要的是發展自家應用,提供更多的『加值』且『不需大量人力』的服務,然後對客戶進行『綁樁』;對中間維護伺服器的廠商,就是『租出更多的伺服器』,得到更『大規模的需求和機會』,進一步『降低機房建設和維護的成本』;而對電信單位,就是賣出更多『通信產品』和『頻寬線路』,也能換到更多『國家預算』。 雲端對不同的企業有不同的意義,但對終端的一般企業和使用者來說,建立一個不用擔心擴展性和極限的網路服務,是他的真正價值所在。所以講穿了,雲端並不是什麼新東西,多企業會將服務放在雲端上,求的不過就是為了量化的『擴展性(Scalability)』,如果你很熟悉網路產業,就會發現其實這就是以前,當一個網路服務長大到一定規模,才開始要考慮的事。只是現在這個時代,網路服務搭上了終端實體產品的『量產列車』,許多服務的第一時間規模就相當龐大,所以直接跳過網路服務的發展期,馬上得考量第二步的事。這也是為什麼現在雲端熱哄哄的原因。 假設業界使用雲端的真正原因,主要是為了追求擴展性,我們不能親手打造嗎?我們是否可以自己建構一個像 Google App Engine(GAE) 的平台,將自己的 Web App 輕鬆佈建在上面?也保留日後擴展的可能性? 於是『 AppHouse 』應運而生,我們開始投入開發這樣的專案,目前開放原始碼,以 GPL 做為授權而公開。雖然初期是自己使用為主,但這對在國內還未投入實際行動的雲端市場來說,算是一種相當特別的嘗試。如果可以,也希望能找到機會,在國內能建置公開的平台,供業界或軟體開發者使用。 『AppHouse』最終目標是提供一個 Hosting Platform,就如 Google

使用 Node.js 控制網路連線管理員

既然以『國內首屈一指的 JavaScript 專家』為目標,使用 JavaScript 打造作業系統就是我們的終極目標。未來會將先前的 Flat Project(可參考舊文 Flat Project Demo - An OS for Tablets 平板作業系統 和 Flat Project - 從山寨做起,親手打造炫麗的平板系統 )以 JavaScript 重新架構,實作並提供一個更易於開發應用的環境。當然,就像過去所說,無論有多困難,產品化一直是我們的目標。 既然要開發作業系統,就要讓 JavaScript 能直接觸碰到系統層級或硬體裝置的控制,我們必須實作各種 JavaScript API 去達成這個目的,而前些日子所提及的『 node-dbus 』和『 jsdx-toolkit 』就是在做這類的工作。現在,基於 node-dbus,我們進一步和『 connman(Connection Manager) 』連接,實作出『 jsdx-connman 』,提供 JavaScript 網路管理機制的 API。這代表我們可以藉由 jsdx-connman 去控制無線、有線網路,甚至是WiMax、藍芽等各種連線介面。 如果想要嘗試 jsdx-connman,可以直接使用 NPM 安裝: npm install jsdx-connman 這邊有個範例,讓我們可以使用 jsdx-connman API 去得知無線裝置的狀態和掃描當前環境的 Wifi 無線基地台: var ConnMan = require('jsdx-connman'); var connman = new ConnMan(); connman.init(function() { if (connman.Wifi.Powered) console.log('Wifi is powered'); else console.log('Wifi is not powered'); if (connman.Wifi.Connected) console.log('Wifi is connected'); else console.log('Wifi is not connected');

這是兩碼子事!『犛清問題』與『不是我的問題』!

前一陣子有人寫了文章,以硬體工程師的角度,跳出來罵軟體工程師,因而吵得沸沸揚揚,在各社群網站上也被人重覆轉貼了好一段時間,掀起不少戰文。雖然整篇文章看下來情緒化字眼相當多,在某些部份也有些偏頗甚至太超過。但是不可否認,他的確有提到一個長久以來,許多工程師的通病,無論是軟體工程師還是硬體工程師。 身為工程師或與工程師一同工作的人,應該常聽到或自己本身常說這句話:『不是我的問題。』,就是這經典名句,總是搞得老闆慌、主管氣、工程師們更怒。而對這句話,我特別有感觸,因為過去我身為一個科技業救火員,常跳入火坑滅火,發現很多時候,就是這句話讓什麼問題都解決不了,導致起了大火,又沒人要解決,最後還需要我這外人進去犛清問題。 而在這些救火經歷中,我深刻體會到,證明『不是我的問題』是非常困難的。 一方面,有原罪加身,別人會把你當做在推卸責任。另一方面,因為非常難用『列舉法』去證明自己沒錯,又加上當局者迷,所以,才會有這類『列舉不全』的自我辯解:『我的程式在我的機器上測一點都正常,所以沒問題』、『我測量的電壓和波形都很正常,所以不是我硬體的問題』。其癥結在於,你有在其他電腦環境上測過嗎?你有測過所有工作狀況之下的電壓和波形嗎?大家似乎都忘了高中數學就學過,要找出『向量』以指出方向,要有兩個或更多個點嗎?就算你要用列舉法證明問題不在於你,你也要取樣更多更完整的證據。 所以,很多工程師想盡辦法證明自己沒錯,以為自己是在犛清問題,根本不然。因為『犛清問題』與『不是我的問題』是兩碼子事啊! 我認為,如果你要犛清問題,又證明自己沒錯,『證明是別人的錯』才是最好的方法,並且有助於專案前進和實質意義。 這邊有個自己團隊最近遭遇的小故事與大家分享: 我們與硬體廠 X 合作開發一個產品,其中發生了一個問題,播放影片時常會鈍鈍卡卡的,此外,因為該產品有觸控面板,如果影片播放中,用手去碰觸觸控面板,影片會立即變很鈍。 由於是 ARM 平台,播放影片都藉助晶片解碼(Decode),所以起初是找晶片供應商 Y 來查明真相,但是,晶片商『並不認為是自己的問題』,他們認定自己已經出了不少貨,平台夠穩定,所以應該也不可能會有問題。此外,因為觸控面板也會影響影片播放,所以供應商 Y 認定,問題肯定出在 X 廠商因自己動了手腳,加了其他模組或軟體所導致。所以,廠商 X 只好摸摸鼻子,請自己的

能處理 Binary Data 的 Node.js Buffer Class

從一開始 JavaScript 就被設計成易於處理 Unicode 的語言,其所有的動作,都無法直接操作 Binary 類型的資料。也就是說,JavaScript 對處裡一個個位元組(byte)的資料是沒輒的,因此使用範圍大幅受限。為了解決這個問題,Node.js另外設計了一個 Buffer class,讓開發者可以處理 Binary data。 為了方便理解,其實我們可以將 buffer class 看做為 C 語言中的 malloc(),使用它就像是和直接系統要一塊原始記憶體來使用。此外,因為 buffer class 被設計成在 V8 heap 之外配置記憶體,因此不受限於 V8 Engine heap 的 1.6GB 大小限制。 你可以用下列三種方式建立 Buffer 物件: /* 建立 16 Bytes 的記憶體空間 */ var buffer = new Buffer(16); /* 直接代入資料陣列 */ var buffer = new Buffer([ 8, 8, 6, 9, 2, 6, 3, 3, 3, 5, 7, 2, 1, 1, 1 ]); /* 直接代入字串 */ var buffer = new Buffer('String!', 'utf-8'); var buffer = new Buffer('String!', 'ascii'); 你可以寫入資料: var buffer = new Buffer(32); /* 寫入一段字串 */ buffer.write('Write something', 'utf-8'); /* 只寫入兩個字元 */ buffer.write('Write something', 2, 'ascii'); 以操作陣列(Array)的方法,單獨存取每個 Byte 的資料: var buffer = new Buffer(32); /* 將每個 byte 歸零 */ for (var i; i < buffer.length; i++) { buffer[i] = 0; } 當然也有像 memcpy() 的資料複製: var buffer1

讓我們用 Node.js 與 DBus 打交道

一個多工的作業系統,最不可或缺的機制就是 IPC,應用程式互相溝通的管道。但在比較複雜的桌面應用,系統核心本身的 IPC 就顯得太過簡單,不敷使用。而『DBus』是一個被廣泛使用的 IPC 機制,擁有權限控管、標準的 Interface 甚至是可跨網路溝通等特性,讓應用程式只要遵循標準的資料結構,就可以將資訊傳遞到另一支程式手上。DBus 尤其是在桌面環境下被使用最多,從網路管理員(Network Manager)、藍芽(Bluetooth)連線管理、亮度/音量變更等各式更新訊息通知(Notification)機制,無一不用到他。但由於 DBus 有眾多複雜功能,撰寫程式去使用他其實不是這麼容易,所以若是能用 JavaScript 來做這項工作,肯定能加快許多。 對 JavaScript 而言,打通了 DBus,意謂著可以控制網路管理員,去建立所有類型的網路連線(無論是有線、無線、需要撥號或 VPN),亦可以連接 iBus(當前主流的輸入法框架)以支援並控制輸入法,甚至是可以控制絕大多數的系統服務,說是打通任督二脈可是一點也不為過。 上網尋找,其實已經有一些人嘗試在為 Node.js/V8 Engine 寫 DBus 的支援,只是多半都不夠完整或 API 的使用上過於複雜,這讓筆者萌生了要自己開發一個新的 Dbus 模組的念頭。但重新開發實在是太累人,於是在網路上眾多的現成品中,挑選了一個 API 比較易於使用的專案『 node-dbus 』,然後為他加上更完整的功能,目前已經小有成果,除了提交回 upstream 外,也已經發佈到 NPM 上。 如果想要使用,你可以直接以 NPM 安裝(註:NPM上註冊的名稱和github上不太一樣): $ npm install dbus 其使用上相當簡單,建立一個自己的 DBus Service 範例如下: var dbus = require("dbus"); dbus.start(function() { var service_path = 'org.freedesktop.DBus.TestSuitePythonService'; var object_path = '/org/freedesktop/DBus/TestSuitePythonObje

我為什麼大舉投入 JavaScript 的相關開發

和我比較熟的人,最近應該都知道,目前我專注於 JavaScript 和 Google V8 engine 的相關研究上,甚至決定從今年開始,公司營運以及技術團隊的方向,是企圖提供『最專業的 Node.js 和 JavaScript 相關服務』。(所以,如果您有需要,請聯絡我們 :-) )我非常清楚知道,有些人聽到 JavaScript 就歡天喜地,而有些人則不將他當一回事。更有多到數不清的技術人員,熟悉並使用 JavaScript 非常多年,聽到我說要提供『最專業的 JavaScript 相關服務』,會不屑一顧甚至以為我在瘋言瘋語。不過,如果你願意聽,接下來我會說明這是怎麼樣的瘋狂服務。 我不能阻止你對 JavaScript 有預設立場,因為這是無奈的歷史包袱,但請暫時放下過去成見,聽我靡靡道來。 我所遭遇的矛盾 過去,絕大多數人都只將 JavaScript 視為 Web 開發的一環,在大家的印象和認知中,JavaScript 充其量只是一個在瀏覽器中控制著 HTML DOM 的腳本語言。雖然近年來出現了 Node.js,過去微軟也支援使用者使用 JavaScript 撰寫 ASP 和系統腳本程式,但也不改這樣的看法:『JavaScript 是身處於末端的語言,與網頁、網站密不可分的東西』。所以,對許多硬底子的企業和研發人員來說,JavaScript 象徵了 Web/HTML 與不彰的效能,一種幻想的存在;而對很多 Web 開發者和前端工程師來說,JavaScript 卻是一種當今資訊產業的萬靈丹。如此天差地遠的矛盾,一直存在於這個產業界。 曾經當過 Web 開發者一段不少的時間,我承認也理解,使用 Web 技術來實作各類使用者界面(User Interface)和資料庫應用,非常容易和快速,不用考慮到太多的事。這一切要歸功於 JavaScript 和 HTML 的合作無間。所以,不時能聽到一些 Web 開發者,嘲笑作業系統程式開發者和嵌入式裝置的技術人員的辛苦,認為許多功能和特效,使用 Web 技術一下就達成了。 由於我過去也是『慣C』一族,做過很多包羅萬象的硬碰硬開發,小從一般電腦到嵌入式裝置、桌面系統到手機平版,大到各類特殊需求的系統研發,都有所涉獵。所以,對於系統資源和效能,一直有著莫明的堅持。也因為長期的磨練,深

Node.js Callback Function 不成文的習慣

我們常會在一些 Node.js 或是第三方模組的 API 上,看到 callback function 的第一個參數是 err 的情況,雖然官方並沒有明文規定(或許有,只是我沒有看到?),但這樣的習慣已經隨處可見。從官方 API 文件中的範例,就能看到許多例子: fs.rename('/tmp/hello', '/tmp/world', function (err) { if (err) throw err; console.log('renamed complete'); }); fs.stat('/tmp/world', function (err, stats) { if (err) throw err; console.log('stats: ' + JSON.stringify(stats)); }); 這樣的情況,最常出現在非同步(asynchronous)執行的函式中。因為這類的函式呼叫,做法是將工作丟到背景等待完成,所以會立即回傳(return),並繼續執行下面的程式。而該函式的工作,在真正完成或有出錯時,會呼叫 callback function。所以,在 callback function 內,我們需要藉由判斷 err 存在與否,去得知該函式是否完成工作或出錯。 至於 err 是什麼格式,對大多開發者來說,他只是個純字串的存在,也就是你可以直接印出它的內容: console.log(err) 但事實上,err 是 Error 物件,這是 ECMA 有定義的標準物件,對一些有經驗的 JavaScript 開發者來說,應該不陌生,甚至除了 Node.js 之外,在其他的瀏覽器上都有支援。如果想知道他是什麼東西,也可以自己嘗試建立一個 Error 物件來觀察: var err = new Error('Hello Error!'); 比較有趣的是,Error 物件被建立時,會包括 JavaScript Engine Stack 的資訊,這有利於更進一步的 Debug 工作。 console.log(err.stack) Error: Hello Error! at repl:1:6 at REPLSe

探討 Node.js 的非同步機制

Node.js 標榜著事件驅動(Event Drive)的設計,也因為如此,它在網站應用程式的領域上,通常強調有最快速的即時反應。其原理是利用 libev 去實作事件輪詢,不斷的檢查是否有事件需要被處理,一旦發現有事件在待命,就去執行並觸發相應的 Handler。但無可避免的,總會有程式和工作需要佔用大量的 CPU 時間,因此獨佔目前的事件處理程序,造成整個程式被單一事件卡死。這樣的問題,有機會讓原本期望的即時反應機制崩潰。 同樣的問題,也出現在其它 non-blocking 設計的 Framework。Facebook 所開發,也紅過一陣子的 Tornado Web Framework,針對這個問題,就提供了一個 Decorator  -『@tornado.web.asynchronous』,這可以讓 Handler 處於非同步的模式下執行,意味著該段程式可以先丟到背景,而不會讓整個程式為了等待該 Handler 結束,而耗時太久或卡死。 相同的,Node.js 也提供擁有類似的設計,只不過對於語言的使用者來說,概念和用法上不太一樣,因為 Node.js 所提供的 API 目標並不只是單純處理 Web Server 的應用,更像是低階的工作排程器的控制,如作業系統上的 yield() 或 sched_yield()。 我們可以很快的透過一個簡單的例子,去理解怎麼使用他,假設我們開一個檔案讀資料,一般邏輯上的做法(這裡所用的 file 物件是假的,在真實的 Node.js API 中並不存在,只是為了說明方便): file.open(); while(true) {     result = file.read();     if (!result)         break;     /* Do something... */ }; console.log('blah blah blah...'); 若是這個檔案很大,需要花三分鐘才能讀完,那這個 while 迴圈肯定會鎖死,等讀完後才顯示『blah blah blah...』字樣。想想看,若是這樣的程式被放在 Web Framework 的 Handler 中,肯定會因為這一個使用者,讓其他人三分鐘之內,都無法使用這個網站服務。而實際上,這樣的問題最常出現於檔案上傳的工作上。

玩什麼雲端?

雲端這個詞已經吵得鬧哄哄,也有更多人為了這個『形容詞』下了太多的定義,到底什麼是雲端已經變得不重要,也無法三言兩語說的清楚。身為一個資訊產業的創業小老弟,其實並不期待雲端能帶給資訊業如何的革命和新生態,只視為這是一次新契機,讓政府和台灣科技業的老大們,能靜下心傾聽。 我們暫且不需要討論雲端的格局觀,因為這類的畫餅,大從國家政策,小到百姓家常,已經太多了。我們有預算,有政策,有土地,有銀行,有股票,什麼都不缺,只缺少夠多的實際作為而已。其實,回顧過去,可以看到許多事我們現在可以做,但是大多數人,多半用美國矽谷的角度探討當今的資訊產業,我認為,那無法幫助台灣人省視情勢,因為有太多經驗不是在台灣的業界可以仿效或改進的。所以,既然人在台灣,當以台灣出發的角度,省視這些年來的發展過程,因此,筆者將以自己在台灣的經驗,嘗試省視這個產業,雖可能不算準確,卻是一種不同角度的嘗試。 的確,筆者剛滿 26 歲,年紀不足,在商業上,經驗也不算多。但在上一個世紀末,卻曾趕上過十幾年前 .COM 的最後一班列車。至今,看著當年遺留下來的無價紀念品,那些重量級的網域名稱,是花再多錢都無法獲得的一種經驗,令筆者有著無限的感慨和體會。說實在,如果沒這樣做過,永遠不會理解,不受金錢誘惑,堅持自己認為正確的事,然後去惡搞並使用那些當年叫價上億美元的網域名稱,是多麼痛快的事。 很多人會說我是忌妒,眼紅看著在十多年前還是小學生時,曾經發想和完成過的東西,諸如網路相簿、Blog、購物車、集體購物等,還有更多當時翹課躲書店而寫出來的服務,在今天一一出現或成功於網路上。事實上,比起心中的不平衡,我開心自己從中學到更多當時沒有看清楚的事,讓今天的視野可以更開闊。 還記得當時,所有人對網際網路(Internet)都有一種特別的期待,就像今天的雲端(Cloud)魔力一樣。全世界的人也都像現在一樣,砸進了無數的人力物力,在商業界,更是起了許多不得了的名目,打算大賺一筆。然而,絕大部份獲得勝利的人是誰?不是那些有錢有勢的企業和組織,而是真正做事和成本相對低的車庫公司。在某方面來說,這些大企業意外吃了不少悶棍。 從國內的發展來看,雖然在網路發達的今天,網路速度已經不再是大問題,架設網站的成本也不是太高。你可能很難想像當年,要是你有著一條 64K 專線,都可以成為台灣 ISP 公司的情況。也因為如此,當時

那一年,我們一起用Node.js開發3D使用者介面!

圖片
曾經想要用 Node.js 開發一些原生的應用程式或是 OpenGL 程式,但無論怎麼問,無所不答的 Google 大神都給我千篇一律的答案:『使用 HTML5 和 WebGL』。這答案其實不令人意外,因為截至目前為止,大多數學習使用 Node.js 的人都是 Web 開發者,其所提出的解決方案,理所當然都是與『瀏覽器』有關。想來有趣,Node.js 就是『與瀏覽器剛分手的 JavaScript Engine』,為何還要回頭與瀏覽器糾纏不清呢?於是,筆者開發並於 GitHub 釋出了一個 Node.js module - 『 jsdx-toolkit 』,讓 JavaScript 開發人員,可以輕易使用 Node.js 開發原生的桌面應用程式,更重要的是,不但可以寫炫麗的 3D UI,而且完全不需要靠『傻大個瀏覽器』。 如果想要載入圖片,並把物件 3D 旋轉,只需要這樣做: var toolkit = require('jsdx-toolkit'); if (toolkit.init() != toolkit.INIT_SUCCESS) { console.log("Failed to initialize jsdx-toolkit."); process.exit(); } /* Create a new stage */ var stage = new toolkit.Stage(); stage.title = 'Rotate'; stage.resize(500, 500); stage.setColor(0, 0, 0, 255); stage.on(toolkit.EVENT_DESTROY, function() { toolkit.quit(); }); stage.show(); /* Load a image */ var texture1 = new toolkit.Texture; texture1.loadFile('fred.jpg'); texture1.setPosition(100, 100); texture1.rotate(toolkit.Y_AXIS, 30, 0, 0, 0); stage.add(texture1); toolkit.

我的 Kinect 應用程式開發記錄

圖片
話說微軟(Microsoft) 這兩年為了 XBox 360 所推出的 Kinect 造成一股風潮,一夕之間,把 Wii 打的七零八落,取代了其體感遊戲機王者的地位,相比之下,Sony PS3 同一時期所推出的體感裝置,就顯得乏人問津 。 最近,筆者雖然忙錄,被很多麻煩的公事私事綁住,但每當睡前,仍抽空研究一些新技術。一方面是為了促使腦筋轉得更快,一方面是想加強許多 Idea 和 Business Model 的強度和完整性。於是,撿起丟在一旁生灰塵的 Kinect,嘗試著在上面開發一些應用。 由於『 OpenKinect 』眾高手的努力,所以驅動程式不是太大的問題,很久以前就已經能分別在 Linux、Windows 和 Mac 上驅動 Kinect。不過雖說如此,最困難的還是在於辨識演算法的相關設計,對於開發人員來說,你不過就是能得到攝影機的影像,就如同從 Webcam 上得到一樣,其他的圖學運算以及應用還是要自己動手。 當然,如果 Kinect 只是和一般 Webcam 一樣,那新聞媒體和許多人對他的誇讚,就太言過其實。其最大的不同在於,Kinect 有深度感測,這意味著我們可以得到實際的空間資訊,以工程的方式,大大減少辨識演算法的難度,並提升了辨識系統的精準度。 這次的嘗試,焦點放在辨識演算法之上,便開始思索各種方案。過程中,試了數種別人已經開發好的函式庫,都不甚滿意。倒不是效果不好,而是系統需求太大,開發語言大多採用  Java ,所以需要安裝一卡車的模組程式以及 JVM。有些更是對 Linux 的開發者不夠友善,或開發支援不夠完整。無論哪一種現有方案,都不足以讓筆者可以安心建構在上面然後開發下去,因為產品化和易移植性,對筆者來說是相當重要的考量,不是只要學術驗證而已。所以最後決定,自己手動設計演算法,採用 C/C++。 經過這幾天睡前的努力,可以看到開發過程中的截圖,演算法初步已經能辨識手掌,並抓取指尖位置,精準度已達可用的程度。接著,只要多做些簡單的開發,撰寫 X11 輸入裝置驅動程式,就能實際以多點操控的型式,操作螢幕上的所有應用程式。 此外,這裡有一些心得,Kinect 深度感測的數值範圍是 0 ~ 2047,至於得到的深度數值如何換算成實體距離,這邊有個公式可以換算成公尺(Meter)的型式: Real Distance = 1.

用 NodeJS 打造守護神常註程式

寫系統程式很常會需要碰到實作常駐程式,這意味著你必需要讓程式在背景執行,然後提供服務或是等待事件觸發,如『 親手打造一個背景執行的Daemon程式 』所提到,若用 C 語言,做法大致如此: void main() { pid_t pid; pid = fork(); if (pid>0) { exit(0); } } 而在 node.js 上可以使用『 daemon 』模組,輕易打造常註程式。 $ npm install daemon 使用方法如下: var daemon = require('daemon'); /* Become a daemon */ daemon.start(); /* Loop to do something here in background */ 執行後,程式應該會立即返回並結束,但是若用 ps 等系統工具程式去看目前正在執行的 Process,會發現我們的程式已經運行在背景了。

JuDaemon 完全取代 GNOME 的最後一根稻草

我們不得不承認,GNOME 為了整合桌面環境,曾經開發了很多好用的整合性的元件,像是桌面背景控制、圖型化元件樣式、螢幕設定監控和更多桌面功能的設定程式。對於我們這些不愛 新版 GNOME 的使用者來說,常常是改用其他桌面環境(如:LXDE、E17 或單純用 Awesome window manager),再配上 GNOME 的這些整合性元件。 不久前,雖然 GNOME 進入了 3.0 時代,但這些整合性元件依然存在著,並不隨著版本上升而有所太大改變,這對我們這些『不肯升級的使用者』是很好的消息,沒有太大的影響。不過,在最近幾個月,GNOME 已經將這些元件一一消滅,整併進去其他的專屬程式當中。在 Debian 上,gnome-control-center 更是已經毀損(如果你沒有裝新版的 GNOME 3.0),更進一步,許多重要的系統常駐程式一一失效(如:gnome-settings-daemon 和 gnome-power-manager 等),不再如同過去可以輕易單獨使用。 GNOME 所帶來的毀滅,已經嚴重影響到筆者現有的使用,所以打算再次繼續原本停滯一段時間的 Juice Desktop Environment (詳情可參考『 新鮮果汁吧!果汁桌面環境(Juice Desktop Environment)! 』),過去曾開發過『 JuShelf 』,就屬於這計劃的元件之一。 大概評估了工作,主要就是系統監控程式的實現,也就是取代舊有 gnome-settings-daemon 的功能。對筆者個人而言,目前只有幾種簡單需求: 電源管理:螢幕休眠、電腦蓋上後自動休眠、AC 電源切換通知和低電壓通知。 螢幕設定:插上外接螢幕後自動偵測,拔除時也自動恢復成單一螢幕(現在是一片黑)。 OSD支援:調整螢幕亮度、音量時,可以跳出畫面顯示目前亮度和音亮。 日後當然還需要有圖型化程式,可以微調這些細部設定,不過不是初期主要的工作(相信會選擇不用 GNOME 的人,應該都有能力自己改設定檔)。 筆者成立了一個新的 Project -『 JuDaemon 』,就是為了解決這樣的需求,目前只完成了螢幕自動休眠的部份,尚有其他工作待繼續。如果您有興趣,可以提交 patch 或是加入這個專案一同開發。:-) 後記 考慮到筆者近來