2010年7月28日 星期三

碩士在職專班(夜間)念完兩年大約需要費用多少?

EMBA、在職專班和一般MBA課程項目皆大同小異,但學習方法差很多,我先清楚說明,這EMBA、在職專班及一般生MBA有甚麼差別:
就門檻來講,其實每個學校設置的門檻都稍有不同,但是EMBA大體上要求工作資歷(這裡的工作資歷是指當你從大學畢業(或同等學力)後起算)在十幾年以上(職位但大多是經理、副總以上層級);
在職專班的要求則大多是五至十年的工作資歷;
MBA(或其他一般生研究所)則是大學畢業即可報考;
考取的難易度取決於競爭者不同而有不同,
如果你在職很久要考一般生就會很費心力,
如果你剛畢業沒多久通常也不會具備資格來考在職專班、EMBA。

以難易度來說其實視情況判斷,不過大體上國內十大名校(台、政、清、交、成、中央等)一般生研究所競爭激烈度非常高,至於碩專班跟EMBA通常需要視情況比資格跟比經歷,當然最後的筆試及書審資料(口試分數常和書審分數高度正相關)的得分,就是最後的入門關鍵,但是基本條件有沒有符合常常就是取決於能不能考上的大前提。
至於學制部分,由於教育部鼓勵在職進修,大體上所有碩士都可以最快在一年半念完,最晚六年念完,那沒有特別的規定在職專班、EMBA、一般生一定要念幾年,不過大體上一般生都是兩年畢業,少數念到三年;至於EMBA、在職專班大都都是兩年半至三年,但有也有人念到四、五年左右,完全取決於學生在生活、工作上調配的需要。

而上課時間,一般的MBA(或其他一般生研究所)就是跟一般的學生一樣,禮拜一至禮拜五的白天排課;
EMAB涉及到高階主管的職位,大多是禮拜五的晚上、禮拜六跟裡拜天排課;
在職專班則是看各學校,有些學校專排六、日,但大部分的在職專班則利用禮拜一到禮拜五的晚上排課。

提供些學校費用參考~
(1)台灣大學 約 24~42 學分
EMBA 學雜費約 100,750 元 / 學期 ( 一年 3 學期 )
 在職專班 學雜費約 53,470-73,170 元 / 學年

(2)政治大學 約 36 ~45學分
EMBA 約 10,000 元 / 學分;學雜費 12,480/ 學期
 在職專班 約 3,500-17,000 元 / 學分;學雜費 12,300-14,280 元 / 學期

(3)清華大學 約 24 學分
EMBA 約 10,500 元 / 學分;學雜費 11,080 元 / 學期
 在職專班 約 5,250 元 / 學分;學雜費 12,980 元 / 學期

(4)交通大學 約 24~42 學分
EMBA 約 10,000 元 / 學分;學雜費 12,980 元 / 學期
 在職專班 約 5,000 元 / 學分;學雜費 12,980-13,470 元 / 學期

(5)成功大學 約 30~45 學分
EMBA 約 8,000 元 / 學分;學雜費 12,000 元 / 學期
 在職專班 約 3,700 元 / 學分;學雜費 11,400-13,700 元 / 學期

jQuery vs MooTools

大部分最近才剛接觸JavaScript的人會面臨到的困難是該選擇哪個套件(library)或是該先學哪個套件。如果你在一間公司裡上班,那麼可能公司已經有一套固定使用的套件,若是在這種情況下,問題就沒那麼重要。如果你的公司選擇使用MooTools而你自己已經習慣使用jQuery,那麼這篇文章也許對你還是有些幫助的。

每天在 Twitter上 我看到 一堆人討論著MooTools好還是jQuery的話題。這篇文章希望能幫助你做出這決定。

聲明

我是個MooTools的開發人員。我也專注於MooTools這個framework。我的部落格是有關MooTools。我寫過MooTools的線上文件以及一本有關MooTools的書。很明顯的我的立場是有一點偏頗的。我也必須說明我並不常用jQuery。如果你是個jQuery的開發員,同時看到我文章裡任何謬誤之處,請聯絡我並不吝給予指教錯誤之處。我的目的是讓文章正確且有所助益而非去推銷特定的framework。

目的

透過我的說明,讓大家明白這兩個frameworks之間的差異進而能幫助大家做出一個選擇。我首先要說的是,兩個frameworks都是很好的選擇,你並不會選到一個糟糕的framework。兩者各有其強項與弱項,但是都是很棒的。除此之外還有很多也很優秀的frameworks值得考慮,如Dojo,Prototype, YUI, Ext 等等的。這些選擇基本上也取決於自己的習慣跟需要完成甚麼樣的東西而定。這篇文章的重點在於MooTools跟jQuery之間的比較,因為我看到越來越多的人在這兩者之間猶豫不決著。最後我要聲明的是,我並不是想要說服誰誰誰從某個framework轉換到另一個,這兩個frameworks其實有很多有趣的地方值得我們學習。你可以從這個公告看到我寫這篇文章的由來。

內容

標題說明一切
學習曲線與社群
JavaScript過人之處
不只是DOM
JavaScript的繼承
自我參照
MooTools把JavaScirpt變得更有趣
jQuery把DOM變得更有趣
你行的我比你更行
MooTools讓你想怎樣就怎樣
連續技(Chaining)的設計模式
jQuery程式的重複利用
MooTools程式的重複利用
MooTools與繼承
延伸與實作(Extending and Implementing)
抉擇
討論
統計

jQuery 核心 MooTools 核心
檔案大小 55.9K 64.3K
功能
授權 MIT & GPL MIT
DOM 工具 yes yes
動畫效果 yes yes
事件處理 yes yes
CSS3 選擇器 yes (Sizzle引擎) yes (Sly引擎)
Ajax yes yes
原生物件延伸 Native Extensions (不含Element) 10幾個關於 Array, Object, 以及 String的延伸 約70個 Array, Object, String, Function, 以及 Number 的延伸
繼承 沒有直接支援繼承 提供 Class 構件式
其他考量項目
plug-ins 上百個非官方 plug-ins: plugins.jquery.com 目前約四五十個官方 plug-ins: mootools.net/more, & mootools.net/plugins
官方UI套件 yes no
資料來源: jquery.com, mootools.net, 與 wikipedia.com.

標題說明一切

如果你去jQuery的網站看,它最上面的標語就寫著:

jQuery是個簡潔快速的JavaScript函式庫,能透過簡化HTML的操作、事件的處理、動畫效果以及Ajax互動來加速網頁開發。jQuery是一個可以改變你寫JavaScript方式的函式庫。
...然後如果你到了MooTools的網站,你也可以找到這段話:

MooTools是個精簡、模組化同時也物件導向的JavaScript框架,設計給中等與進階的JavaScript開發員使用。透過其優美、詳細而條理分明的API,可以讓您寫出強大、富有彈性且跨瀏覽器的程式。
我想這就說明了全部了。如果你問我(因為你正在讀這篇文章,所以我假設你會問囉):重點不在於哪個比較好,哪個比較差,而是在於這兩者的特性之間,該如何取捨衡量?這兩個框架(frameworks)試圖要做的事情並不相同,在功能上它們或有重疊但目標並非一致。

jQuery的那段敘述講的是關於HTML、事件、動畫、Ajax與網頁開發,MooTools那段說的是有關物件導向、強大且彈性的程式架構。jQuery要改變你寫JavaScript的方式,而MooTools則是為了中高階JavaScript開發員而設計。

這其中值得思考的是關於框架與工具包(framework vs. toolkit)的概念差異。MooTools是一個用JavaScript原本應有的方式來寫JavaScript的框架(framework)。其立意是實作一個跟JavaScript非常相似的API並且針對各個部分加以強化,而不只是針對DOM而已。jQuery則比較像是包好了很多很方便的函式在一個工具包裡(toolkit),這個自成一個體系的工具包讓DOM的操作變得更簡單易用。而DOM剛好就是大多數的人寫JavaScript時花最多時間的地方,所以在大多數的情況下,jQuery就是你最好的選擇。

大部分你用MooTools所寫的程式還是跟JavaScript很像,如果你對JavaScript這個程式並不是很感興趣,那麼學MooTools對你來說就會是很討厭的事情。如果你對JavaScript有興趣,也想知道它哪裡有趣、強大而多樣,那麼我個人認為MooTools是個較好的選擇。

學習曲線與社群

首先,jQuery是非常非常容易學會的。它的撰寫風格如同口語般幾乎不像個程式語言。如果你要的就是快速搞定又不用刻意學習JavaScript的話,jQuery可能對你而言是較好的選擇,MooTools並不具備這些好處。我必須承認如果你是個JavaScript新手,MooTools會有點難上手。加上有很多現成的資源或教學可以幫助你學會jQuery,至少比MooTools多。

如果你比較看看jQUery(jQuery的討論版)跟MooTools的社群(irc, mailing list),你馬上就會發現:一) jQuery的社群資源與數量遠大於MooTools(我認為是因為之前說的那個原因易學以及...)。二) 她們比較積極推廣。如果你用使用的人數、Google搜尋的次數以及賣出的書量來衡量jQuery與MooTools,你會看到jQuery是遙遙領先的。

為了要完整說明為何你可以考慮用MooTools的原因,我必須先說一下這兩個frameworks在做什麼事情。最終你會選擇哪個framework還是取決於你想要達成什麼目的以及你想用什麼方式寫程式(甚至關乎你是否喜歡程式,或至少喜歡JavaScript)。

JavaScript過人之處

抉擇的過程裡,你得先問自己想要用JavaScript來做什麼。我們可以先想想純JavaScript的情況,不使用任何的framework;就是傳統的JavaScript程式。JavaScript提供一些原生的物件像是 Strings, Numbers, Functions, Arrays, Dates, Regular Expressions, 等等,同時也提供了一個繼承的模型 - 一個有點難懂的模型叫做原型繼承(prototypal inheritance,我稍後會作說明)。這些基本架構跟繼承概念就是足以支撐著各種程式語言的基本要素,而且這些要素跟瀏覽器、網頁、CSS或HTML都沒有任何關聯。所以其實JavaScript是可以用來寫出各種程式的,不管是井字遊戲、西洋棋、相片編輯程式或是個網站伺服器。只是剛好百分之九十九的JavaScript都在瀏覽器上執行,所以我們通常就把它當作是瀏覽器專用的程式了。

絕大部分的JS都應用在瀏覽器跟DOM,但其實JavaScript是個非常健全且多樣的程式語言,如果能夠理解這點的話,會有助於你了解MooTools跟jQuery之間的差異。

不只是DOM

如果你認為JavaScript做的事情就是"指定頁面中的某個東西,然後對它做一些動作",那jQuery可能就是最好的選擇了。jQuery提供了一個非常好的架構讓你用幾乎不像是程式語言的方式去描述頁面中的行為。你還是可以用JavaScript的其他功能來寫出你想要的程式,但是如果你的重點在DOM - 動態改變CSS、動畫效果、透過AJAX來取得內容等等,你需要寫的大部分程式都可以用Jquery完成,其餘未包括的部份就會是原本JavaScript的寫作方式。此外jQuery也提供一些非DOM相關的程式,例如繞陣列迴圈(iterating)的方法 - $.each(array, fn) - 或是用$.trim(str) 除掉字串前後空白的函式。這些公用程式並沒有很多,不過那也沒差,因為大部分情況下,如果你只是從DOM裡面指定了幾樣東西,繞了迴圈,變更了某些細節(插入HTML、改變樣式或是定義一個滑鼠點擊的事件等等),其實並不需要那麼多公用程式。

不過如果你用比較廣泛的角度來看的話,jQuery並沒有把心思放在DOM以外的事物上。這也是它如此易學的原因之一,但同時也限制了從其他方面來幫助你撰寫JavaScript。它除了扮演著一個完整的DOM程式語言之外,便再無二心,沒有在繼承物件概念或是提供基本型別的公用程式上多下功夫,因為它本來就沒這個必要。如果你想在字串、時間、正規表示式、陣列或函式之間周旋的話,可以。只不過那並非jQuery的使命,JavaScriprt一直都在那,隨時要用都可以的。jQuery讓你能夠輕鬆駕馭DOM,但其他的東西就不是它的範疇了。

這點跟MooTools有很大的不同。MooTools把範疇放大到整個JavaScript語言,而不單單只是針對DOM而已(據我所知,MooTools也提供跟jQuery相同的功能,但是用很不一樣的方法寫的)。如果jQuery讓你能對DOM為所欲為,MooTools則是讓你能夠對整個JavaScript為所欲為,這也是它學習難度較高的原因之一。

JavaScript的繼承

JavaScript裡面有些很棒的東西。首先,它是個函數程式語言。這代表著function被視為高階物件,像其他物件 - 如字串或數字般可以被互相傳遞。當你用這種方式來寫程式,很多模式跟方法可以藉由這個設計理念獲得最好的結果。兩者之間的差異:

for (var i = 0; i < myArray.length; i++) { /* do stuff */ }
以及

myArray.forEach(function(item, index) { /* do stuff */ });
JavaScript有一種 繼承模型,在程式語言的世界裡,不能說獨特但也算是相當罕見。JavaScript是用 原型繼承的方式來做,而非類別(class)在延伸次類別的繼承方式,這表示物件是直接繼承另一個物件的原型。當你參照一個物件的property,程式會先從物件本身尋找是否有此property,如果沒有的話,就去找該物件的父親。這就是一個陣列可以有method的原理。當你寫了:

[1,2,3].forEach(function(item) { alert(item) }); //this alerts 1 then 2 then 3
"forEach"這個方法並不存在於你所定義的陣列([1,2,3])裡面,它存在於所有陣列的原型中。當你參照forEach這個方法時,JavaScript會在你定義的陣列中去找,如果沒有的找到的話就去陣列的原型去找。這表示說,並非所有陣列都在記憶體中有forEach這個方法,它只要在陣列的原型裡放一次就可以了。這種方式非常有效率也非常非常強大。(補充:MooTools裡面forEach的對應method是each)

自我參照

JavaScript有一個特別的字眼:"this"。我很難在這邊簡單的定義甚麼叫this,但是一般來說this就是指目前method的所有者。this允許物件可以在其所屬方法運行時參照到物件自己本身,也正是this存在的目的。當你產生很多子物件然後又有很多父物件的實體(instances)時,這就變得很重要了,否則還能甚麼其他方式來參照自己?當一個方法(method)原本屬於父物件而非子物件,this這個關鍵字就能讓實體們都能參照到它們自身。(這裡有this更完整的解釋,還有Mozilla的)

this可以讓那些繼承而來的子物件參照到它們自身,但是有時候也可能需要用this參照到其它的東西,你就要指定一個不同的this到方法(method)裡,這就叫做榜定(binding)。陣列的each方法的第二個參數可以讓你指定一個物件做榜定(binding)。可以參考一下這個範例傳了一個不一樣的 "this":

var ninja = {
weapons: ['katana', 'throwing stars', 'exploding palm technique'],
log: function(message) {
console.log(message);
},
logInventory: function() {
this.weapons.each(function(weapon) {
//we want "this" to point to ninja...
this.log('this ninja can kill with its ' + weapon);
}, this); //so we pass "this" (which is ninja) to Array.each
}
};
ninja.logInventory();
//this ninja can kill with its katana
//this ninja can kill with its throwing stars
//this ninja can kill with its exploding palm technique
上面的範例裡面,我們把ninja榜定(就是在logInventory裡面的this)在傳給陣列的那個方法(method),所以在each裡面我們可以參照到ninja的log的屬性。如果我們沒這麼做的話,this得到的參照就會是window了。

這些只是幾個範例,用來說明JavaScript提供了強大多樣的繼承、自我參照、榜定跟原型特性。不幸的是,原本的JavaScript並沒有把這些強大的特點凸顯出來,這也是MooTools之所以發展的起頭。MooTools把這幾種類型的模式變得簡單也更和善。最終你會寫出更為抽象的程式,長遠來看這會是好事情 - 也會是很棒的程式。去理解這些模式的價值以及如何正確地使用它們是很需要花費心力的,但是從好的方面來看,你所寫的程式會具備高度的重複使用性也會非常容易維護。這些好處我等等會稍做說明。

MooTools把JavaScirpt變得更有趣

因為MooTools專注在增加JavaScriptAPI的穩定性與連貫性,所以在"改變你寫JavaScript的方式"這件事情上就沒有太多著墨,整體來看它卻是降低了JavaScript使用上的不便。MooTools是JavaScript語言的擴充,也試著把JavaScript導向原本應走的路上。整個架構的核心有重要的一部份是在加強Function、Stirng、Array、Number、Element跟其他的原型物件。另一個重點是它提供了一個函數叫類別(Class)。

現在,對人們來說,Class看起來像是要重建一個像Java或是C++那種正統的繼承式模型,其實並不是那麼一回事。這個Classn所做的是幫我們更簡單地存取JavaScript的原型繼承模型並且更加凸顯它的優勢。我要說明的是這概念並不是MooTools才有的(其他的一些frameworks也有提供類似的功能)。但是jQueryy並沒有這些的設計概念,jQuery沒有所謂繼承的系統也沒有任何加強原生物件(Function、String等)的架構。這並非jQuery的缺陷,因為作者其實可以輕而易舉的增加這些東西進來;而是他們是以不同的目標來設計這個工具包(toolkit)套件。MooTools的目的是讓JavaScript變的有趣,而jQuery是要把DOM變得有趣,所以它的設計者設定了這樣的範疇來達到目的。

jQuery把DOM變得更有趣

這也是為什麼jQuery比較有親和力,它並沒有要求你把JavaScript從裡到外都搞懂,它不會把你丟到底層去跟原型繼承架構、榜定、"this"和原生原型(native prototypes)打交道。當你開始從官網接觸jQuery,你可以看到它的第一個範例:

window.onload = function() {
alert("welcome");
}
and here's the third:

$(document).ready(function() {
$("a").click(function(event) {
alert("Thanks for visiting!");
});
});
如果你讀過MooTools的書或是教學(我寫的那兩個),裡面開頭的章節就很不同。如果要學習怎麼使用MooTools的話,你必須從一些基本的概念開始看起,例如Class,雖然你也可以略過直接開始學有關特效或是DOM的部分。而且我也必須承認:如果你是寫程式的新手或你想要快速架站,而非得要先了解JavaScript的一些細節,可能對你來說jQuery會比較友善的多。

反之,如果你想要好好學習JavaScript這個語言,MooTools是一個很好的管道。MooTools實做了很多JavaScript以後會有的功能(很多在Native的方法正是JavaScript 1.8或更新版本會有的)。如果你是老手了,特別是熟悉物件導向以及函數式程式語言(functional programming)的人,MooTools有很多令人振奮且驚艷的設計模式(design patterns)。

你行的我比你更行

如果你看一下jQuery所提供的功能,你會發現通常MooTools也有提供相同的功能。或如果你看一下MooTools的功能,你會發現jQuery通常沒辦法達到相同的目的,因為jQuery專注的是DOM相關功能,MooTools提供的功能則涵蓋的層面比jQuery還廣些。不過jQuery也不會阻礙你去實做那些MooTools才能達到的功能。舉例來說,jQuery並沒有提供繼承的架構,但是沒關係,如果你想要的話還是可以結合MooTools 的Class來達到(或自己寫一個)。甚至也有人寫了一個繼承的jQuery外掛(我沒有用過不過我想它應該也能提供相同的功能)。

如果我們回頭看一下上面jQuery的那個範例:

$(document).ready(function() {
$("a").click(function(event) {
alert("Thanks for visiting!");
});
});
如果我們要轉成MooTools的語法,就會變成:

window.addEvent('domready', function() {
$$('a').addEvent('click', function(event) {
alert('Thanks for visiting!');
});
});
非常相似吧?

或是這個比較複雜的jQuery範例:

$(document).ready(function() {
$("#orderedlist li:last").hover(function() {
$(this).addClass("green");
},
function() {
$(this).removeClass("green");
});
});
and in MooTools:

window.addEvent('domready',function() {
$$('#orderedlist li:last-child').addEvents({
mouseenter: function() {
this.addClass('green');
},
mouseleave: function() {
this.removeClass('green');
}
});
});
也是非常類似。我想說明的是,MooTools的版本語法更為清楚,不過也因此較為累贅。MooTools的程式閱讀很清楚可以知道我們增加了兩個events,一個是滑鼠移入物件時的,一個是滑鼠離開物件的。而jQuery則較為簡潔,它的hover方法一次接收兩個functions,第一個是滑鼠移入物件時用,第二個是滑鼠離開物件時用。我個人比較偏好MooTools程式的可閱讀性,不過那是主觀的看法。

我有時候會覺得jQuery的語法過於艱澀隱晦,一個方法(method)裡可接收兩個function這回事我光是用看的的話,並非那麼容易理解。由於我對MooTools很熟悉,這說法多少有點不公平,因為讀MooTools的程式對我來說很簡單。不過MooTools方法與類別的命名方式很有名符其實的味道,這點我很欣賞。MooTools幾乎都是用動詞來命名,留下一絲絲疑惑是對"甚麼"做動作。當然在撰寫每一種程式語言時,你都需要去看文件來查語法,我意思不是說MooTools就不用,我只是覺得MooTools的API的命名邏輯比較連貫一致。

MooTools讓你想怎樣就怎樣

可是如果你比較喜歡jQuery式的語法怎麼辦?MooTools也是有這種能力把程式變得更合你胃口,如果我們想在MooTools裡面實作jQuery的hover,我們只要加上這段:

Element.implement({
hover : function(enter,leave){
return this.addEvents({ mouseenter : enter, mouseleave : leave });
}
});

//然後你就可以用跟jQuery相同的語法:
$$('#orderlist li:last').hover(function(){
this.addClass('green');
},
function(){
this.removeClass('green');
});
實際上確實有MooTools的plug-ins在幫你完成這些動作:jQuery syntax for MooTools。MooTools著重在延伸能力上,這意味著你可以做任何你想做的事情,這是jQuery沒辦法辦到的。MooTools可以模仿jQuery,但是jQuery沒辦法模仿MooTools,如果你想要用類別或是延伸的原生原型物件等等MooTools的功能,你就得自己手動去寫額外的程式。

連續技(Chaining)的設計模式

我們來試試別的東西看看,這邊有一些jQuery的範例(從jQuery教學裡面擷取的):

$(document).ready(function() {
$('#faq').find('dd').hide().end().find('dt').click(function() {
$(this).next().slideToggle();
});
});
我個人並不是很推崇這個範例的語法,光是看上面那段程式碼我很難立刻了解在幹嘛。最明顯的部分是那個.end在做甚麼以及後面連接的.find是啥,跟.end又有甚麼關聯。jQuery文件可以找到關於.end很清楚的解說(重設目前選擇的物件(selector),也就是#faq),不過我是覺得滿怪的。當我在用jQuery的時候,我自己常常不太能確定一個方法(method)會回傳甚麼東西給我。不過很明顯的,這並沒有困擾到大家,因為jQuery有著一大票的愛用者,所以我也把這個歸類為個人偏好之一。

我們來看看上面那段程式碼如果在MooTools裡面會怎麼寫:

window.addEvent('domready', function() {
var faq = $('faq');
faq.getElements('dd').hide();
faq.getElements('dt').addEvent('click', function() {
this.getNext().slide('toggle');
});
});
當然,MooTools還是比較累贅些,但是意思就更明確。同時也可以看到,jQuery用.end來回傳#faq這個物件,而MooTools的設計模式是把#faq放到一個變數裡。當然MooTools也可以寫出jQuery那樣的連續技(Chaining):

item.getElements('input[type=checkbox]')
.filter(function(box) {
return box.checked != checked;
})
.set('checked', checked)
.getParent()[(checked) ? 'addClass' : 'removeClass']('checked')
.fireEvent((checked) ? 'check' : 'uncheck');
不過說真的,像這樣把一堆程式碼跟判斷塞到一個domready宣告裡,不管是用哪一種framework都不是個很好的做法。如果把這些邏輯都封裝成可以重複利用的片段會好很多。

jQuery程式的重複利用

當你在執行一個網站專案時,可重複利用的程式碼是很誘人的。只需要寫一點點程式就可以選取所需的DOM,然後隱藏掉某些、變更幾個屬性以及增加幾個滑鼠的event就搞定一切。這種開發方式會非常的有效率、非常的快。不過把你的程式碼都寫在domready裡面的問題在於:最後你會在不同地方寫了一堆在做同樣事情的程式碼。如果我們用上面那個FAQ的範例來看,我們其實可以輕易地套用相同的程式碼套在不同的頁面中類似的結構。難道我們每次遇到這種結構時都要重複做一次相同的事情嗎?

有個很簡單的方法就可以把它變成可重複利用,我們只要把這段程式碼包裝起來然後給個參數讓它接收。在jQuery裡面可能會長這樣:

function faq(container, terms, definitions) {
$(container).find(terms).hide().end().find(definitions).click(function() {
$(this).next().slideToggle();
});
};
$(document).ready(function() {
faq('#faq', 'dd', 'dt');
});
這樣一來程式會好很多,有兩個很重要的原因:

如果哪天我們得要變更這個FAQ清單的運作方式(例如我們要加上點擊次數追蹤,以便在記錄檔中計算或是我們可能改成要透過AJAX來取得清單資料),我們只需要修改faq這個方法,在所有套用過的頁面都可以一次更新完畢。又或者是jQuery有個新的大改版,我們只需要把faq方法更新就好,不需要去每個頁面逐一修改。我稱之為把程式的資源最佳化,透過這樣的作法,我的應用程式中的其他一般程式碼盡可能地越少越好,我就能很輕鬆的除錯、更新整個framework、增加新功能或是修改原有的功能。
第二個理由是程式碼會變少。隨著相同的方法(method)被一再套用,我都不需做重複的工作,這在任何的程式語言裡面都是非常有價值的。而且我的網站訪客也可以節省下載那些程式的時間。
jQuery其實有在針對可重複使用的"wigdets"上做了一些調整。他們鼓勵人們使用jQuery plug-ins,而不是用上面那個範例(其實滿粗糙的)的方式。然後會長成像這個樣子:

jQuery.fn.faq = function(options) {
var settings = jQuery.extend({
terms: 'dt',
definitions: 'dd'
}, options);
//"this" is the current context; in this case, the elements we want to turn into faq layouts
$(this).find(settings.terms).hide().end().find(settings.definitions).click(function() {
$(this).next().slideToggle();
});
return this;
};
接下來你就可以這樣用:
$('#faq').faq();
從上面那個範例來看,寫一個faq 的plug-in跟寫成一個普通的function沒有很大的差別。是的,普通的function沒有放在一個全域的命名空間(global namespace),不過我們也可以創一個nampespace,然後把function放進去。像plug-in那樣依附在jQuery中,我們就可以把其他的jQuery方法用連鎖動作串再一起。另外一個好處是,function裡面呼叫this就會得到目前的元素(current context)。用plug-in的作法,就會讓function看起來像是jQuery的一部份,但是除此之外plug-in基本上就是一個單一的function加上能存取到目前的jQuery元素(context)、操作那些元素然後再把那些元素傳給連鎖動作中的下一個method。它並不複雜,所以每個人都能輕鬆的寫出jQuery plug-ins,它們就是functions而已。

另外注意的是,jQuery也可以寫一些較為複雜,包含methods跟狀態的plug-ins。jQuery UI有支援這種模式,不過寫法跟基本plug-in(像faq那個範例)不同,取而代之的是你會在jQuery上附加一個具有methods跟properties的物件(如$.ui.tabs)。它有個快捷方式讓你直接使用(如$(selector).tabs()),所以你還是可以使用連鎖動作,就像faq那個plug-in一樣。只不過它並不是回傳該物件本身($.ui.tabs),而是回傳jQuery 目前的元素(context),所以當你要存取tab的methods時,你必須再次呼叫一次selector。你必須再執行一次selector然後再呼叫function的名稱:$(selector).tabs('add', url, label, index); ,而不是直接呼叫類似像myTabInstance.add(url, label, index) 的東西。這意味著你執行了兩次選擇器(除非你用個變數來參照),你也沒有可以指向add這個method的參照讓你做像是綁定(bind)或是延遲(delay)的動作。這篇文章焦點在於MooTools跟jQuery的核心程式,而雖然jQuery UI有提供這些功能,但是jQuery本身並沒有。

MooTools程式的重複利用

在MooTools裡面當你要定義一個模式(pattern)時,你會用Class或是實作一個方法到原生的物件上(如String)。

MooTools介於一個獨有語法與擴充JavaScript原本的設計模式之間,它走的是一個較為中庸的道路,而非給你一個跟JavaScript完全迥異的程式語言。它的其中一個方式是去擴充程式本身跟DOM原生物件的prototype,如果你想要有個去掉字串空白的功能,MooTools鼓勵你在String物件上增加一個method(MooTools已經有提供String.trim,你不需要自己再寫一個)。

String.implement({
trim: function() {
return this.replace(/^\s+|\s+$/g, '');
}
});
這意味著你可以直接在字串上使用: " no more spaces on the end! ".trim(),然後你就會得到 "no more spaces on the end!" 的結果。有些人可能會說,去實作原型(native prototype)並不妥當,這也是為什麼MooTools跟Prototype.js沒辦法同時並存,任何兩個會動到原生原型的frameworks都是沒辦法並存的。如果我定義了,而在另一個函式庫裡面也有相同的東西,那最後定義的會覆蓋原先的。某種程度來說,這也跟window的全域命名空間的問題類似,這就是JavaScript的特性。這也是JavaScript 1.8增加新功能的方式,它們都是透過prototypes。

MooTools的開發者包好了一個完整的framework讓你可以很輕易的擴充你想要的功能,其出發點是讓你把這個framework放到網頁裡面去使用,而不是讓你放其他的framework,要求訪客在一個頁面下載兩個不同的framework其實是有點不禮貌的。一次套用兩個framework唯一可能的理由是,兩個frameworks的plug-ins你都想要用。MooTools作者(包含我自己)的想法是,如果你想要的某個plug-in是你所選的那個framework裡面沒有的,那可能比較合理的作法是花時間去做出來,而非要求使用者去多下載一個framework的檔案。

一旦你學會了JavaScript的運作原理跟擴充原生物件的強大功能,一個全新層級的程式寫作方式就此開展。你可以寫plug-ins來改變Elements、Dates或是Functions。某些人可能會說,這種添加方式是一種對原生物件的汙染,我必須主張這種方式就是JavaScript原本的意圖。它是程式語言設計的特色,透過添加methods到原生物件上,你的程式碼會變得更簡潔,更有區隔性。jQuery也有這麼做,不過只限於強化jQuery自己本身的物件。

雖然你可以輕鬆地在jQuery物件上連續呼叫methods,但是在其它一般物件上,你就不能用同樣的方式。舉例來說,如果你要一行一行地重複trim掉字串,在jQuery你可能得這麼做:

$.each( $.trim( $('span.something').html() ).split("\n"), function(i, line){alert(line);});
但是由於MooTools修改過prototypes,所以你可以:

$('span.something').get('html').trim().split("\n").each(function(line){alert(line);});
這個範例很清楚地示範了修改prototypes有多麼強大。連鎖動作並不是只能在DOM,連鎖可是個很有用的東西,MooTools讓你可以在任何物件上做連鎖動作,包括一次對多個元素(elements)執行一個method。

這裡的重點是MooTools的精隨在於它主張你可以寫出任何你想要的東西。如果有個功能是裡面沒有的,你可以擴充它並增加你自己要的。它的工作並不提供大家任何可能該有的功能,它是提供一個工具讓你可以為所欲為。它有很大一部分在做的事情是把擴充原生prototypes這件事情變得更簡單,善用原型式繼承的優點。你也可以用傳統的JavaScript來寫出這些東西,但是MooTools把它變得更簡易和善。

MooTools 與繼承<

儘管它名字叫MooTools,它的Class功能並不是真的類別也不是創造一個類別。它的設計模式也許會讓你想起傳統的程式語言,但Class的確是都是跟物件與原型繼承相關的。(很不幸地,用"class"這個字眼是用來描述這些東西最方便的方式,所以在這篇文章中,當我提到"class"的時候,就是指那些會回傳物件的函數,而這些物件就是我要用來"實體化"且繼承自某個原型。)

要建立一個class,你可以把一個物件傳進這個類別構建式,像這樣:

var Human = new Class({
initialize: function(name, age) {
this.name = name;
this.age = age;
},
isAlive: true,
energy: 1,
eat: function() {
this.energy = this.energy + 1; //same as this.energy++
}
});
你把一個物件丟給Class(在上面,我們把一個有"isAlive"跟"eat"成員的物件傳進去),這個物件就會變成任何類別實體(instance of class)的原型。要建立一個實體,你只要:

var bob = new Human("bob", 20); //bob's name is "bob" and he's 20 years old.
現在我們得到一個Human. bob實體,裡面有我們在建立我們自己的Human類別時所定義的屬性。但是重點是bob的那些屬性是透過繼承而來的,當我們參照到bob.eat時,bob並非真的具有這個屬性。JavaScript先看bob,發現他沒有eat這個方法,所以就從繼承鍊找到它,也就是從我們之前建立的Human類別裡面,energy這屬性也是同樣的道理。一開始這看起來有些潛在的壞處;我們並不希望每次bob吃(eat)的時候,每一個被建立的human都會得到一次energy。有一點需要知道的是,當一開始給enegey值的時候,bob會擁有自己的值,我們也不再從原型(prototype)中去尋找值了。所以第一次bob吃(eat)的時候,他會得到自己的energy值(enery=2)。

bob.eat(); //bob.energy == 2
bob的name跟age都是獨有的;在initialize初始化的時候就分配給bob了。

這整個模式看起來可能對你來說有點怪,但是其價值在於我們可以為某種特定模式(pattern)定義功能,然後每次需要使用時便初始化這個東西。每個實體(instance)都有自己的狀態。所以如果我們建立另一個實體,那麼兩個實體個字都會是獨立的,且繼承自同一個基本的模式(pattern)。

var Alice = new Human();
//alice.energy == 1
//bob.energy == 2
當我們要把這種方式擴大時,事情會變得更有趣。

MooTools與繼承

我們再回顧一下jQuery的faq外掛。如果我們要在這個外掛加入更多的功能會如何?如果我們要透過ajax從伺服器端取得問題所相對應的答案內容時該怎做?想像一下如果faq是另一位作者寫的,而我們要在不改變外掛程式碼的前提下增加新功能(不想把程式變成有分支的)。

我們唯一的選擇就是把整份faq程式碼複製(記得,它只是個單一函式),實際上也就是分支。或者是我們可以呼叫這個外掛然後再多增加一些程式碼。如果可以選擇的話,後者看起來較能省去一些麻煩,程式碼看起來會像這樣:

jQuery.fn.ajaxFaq = function(options) {
var settings = jQuery.extend({
//some ajax specific options like the url to request terms from
url: '/getfaq.php'
definitions: 'dd'
}, options);
//"this" is the current context; in this case, the elements we want to turn into faq layouts
$(this).find(settings.definitions).click(function() {
$(this).load(.....); //the logic to load the content from the term
});
this.faq(); //call our original faq plug-in
});
這作法有些缺點。第一個,我們的faq會多執行一次有時會花很久時間的CSS選擇器;我們沒辦法把已經得到的選擇結果傳給第二次需要用到的場合。第二,我們沒辦法把ajax的程式碼插入在faq外掛程式邏輯的中間(例如要改寫顯示faq的規則)。原本的外掛呼叫了可以用特效展開內容的slideToggle。這將會產生問題,因為在ajax得到完整資料之前,這個效果可能會出錯,這邊除了複製一整份faq程式之外沒有甚麼解決方法。

現在我們再來看看MooTool的Human類別,它包含了isAlive跟energy兩個屬性以及一個eat方法。如果我們要建立一個新版本的Human且添加一些額外的屬性要怎做呢?用MooTools的話,我們可以延伸(extend)這個類別:

var Ninja = new Class({
Extends: Human,
initialize: function(name, age, side) {
this.side = side;
this.parent(name, age);
},
energy: 100,
attack: function(target) {
this.energy = this.energy - 5;
target.isAlive = false;
}
});
你可以看到我們增加了許多功能到子類別裡面。這個子類別所有的屬性都Ninjas是獨有。Ninjas初始時得到energy值為100、side屬性以及可以擊殺其他但是會消耗的energy的attac方法。

var bob = new Human('Bob', 25);
var blackNinja = new Ninja('Nin Tendo', 'unknown', 'evil');
//blackNinja.isAlive = true
//blackNinja.name = 'Nin Tendo'
blackNinja.attack(bob);
//bob never had a chance
把程式碼拆解開來看,其中有些有趣的地方值得思考。在Ninja類別裡面有個initialize方法,這個initialize方法會覆蓋掉原本在Human裡面的,但是我們還是會透過this.parent叫用原本的initialize,把兩個原本該有的兩個參數傳過去。更進一步地,我們可以控制新的程式碼要出現在原來程式碼的前面或是後面。我們可以給屬性新的值(像是新的energy值)還可以定義新的功能,想想看這些是不是能在jQuery的faq外掛裡做到。我們可以載入我們自己的ajax然後用滑動效果來展開內容。

MooTools還有另一個模式叫做Mixin。不同於延伸一個類別到其子類別來定義父子關係,你也可以定義一個類別去混合其他類別進而感染(imbue)其他類別的屬性。如這個範例:

var Warrior = new Class({
energy: 100,
kills: 0,
attack: function(target) {
target.isAlive = false;
this.energy = this.energy - 5;
this.kills++;
}
});
這裡我們把Ninja不同於Human的特性拆散開來並且放在一個類別裡。這樣我們就可以在Ninja以外的地方重複使用這些程式碼。我們可以讓Ninja染上戰士(warrior)的特質:

var Ninja = new Class({
Extends: Human,
Implements: Warrior, //can be an array if you want to implement more than one
initialize: function(name, age, side) {
this.side = side;
this.parent(name, age);
}
});
Ninja 依然跟之前的功能完全一樣,而Warrior變成我們可以重複利用的部分:

var Samurai = new Class({
Extends: Human,
Implements: Warrior,
side: 'good'
});
現在我們擁有了武士(Samurai)跟忍者(Ninja),不過我們只需要很少的程式碼就可以定義出Samurai跟Ninja。兩者相同的是它們都有戰士的特質,不同的是武士永遠只會是善良的一方,而忍者可以有搖擺的善惡立場。我們只需要花時間寫出Human跟Warrior類別。當我們能在方法叫用時機以及它們彼此之間相互關係上擁有細微的控制,就能寫出不重複的程式碼而得到三種不同類別。每個我們所建立的實體都有自己的狀態,而程式碼本身也具有很好的可讀性。

現在你對MooTools類別的運作方式有個概括的了解了,讓我們看看把之前寫的jQuery的faq寫成MooTools類別,然後延伸出Ajax功能。

var FAQ = new Class({
//Options is another class provided by MooTools
Implements: Options,
//these are the default options
options: {
terms: 'dt',
definitions: 'dd'
},
initialize: function(container, options) {
//we store a reference to our container
this.container = $(container);
//setOptions is a method provided by the Options mixin
//it merges the options passed in with the defaults
this.setOptions(options);
//we store the terms and definitions
this.terms = this.container.getElements(this.options.terms);
this.definitions = this.container.getElements(this.options.definitions);
//we call our attach method
//by breaking this into its own method
//it makes our class easier to extend
this.attach();
},
attach: function(){
//loop through the terms
this.terms.each(function(term, index) {
//add a click event to each one
term.addEvent('click', function(){
//that calls our toggle method for
//the current index
this.toggle(index);
}, this);
}, this);
},
toggle: function(index){
//toggle open the definition for the given index
this.definitions[index].slide('toggle');
}
});
蛤?好多行程式。即使我們把註解拿掉還是有二十幾行。我之前有說明過,我們可以用跟jQuery版本差不多的行數就寫完這個外掛,那為什麼還要搞得這麼長?就是要把它做得更彈性化。要使用這個類別,只要呼叫他的構建式:

var myFAQ = new FAQ(myContainer);
//and now we can call methods on it if we want:
myFAQ.toggle(2); //toggle the 3rd element
我們可以存取這個實體的方法跟屬性,但是ajax在哪?我們在jQuery版本遇到的問題是我們沒辦法延遲特效的展開時間來等待ajax取得資料完成,在MooTools版本我們沒這困擾了:

FAQ.Ajax = new Class({
//this class inherits the properties of FAQ
Extends: FAQ,
//it also gets a new option in addition to the other defaults
//this one for url, that we're going to append the index of the
//term to; in reality we might make this more robust, but for
//this example it serves the purpose
options: {
url: null;
},
//we're going to cache the results, so if a section is opened
//twice, we won't hit the server for the data
indexesLoaded: [],
toggle: function(index){
//if we've already loaded the definition
if (this.indexesLoaded[index]) {
//just call the previous version of toggle
this.parent(index);
} else {
//otherwise, request the data from the server
new Request.HTML({
update: this.definitions[index],
url: this.options.url + index,
//and when the data is loaded, expand the definition
onComplete: function(){
this.indexesLoaded[index] = true;
this.definitions[index].slide('toggle');
}.bind(this)
}).send();
}
}
});
現在我們有另一個能夠從遠端取得資料的FAQ,整合成了一個可以在資料讀取完之後才展開的新方式(之前在jQuery版做不到的)。而且我們的程式只需要寫多出來的那部分跟其他寥寥數行。這種擴充性允許你建立一整個系列的外掛,可包含了各種不同的變化。同時也意味著你可以沿用別人寫好的外掛,變更你所需要的部分(不用整份程式複製)。這也解釋了為什麼每一種特定的設計模式裡面,你只能找到很少數的MooTools外掛,大多數你所取得的外掛,若不能夠解決你的需求,你都可以自行擴充你所需要的部分。

如同我之前說的,你當然可以用jQuery寫出包含方法與屬性的複雜widgets。大部分的你所寫的這種程式如果是跟DOM無關的邏輯,那麼就會是屬於傳統的JavaScript,但是jQuery沒有提供一個能夠把實體擴充為次類別的系統,也不能幫你用混搭的方式,來使你的程式更容易被重複使用。最後,jQuery的外掛總是被指定到DOM元素中,如果你要寫一個像是處理URL字串的類別,它並沒有一個能記錄這些狀態的架構可用,除非你自己寫一個。

抉擇

jQuery專注於表述性、快速簡易開發以及DOM上面,而MooTools著重於擴充性、繼承、可讀性、重複使用與易維護性。如果把這兩者放在一把尺的兩個極端,jQuery可視為一種好入門且快速得到結果的東西,不過(以我的經驗)也會讓程式變得難以再利用與維護(不過這真的看你怎麼做,這並不是jQuery本身的問題),而MooTools需要較長的學習時間,得要寫較多的程式碼才能得到你要的結果,但是之後更容易重複使用與維護。

更進一步地說,MooTools並沒有涵括每一個你能想像可能需要的功能,當然jQuery也沒有。兩者都盡量給你簡潔的程式碼,讓你去寫你要的plug-in或是擴充功能。其目的不是提供你所有你有可能需要的功能,而是給你一個工具讓你能夠做出你能想像的任何東西。這就是JavaScript強大的地方所在,也是JavaScript framework強大之處,而這兩個frameworks更是擅長於此。MooTools用一個更全面的角度讓你擁有一個在DOM的範圍中為所欲為的工具,但代價是一個較為陡峭的學習曲線。MooTools的延展性與整體性的方法提供你一個涵蓋jQuery功能的大集合,但是jQuery注重在一個靈活的DOM API,同時又不會阻礙你應用JavaScript原生的繼承模型,如果你想要的話,甚至也可以額外使用像是MooTools這樣的類別系統。

這就是為什麼我說兩者都是很棒的選者,我花很大的利器在凸顯出兩者之間在程式設計哲學上的不同以及它們各自的優缺點。我不知道自己是否有在對MooTools的偏好這個事實上維持中立,但是我希望這些文章是有幫助的。非關於你選擇使用哪個framework,而是你現在更了解這兩個framework了,但願。如果你有充裕的時間,我強烈建議你分別用這兩個framework實作一個網站,然後寫下你自己對兩者的見解,也許你的觀點會出現我所未及之處。

摘自:http://jqueryvsmootools.com/index_cn.html

[javascript] 實現陣列 key , value .

PHP:
var foo = [];
foo['alfa'] = "first item";
foo['beta'] = "second item";

for (var key in foo) {
console.log(key);
}

JQUERY:
var a = {};
a['alfa'] = 0;
a['beta'] = 1;
$.each(a, function(key, value) {
alert(key)
});

JAVASCRIPT:
var foo = {};
foo['alfa'] = "first item";
foo['beta'] = "second item";

for (var key in foo) {
console.log(key);
}

Google API 運用 Language




Google AJAX Language API - Basic Translation









結果會輸出: 世界你好

摘自:http://calos-tw.blogspot.com/2010/03/mongodb.html

2010年7月27日 星期二

Gmail is Not Opening – Fix Temporary Server Error Issues

暫時錯誤 (500)

很抱歉,您的 Gmail 帳戶暫時無法使用。如果造成您的不便,敬請見諒。建議您幾分鐘後再試一次。

如果問題仍未解決,請造訪 Gmail 說明中心 »

再試一次 登出


隱藏詳細技術資訊
數值代碼:5

Solution:
Gmail is not opening and while trying to open Gmail it shows a temporary server error. I faced this problem with my primary Gmail account today and this made me to write a post on Gmail server issues. It’s a headache when you can’t open your Gmail and the server serves some temporary error issues. If your Gmail account behaves normally after few time, all is fine, but what if the problem lasts for a longer period?
Once you have entered your Gmail username and password, it will show you nothing, the page won’t get loaded and you will be seeing a blank page. After some 40-50 seconds you will see one page which will be saying : “We’re sorry, but your Gmail account is temporarily unavailable. We apologize for the inconvenience and suggest trying again in a few minutes“. Checkout the below screenshot:

If this problem continues, you can contact Gmail support to look into this matter here. Provide as much accurate information as you can such as an alternative email address to contact you, Gmail address, error type (Oops.. or Temporary Error), error code (e.g. 500, 502, 601, 767 etc), full description of your problem with few other details.
Once you have contacted the support, wait for few more days for the problem to get resolved. Usually they take 3-4 days to fix this problem.

http://mail.google.com/support/bin/request.py?contact_type=gtag_server&ctx=gtag_server&hl=en&status=500&error=93

NoSQL數據庫探討之一- 為什麼要用非關係數據庫?

隨著互聯網web2.0網站的興起,非關係型的數據庫現在成了一個極其熱門的新領域,非關係數據庫產品的發展非常迅速。 而傳統的關係數據庫在應付web2.0網站,特別是超大規模和高並發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,例如:

1、High performance - 對數據庫高並發讀寫的需求
web2.0網站要根據用戶個性化信息來實時生成動態頁面和提供動態信息,所以基本上無法使用動態頁面靜態化技術,因此數據庫並發負載非常高,往往要達到每秒上萬次讀寫請求。 關係數據庫應付上萬次SQL查詢還勉強頂得住,但是應付上萬次SQL寫數據請求,硬盤IO就已經無法承受了。 其實對於普通的BBS網站,往往也存在對高並發寫請求的需求,例如像JavaEye網站的實時統計在線用戶狀態,記錄熱門帖子的點擊次數,投票計數等,因此這是一個相當普遍的需求。

2、Huge Storage - 對海量數據的高效率存儲和訪問的需求
類似Facebook,twitter,Friendfeed這樣的SNS網站,每天用戶產生海量的用戶動態,以Friendfeed為例,一個月就達到了2.5億條用戶動態,對於關係數據庫來說,在一張2.5億條記錄的表裡面進行SQL查詢,效率是極其低下乃至不可忍受的。 再例如大型web網站的用戶登錄系統,例如騰訊,盛大,動輒數以億計的帳號,關係數據庫也很難應付。

3、High Scalability && High Availability- 對數據庫的高可擴展性和高可用性的需求
在基於web的架構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,你的數據庫卻沒有辦法像web server和app server那樣簡單的通過添加更多的硬件和服務節點來擴展性能和負載能力。 對於很多需要提供24小時不間斷服務的網站來說,對數據庫系統進行升級和擴展是非常痛苦的事情,往往需要停機維護和數據遷移,為什麼數據庫不能通過不斷的添加服務器節點來實現擴展呢?

在上面提到的“三高”需求面前,關係數據庫遇到了難以克服的障礙,而對於web2.0網站來說,關係數據庫的很多主要特性卻往往無用武之地,例如:

1、數據庫事務一致性需求
很多web實時系統並不要求嚴格的數據庫事務,對讀一致性的要求很低,有些場合對寫一致性要求也不高。 因此數據庫事務管理成了數據庫高負載下一個沉重的負擔。

2、數據庫的寫實時性和讀實時性需求
對關係數據庫來說,插入一條數據之後立刻查詢,是肯定可以讀出來這條數據的,但是對於很多web應用來說,並不要求這麼高的實時性,比方說我(JavaEye的robbin)發一條消息之後,過幾秒乃至十幾秒之後,我的訂閱者才看到這條動態是完全可以接受的。

3、對複雜的SQL查詢,特別是多表關聯查詢的需求
任何大數據量的web系統,都非常忌諱多個大表的關聯查詢,以及復雜的數據分析類型的複雜SQL報表查詢,特別是SNS類型的網站,從需求以及產品設計角度,就避免了這種情況的產生。 往往更多的只是單表的主鍵查詢,以及單表的簡單條件分頁查詢,SQL的功能被極大的弱化了。

因此,關係數據庫在這些越來越多的應用場景下顯得不那麼合適了,為了解決這類問題的非關係數據庫應運而生,現在這兩年,各種各樣非關係數據庫,特別是鍵值數據庫(Key-Value Store DB)風起雲湧,多得讓人眼花繚亂。 前不久國外剛剛舉辦了NoSQL Conference,各路NoSQL數據庫紛紛亮相,加上未亮相但是名聲在外的,起碼有超過10個開源的NoSQLDB,例如:

Redis,Tokyo Cabinet,Cassandra,Voldemort,MongoDB,Dynomite,HBase,CouchDB,Hypertable, Riak,Tin, Flare, Lightcloud, KiokuDB,Scalaris, Kai, ThruDB, ......

這些NoSQL數據庫,有的是用C/C++編寫的,有的是用Java編寫的,還有的是用Erlang編寫的,每個都有自己的獨到之處,看都看不過來了,我(robbin)也只能從中挑選一些比較有特色,看起來更有前景的產品學習和了解一下。 這些NoSQL數據庫大致可以分為以下的三類:

一、滿足極高讀寫性能需求的Kye-Value數據庫:Redis,Tokyo Cabinet, Flare

高性能Key-Value數據庫的主要特點就是具有極高的並發讀寫性能,Redis,Tokyo Cabinet, Flare,這3個Key-Value DB都是用C編寫的,他們的性能都相當出色,但出了出色的性能,他們還有自己獨特的功能:

1、Redis
Redis是一個很新的項目,剛剛發布了1.0版本。 Redis本質上是一個Key-Value類型的內存數據庫,很像memcached,整個數據庫統統加載在內存當中進行操作,定期通過異步操作把數據庫數據flush到硬盤上進行保存。 因為是純內存操作,Redis的性能非常出色,每秒可以處理超過10萬次讀寫操作,是我知道的性能最快的Key-Value DB。

Redis的出色之處不僅僅是性能,Redis最大的魅力是支持保存List鍊錶和Set集合的數據結構,而且還支持對List進行各種操作,例如從List兩端push和pop數據,取List區間,排序等等,對Set支持各種集合的並集交集操作,此外單個value的最大限制是1GB,不像memcached只能保存1MB的數據,因此Redis可以用來實現很多有用的功能,比方說用他的List來做FIFO雙向鍊錶,實現一個輕量級的高性能消息隊列服務,用他的Set可以做高性能的tag系統等等。 另外Redis也可以對存入的Key-Value設置expire時間,因此也可以被當作一個功能加強版的memcached來用。

Redis的主要缺點是數據庫容量受到物理內存的限制,不能用作海量數據的高性能讀寫,並且它沒有原生的可擴展機制,不具有scale(可擴展)能力,要依賴客戶端來實現分佈式讀寫,因此Redis適合的場景主要局限在較小數據量的高性能操作和運算上。 目前使用Redis的網站有github,Engine Yard。

2、Tokyo Cabinet和Tokoy Tyrant
TC和TT的開發者是日本人Mikio Hirabayashi,主要被用在日本最大的SNS網站mixi.jp上,TC發展的時間最早,現在已經是一個非常成熟的項目,也是Kye-Value數據庫領域最大的熱點,現在被廣泛的應用在很多很多網站上。 TC是一個高性能的存儲引擎,而TT提供了多線程高並發服務器,性能也非常出色,每秒可以處理4-5萬次讀寫操作。

TC除了支持Key-Value存儲之外,還支持保存Hashtable數據類型,因此很像一個簡單的數據庫表,並且還支持基於column的條件查詢,分頁查詢和排序功能,基本上相當於支持單表的基礎查詢功能了,所以可以簡單的替代關係數據庫的很多操作,這也是TC受到大家歡迎的主要原因之一,有一個Ruby的項目miyazakiresistance將TT的hashtable的操作封裝成和ActiveRecord一樣的操作,用起來非常爽。

TC/TT在mixi的實際應用當中,存儲了2000萬條以上的數據,同時支撐了上萬個並發連接,是一個久經考驗的項目。 TC在保證了極高的並發讀寫性能的同時,具有可靠的數據持久化機制,同時還支持類似關係數據庫表結構的hashtable以及簡單的條件,分頁和排序操作,是一個很棒的NoSQL數據庫。

TC的主要缺點是在數據量達到上億級別以後,並發寫數據性能會大幅度下降,NoSQL: If Only It Was That Easy提到,他們發現在TC裡面插入1.6億條2-20KB數據的時候,寫入性能開始急劇下降。 看來是當數據量上億條的時候,TC性能開始大幅度下降,從TC作者自己提供的mixi數據來看,至少上千萬條數據量的時候還沒有遇到這麼明顯的寫入性能瓶頸。

這個是Tim Yang做的一個Memcached,Redis和Tokyo Tyrant的簡單的性能評測,僅供參考

3、Flare
TC是日本第一大SNS網站mixi開發的,而Flare是日本第二大SNS網站green.jp開發的,有意思吧。 Flare簡單的說就是給TC添加了scale功能。 他替換掉了TT部分,自己另外給TC寫了網絡服務器,Flare的主要特點就是支持scale能力,他在網絡服務端之前添加了一個node server,來管理後端的多個服務器節點,因此可以動態添加數據庫服務節點,刪除服務器節點,也支持failover。 如果你的使用場景必須要讓TC可以scale,那麼可以考慮flare。

flare唯一的缺點就是他只支持memcached協議,因此當你使用flare的時候,就不能使用TC的table數據結構了,只能使用TC的key-value數據結構存儲。

二、滿足海量存儲需求和訪問的面向文檔的數據庫:MongoDB,CouchDB

面向文檔的非關係數據庫主要解決的問題不是高性能的並發讀寫,而是保證海量數據存儲的同時,具有良好的查詢性能。 MongoDB是用C++開發的,而CouchDB則是Erlang開發的:

1、MongoDB
MongoDB是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係數據庫的。 他支持的數據結構非常鬆散,是類似json的bjson格式,因此可以存儲比較複雜的數據類型。 Mongo最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。

Mongo主要解決的是海量數據的訪問效率問題,根據官方的文檔,當數據量達到50GB以上的時候,Mongo的數據庫訪問速度是MySQL的10倍以上。 Mongo的並發讀寫效率不是特別出色,根據官方提供的性能測試表明,大約每秒可以處理0.5萬-1.5次讀寫請求。 對於Mongo的並發讀寫性能,我(robbin)也打算有空的時候好好測試一下。

因為Mongo主要是支持海量數據存儲的,所以Mongo還自帶了一個出色的分佈式文件系統GridFS,可以支持海量的數據存儲,但我也看到有些評論認為GridFS性能不佳,這一點還是有待親自做點測試來驗證了。

最後由於Mongo可以支持複雜的數據結構,而且帶有強大的數據查詢功能,因此非常受到歡迎,很多項目都考慮用MongoDB來替代MySQL來實現不是特別複雜的Web應用,比方說why we migrated from MySQL to MongoDB就是一個真實的從MySQL遷移到MongoDB的案例,由於數據量實在太大,所以遷移到了Mongo上面,數據查詢的速度得到了非常顯著的提升。

MongoDB也有一個ruby的項目MongoMapper,是模仿Merb的DataMapper編寫的MongoDB的接口,使用起來非常簡單,幾乎和DataMapper一模一樣,功能非常強大易用。

2、CouchDB
CouchDB現在是一個非常有名氣的項目,似乎不用多介紹了。 但是我卻對CouchDB沒有什麼興趣,主要是因為CouchDB僅僅提供了基於HTTP REST的接口,因此CouchDB單純從並發讀寫性能來說,是非常糟糕的,這讓我立刻拋棄了對CouchDB的興趣。

三、滿足高可擴展性和可用性的面向分佈式計算的數據庫:Cassandra,Voldemort

面向scale能力的數據庫其實主要解決的問題領域和上述兩類數據庫還不太一樣,它首先必須是一個分佈式的數據庫系統,由分佈在不同節點上面的數據庫共同構成一個數據庫服務系統,並且根據這種分佈式架構來提供online的,具有彈性的可擴展能力,例如可以不停機的添加更多數據節點,刪除數據節點等等。 因此像Cassandra常常被看成是一個開源版本的Google BigTable的替代品。 Cassandra和Voldemort都是用Java開發的:

1、Cassandra
Cassandra項目是Facebook在2008年開源出來的,隨後Facebook自己使用Cassandra的另外一個不開源的分支,而開源出來的Cassandra主要被Amazon的Dynamite團隊來維護,並且Cassandra被認為是Dynamite2.0版本。 目前除了Facebook之外,twitter和digg.com都在使用Cassandra。

Cassandra的主要特點就是它不是一個數據庫,而是由一堆數據庫節點共同構成的一個分佈式網絡服務,對Cassandra的一個寫操作,會被複製到其他節點上去,對Cassandra的讀操作,也會被路由到某個節點上面去讀取。 對於一個Cassandra群集來說,擴展性能是比較簡單的事情,只管在群集裡面添加節點就可以了。 我看到有文章說Facebook的Cassandra群集有超過100台服務器構成的數據庫群集。

Cassandra也支持比較豐富的數據結構和功能強大的查詢語言,和MongoDB比較類似,查詢功能比MongoDB稍弱一些,twitter的平台架構部門領導Evan Weaver寫了一篇文章介紹Cassandra:http://blog. evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra/,有非常詳細的介紹。

Cassandra以單個節點來衡量,其節點的並發讀寫性能不是特別好,有文章說評測下來Cassandra每秒大約不到1萬次讀寫請求,我也看到一些對這個問題進行質疑的評論,但是評價Cassandra單個節點的性能是沒有意義的,真實的分佈式數據庫訪問系統必然是n多個節點構成的系統,其並發性能取決於整個系統的節點數量,路由效率,而不僅僅是單節點的並發負載能力。

2、Voldemort
Voldemort是個和Cassandra類似的面向解決scale問題的分佈式數據庫系統,Cassandra來自於Facebook這個SNS網站,而Voldemort則來自於Linkedin這個SNS網站。 說起來SNS網站為我們貢獻了n多的NoSQL數據庫,例如Cassandar,Voldemort,Tokyo Cabinet,Flare等等。 Voldemort的資料不是很多,因此我沒有特別仔細去鑽研,Voldemort官方給出Voldemort的並發讀寫性能也很不錯,每秒超過了1.5萬次讀寫。

從Facebook開發Cassandra,Linkedin開發Voldemort,我們也可以大致看出國外大型SNS網站對於分佈式數據庫,特別是對數據庫的scale能力方面的需求是多麼殷切。 前面我(robbin)提到,web應用的架構當中,web層和app層相對來說都很容易橫向擴展,唯有數據庫是單點的,極難scale,現在Facebook和Linkedin在非關係型數據庫的分佈式方面探索了一條很好的方向,這也是為什麼現在Cassandra這麼熱門的主要原因。

如今,NoSQL數據庫是個令人很興奮的領域,總是不斷有新的技術新的產品冒出來,改變我們已經形成的固有的技術觀念,我自己(robbin)稍微了解了一些,就感覺自己深深的沉迷進去了,可以說NoSQL數據庫領域也是博大精深的,我(robbin)也只能淺嚐輒止,我(robbin)寫這篇文章既是自己一點點鑽研心得,也是拋磚引玉,希望吸引對這個領域有經驗的朋友來討論和交流。

從我(robbin)個人的興趣來說,分佈式數據庫系統不是我能實際用到的技術,因此不打算花時間深入,而其他兩個數據領域(高性能NoSQLDB和海量存儲NoSQLDB)都是我很感興趣的,特別是Redis,TT/TC和MongoDB這3個NoSQL數據庫,因此我接下來將寫三篇文章分別詳細介紹這3個數據庫。

摘自:http://robbin.javaeye.com/blog/524977

2010年7月26日 星期一

將SelectBar控制長度的方法

select bar 在「未展開時的寬」,和「展開後的寬」可以設定不一樣
這是怎麼做到的,如果用這種方法,在我在設計上可以省很多空間又美觀…

方法 :

wibiya widget