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 元 / 學期
2010年7月28日 星期三
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
每天在 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);
}
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
結果會輸出: 世界你好
摘自: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
很抱歉,您的 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
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日 星期一
有趣,Google產品經理筆試題&面試題
以下內容整理於網路,可能有些問題並不是來自Google,當時的話很值得思考。 ~
1、一輛校車能裝下多少個高爾夫球?
2、如果讓你清洗西雅圖市所有的窗戶,你會對此索價多少?
3、在一個重男輕女的國家裡,每家每戶都想生男孩。 若一戶人家生了一個女孩,便會再生一個,直到生下的是男孩為止。 請問這個國家的男女比例是多少?
4、全世界共有多少位鋼琴調音師?
5、下水道井蓋為什麼是圓的?
6、為舊金山市設計一個緊急疏散方案。
7、時鐘的指針一天內總共會重合多少次?
8、你有8個大小一樣的球,其中7個重量相同,只有一個略重一些。 給你一個天平,而且只准稱兩次,如何找出重量不同的那個球?
9、向你8歲的侄子或外甥解釋什麼是數據庫,只能用三個句子。
10、你縮小到只有一枚五分硬幣那麼高,你的質量也成比例縮小以保持原有密度不變。 隨後你被扔到一個空的玻璃攪拌器裡,攪拌刀片將在60秒後開始運轉,你該怎麼辦?
11、村子裡有100對夫妻,其中每個丈夫都瞞著自己的妻子偷情。 村里的每個妻子都能立即發現除自己丈夫之外的其他男人是否偷情,唯獨不知道她自己的丈夫到底有沒有偷情。 村里的規矩不容忍通姦。 任何一個妻子,一旦能證明自己的男人偷情,就必須當天把他殺死。 村里的女人全都嚴格照此規矩辦事。 一天,女頭領出來宣布,村里至少有一個丈夫偷情。 請問接下來會發生什麼事?
12、假設在一段高速公路上,30分鐘之內見到汽車經過的概率是95%。 那麼,在10分鐘內見到汽車經過的概率是多少?
13、有四個人要在夜裡穿過一條懸索橋回到宿營地。 可是他們只有一支手電,電池只夠再亮17分鐘。 過橋必須要有手電,否則太危險。 橋最多只能承受兩個人同時通過的重量。 這四個人的過橋速度都不一樣:一個需要1分鐘,一個需要2分鐘,一個需要5分鐘,還有一個需要10分鐘。 他們如何才能在17分鐘之內全部過橋?
14、 如果你看到時鐘上面的時間是3:15,那麼其時針和分針之間的角度是多少?
15、將一根木條折成3段之後,可以形成一個三角形的概率有多大?
16、有兩位盲人,他們都各自買了兩對黑襪和兩對白襪,八對襪了的布質、大小完全相同,而每對襪了都有一張商標紙連著。 兩位盲人不小心將八對襪了混在一起。 他們每人怎樣才能取回黑襪和白襪各兩對呢?
17、有三個人去住旅館,住三間房,每一間房$10元,於是他們一共付給老闆$30,第二天,老闆覺得三間房只需要$25元就夠了於是叫小弟退回$5給三位客人,誰知小弟貪心,只退回每人$1,自己偷偷拿了$2,這樣一來便等於那三位客人每人各花了九元,於是三個人一共花了$27,再加上小弟獨吞了不$2,總共是$29。 可是當初他們三個人一共付出$30那麼還有$1呢?
18、有一輛火車以每小時15公里的速度離開洛杉磯直奔紐約,另一輛火車以每小時20公里的速度從紐約開往洛杉磯。 如果有一隻鳥,以30公里每小時的速度和兩輛火車同時啟動,從洛杉磯出發,碰到另一輛車後返回,依次在兩輛火車來回飛行,直到兩輛火車相遇,請問,這隻小鳥飛行了多長距離?
19、一個經理有三個女兒,三個女兒的年齡加起來等於13,三個女兒的年齡乘起來等於經理自己的年齡,有一個下屬已知道經理的年齡,但仍不能確定經理三個女兒的年齡,這時經理說只有一個女兒的頭髮是黑的,然後這個下屬就知道了經理三個女兒的年齡。 請問三個女兒的年齡分別是多少? 為什麼?
20、你有兩個罐子,50個紅色彈球,50個藍色彈球,隨機選出一個罐子,隨機選取出一個彈球放入罐子,怎麼給紅色彈球最大的選中機會? 在你的計劃中,得到紅球的準確機率是多少?
21、你有一桶果凍,其中有黃色,綠色,紅色三種,閉上眼睛,抓取兩個同種顏色的果凍。 抓取多少個就可以確定你肯定有兩個同一顏色的果凍?
22、對一批編號為1~100,全部開關朝上(開)的燈進行以下操作:凡是1的倍數反方向撥一次開關;2的倍數反方向又撥一次開關;3的倍數反方向又撥一次開關……問:最後為關熄狀態的燈的編號。
23、想像你在鏡子前,請問,為什麼鏡子中的影像可以顛倒左右,卻不能顛倒上下?
24、一群人開舞會,每人頭上都戴著一頂帽子。 帽子只有黑白兩種,黑的至少有一頂。 每個人都能看到其它人帽子的顏色,卻看不到自己的。 主持人先讓大家看看別人頭上戴的是什么帽子,然後關燈,如果有人認為自己戴的是黑帽子,就打自己一個耳光。 第一次關燈,沒有聲音。 於是再開燈,大家再看一遍,關燈時仍然鴉雀無聲。 一直到第三次關燈,才有劈劈啪啪打耳光的聲音響起。 問有多少人戴著黑帽子?
25、有兩根不均勻分佈的香,香燒完的時間是一個小時,你能用什麼方法來確定一段15分鐘的時間?
26、兩個圓環,半徑分別是1和2,小圓在大圓內部繞大圓圓周一周,問小圓自身轉了幾週? 如果在大圓的外部,小圓自身轉幾周呢?
27、1元錢一瓶汽水,喝完後兩個空瓶換一瓶汽水,問:你有20元錢,最多可以喝到幾瓶汽水?
28、100白球100黑球,每次拿出兩個,如白+白,則放一個黑球進去,黑+黑,也放個黑球進去,白+黑,放個白球進去,直到只剩下一個球為止,問剩下黑球的概率。
29、10個人排隊戴帽子,10個黃帽子,9個藍帽子,戴好後後面的人可以看見前面所有人的帽子,然後從後面問起,問自己頭上的帽子,結果一直問了9個人都說不知道,而最前面的人卻知道自己頭上的帽子的顏色,問是什麼顏色,為什麼。
30、正方形邊長為1,以各個頂點半徑為1做弧,在正方形中間有一個公共區域,求面積。
31、1000!有幾位數,為什麼3.11的三次方是1331,12的三次方是1728,請問哪個數的三次方是1442897?
32、在一次酒會上有人作瞭如下統計:參加酒會的人彼此都碰了杯子,此次酒會共碰杯子45 次,請問有多少人參加了酒會?
33、一個人的假期有13天下雨,12天上午晴天,11天下午晴天,任何一天上午下午不會同時下雨,請問這個人的假期有多少天?
34、一隻蝸牛從井底爬到井口,每天白天蝸牛要睡覺,晚上才出來活動,一個晚上蝸牛可以向上爬3尺,但是白天睡覺的時候會往下滑2尺,井深10尺,問蝸牛幾天可以爬出來?
35、在一個平面上畫1999條直線最多能將這一平面劃分成多少個部分?
36、在太平洋的一個小島上生活著土人,他們不願意被外人打擾,一天,一個探險家到了島上,被土人抓住,土人的祭司告訴他,你臨死前還可以有一個機會留下一句話,如果這句話是真的,你將被燒死,是假的,你將被五馬分屍,可憐的探險家如何才能活下來?
37、怎樣種四棵樹使得任意兩棵樹的距離相等。
38、27個小運動員在參加完比賽后,口渴難耐,去小店買飲料,飲料店搞促銷,憑三個空瓶可以再換一瓶,他們最少買多少瓶飲料才能保證一人一瓶?
39、有兩根不均勻分佈的香,每根香燒完的時間是一個小時,你能用什麼方法來確定一段15分鐘的時間?
40、你讓工人為你工作7天,給工人的回報是一根金條。 金條平分成相連的7段,你必須在每天結束時給他們一段金條,如果只許你兩次把金條弄斷,你如何給你的工人付費?
41、5個囚犯,分別按1-5號在裝有100顆綠豆的麻袋抓綠豆,規定每人至少抓一顆,而抓得最多和最少的人將被處死,而且,他們之間不能交流,但在抓的時候,可以摸出剩下的豆子數。 問他們中誰的存活機率最大?
42、據說有人給酒肆的老闆娘出了一個難題:此人明明知道店裡只有兩個舀酒的勺子,分別能舀7兩和11兩酒,卻硬要老闆娘賣給他2兩酒。 聰明的老闆娘毫不含糊,用這兩個勺子在酒缸裡舀酒,並倒來倒去,居然量出了2兩酒,聰明的你能做到嗎?
43、已知: 每個飛機只有一個油箱, 飛機之間可以相互加油(注意是相互,沒有加油機) 一箱油可供一架飛機繞地球飛半圈, 問題:為使至少一架飛機繞地球一圈回到起飛時的飛機場,至少需要出動幾架飛機? (所有飛機從同一機場起飛,而且必須安全返回機場,不允許中途降落,中間沒有飛機場)
44、門外三個開關分別對應室內三盞燈,線路良好,在門外控制開關時候不能看到室內燈的情況,現在只允許進門一次,確定開關和燈的對應關係?
45、一個岔路口分別通向誠實國和說謊國。 來了兩個人,已知一個是誠實國的,另一個是說謊國的。 誠實國永遠說實話,說謊國永遠說謊話。 現在你要去說謊國,但不知道應該走哪條路,需要問這兩個人。 請問應該怎麼問?
46、在一天的24小時之中,時鐘的時針、分針和秒針完全重合在一起的時候有幾次? 都分別是什麼時間? 你怎樣算出來的?
摘自:http://www.biaodianfu.com/google-pm-interview.html
1、一輛校車能裝下多少個高爾夫球?
2、如果讓你清洗西雅圖市所有的窗戶,你會對此索價多少?
3、在一個重男輕女的國家裡,每家每戶都想生男孩。 若一戶人家生了一個女孩,便會再生一個,直到生下的是男孩為止。 請問這個國家的男女比例是多少?
4、全世界共有多少位鋼琴調音師?
5、下水道井蓋為什麼是圓的?
6、為舊金山市設計一個緊急疏散方案。
7、時鐘的指針一天內總共會重合多少次?
8、你有8個大小一樣的球,其中7個重量相同,只有一個略重一些。 給你一個天平,而且只准稱兩次,如何找出重量不同的那個球?
9、向你8歲的侄子或外甥解釋什麼是數據庫,只能用三個句子。
10、你縮小到只有一枚五分硬幣那麼高,你的質量也成比例縮小以保持原有密度不變。 隨後你被扔到一個空的玻璃攪拌器裡,攪拌刀片將在60秒後開始運轉,你該怎麼辦?
11、村子裡有100對夫妻,其中每個丈夫都瞞著自己的妻子偷情。 村里的每個妻子都能立即發現除自己丈夫之外的其他男人是否偷情,唯獨不知道她自己的丈夫到底有沒有偷情。 村里的規矩不容忍通姦。 任何一個妻子,一旦能證明自己的男人偷情,就必須當天把他殺死。 村里的女人全都嚴格照此規矩辦事。 一天,女頭領出來宣布,村里至少有一個丈夫偷情。 請問接下來會發生什麼事?
12、假設在一段高速公路上,30分鐘之內見到汽車經過的概率是95%。 那麼,在10分鐘內見到汽車經過的概率是多少?
13、有四個人要在夜裡穿過一條懸索橋回到宿營地。 可是他們只有一支手電,電池只夠再亮17分鐘。 過橋必須要有手電,否則太危險。 橋最多只能承受兩個人同時通過的重量。 這四個人的過橋速度都不一樣:一個需要1分鐘,一個需要2分鐘,一個需要5分鐘,還有一個需要10分鐘。 他們如何才能在17分鐘之內全部過橋?
14、 如果你看到時鐘上面的時間是3:15,那麼其時針和分針之間的角度是多少?
15、將一根木條折成3段之後,可以形成一個三角形的概率有多大?
16、有兩位盲人,他們都各自買了兩對黑襪和兩對白襪,八對襪了的布質、大小完全相同,而每對襪了都有一張商標紙連著。 兩位盲人不小心將八對襪了混在一起。 他們每人怎樣才能取回黑襪和白襪各兩對呢?
17、有三個人去住旅館,住三間房,每一間房$10元,於是他們一共付給老闆$30,第二天,老闆覺得三間房只需要$25元就夠了於是叫小弟退回$5給三位客人,誰知小弟貪心,只退回每人$1,自己偷偷拿了$2,這樣一來便等於那三位客人每人各花了九元,於是三個人一共花了$27,再加上小弟獨吞了不$2,總共是$29。 可是當初他們三個人一共付出$30那麼還有$1呢?
18、有一輛火車以每小時15公里的速度離開洛杉磯直奔紐約,另一輛火車以每小時20公里的速度從紐約開往洛杉磯。 如果有一隻鳥,以30公里每小時的速度和兩輛火車同時啟動,從洛杉磯出發,碰到另一輛車後返回,依次在兩輛火車來回飛行,直到兩輛火車相遇,請問,這隻小鳥飛行了多長距離?
19、一個經理有三個女兒,三個女兒的年齡加起來等於13,三個女兒的年齡乘起來等於經理自己的年齡,有一個下屬已知道經理的年齡,但仍不能確定經理三個女兒的年齡,這時經理說只有一個女兒的頭髮是黑的,然後這個下屬就知道了經理三個女兒的年齡。 請問三個女兒的年齡分別是多少? 為什麼?
20、你有兩個罐子,50個紅色彈球,50個藍色彈球,隨機選出一個罐子,隨機選取出一個彈球放入罐子,怎麼給紅色彈球最大的選中機會? 在你的計劃中,得到紅球的準確機率是多少?
21、你有一桶果凍,其中有黃色,綠色,紅色三種,閉上眼睛,抓取兩個同種顏色的果凍。 抓取多少個就可以確定你肯定有兩個同一顏色的果凍?
22、對一批編號為1~100,全部開關朝上(開)的燈進行以下操作:凡是1的倍數反方向撥一次開關;2的倍數反方向又撥一次開關;3的倍數反方向又撥一次開關……問:最後為關熄狀態的燈的編號。
23、想像你在鏡子前,請問,為什麼鏡子中的影像可以顛倒左右,卻不能顛倒上下?
24、一群人開舞會,每人頭上都戴著一頂帽子。 帽子只有黑白兩種,黑的至少有一頂。 每個人都能看到其它人帽子的顏色,卻看不到自己的。 主持人先讓大家看看別人頭上戴的是什么帽子,然後關燈,如果有人認為自己戴的是黑帽子,就打自己一個耳光。 第一次關燈,沒有聲音。 於是再開燈,大家再看一遍,關燈時仍然鴉雀無聲。 一直到第三次關燈,才有劈劈啪啪打耳光的聲音響起。 問有多少人戴著黑帽子?
25、有兩根不均勻分佈的香,香燒完的時間是一個小時,你能用什麼方法來確定一段15分鐘的時間?
26、兩個圓環,半徑分別是1和2,小圓在大圓內部繞大圓圓周一周,問小圓自身轉了幾週? 如果在大圓的外部,小圓自身轉幾周呢?
27、1元錢一瓶汽水,喝完後兩個空瓶換一瓶汽水,問:你有20元錢,最多可以喝到幾瓶汽水?
28、100白球100黑球,每次拿出兩個,如白+白,則放一個黑球進去,黑+黑,也放個黑球進去,白+黑,放個白球進去,直到只剩下一個球為止,問剩下黑球的概率。
29、10個人排隊戴帽子,10個黃帽子,9個藍帽子,戴好後後面的人可以看見前面所有人的帽子,然後從後面問起,問自己頭上的帽子,結果一直問了9個人都說不知道,而最前面的人卻知道自己頭上的帽子的顏色,問是什麼顏色,為什麼。
30、正方形邊長為1,以各個頂點半徑為1做弧,在正方形中間有一個公共區域,求面積。
31、1000!有幾位數,為什麼3.11的三次方是1331,12的三次方是1728,請問哪個數的三次方是1442897?
32、在一次酒會上有人作瞭如下統計:參加酒會的人彼此都碰了杯子,此次酒會共碰杯子45 次,請問有多少人參加了酒會?
33、一個人的假期有13天下雨,12天上午晴天,11天下午晴天,任何一天上午下午不會同時下雨,請問這個人的假期有多少天?
34、一隻蝸牛從井底爬到井口,每天白天蝸牛要睡覺,晚上才出來活動,一個晚上蝸牛可以向上爬3尺,但是白天睡覺的時候會往下滑2尺,井深10尺,問蝸牛幾天可以爬出來?
35、在一個平面上畫1999條直線最多能將這一平面劃分成多少個部分?
36、在太平洋的一個小島上生活著土人,他們不願意被外人打擾,一天,一個探險家到了島上,被土人抓住,土人的祭司告訴他,你臨死前還可以有一個機會留下一句話,如果這句話是真的,你將被燒死,是假的,你將被五馬分屍,可憐的探險家如何才能活下來?
37、怎樣種四棵樹使得任意兩棵樹的距離相等。
38、27個小運動員在參加完比賽后,口渴難耐,去小店買飲料,飲料店搞促銷,憑三個空瓶可以再換一瓶,他們最少買多少瓶飲料才能保證一人一瓶?
39、有兩根不均勻分佈的香,每根香燒完的時間是一個小時,你能用什麼方法來確定一段15分鐘的時間?
40、你讓工人為你工作7天,給工人的回報是一根金條。 金條平分成相連的7段,你必須在每天結束時給他們一段金條,如果只許你兩次把金條弄斷,你如何給你的工人付費?
41、5個囚犯,分別按1-5號在裝有100顆綠豆的麻袋抓綠豆,規定每人至少抓一顆,而抓得最多和最少的人將被處死,而且,他們之間不能交流,但在抓的時候,可以摸出剩下的豆子數。 問他們中誰的存活機率最大?
42、據說有人給酒肆的老闆娘出了一個難題:此人明明知道店裡只有兩個舀酒的勺子,分別能舀7兩和11兩酒,卻硬要老闆娘賣給他2兩酒。 聰明的老闆娘毫不含糊,用這兩個勺子在酒缸裡舀酒,並倒來倒去,居然量出了2兩酒,聰明的你能做到嗎?
43、已知: 每個飛機只有一個油箱, 飛機之間可以相互加油(注意是相互,沒有加油機) 一箱油可供一架飛機繞地球飛半圈, 問題:為使至少一架飛機繞地球一圈回到起飛時的飛機場,至少需要出動幾架飛機? (所有飛機從同一機場起飛,而且必須安全返回機場,不允許中途降落,中間沒有飛機場)
44、門外三個開關分別對應室內三盞燈,線路良好,在門外控制開關時候不能看到室內燈的情況,現在只允許進門一次,確定開關和燈的對應關係?
45、一個岔路口分別通向誠實國和說謊國。 來了兩個人,已知一個是誠實國的,另一個是說謊國的。 誠實國永遠說實話,說謊國永遠說謊話。 現在你要去說謊國,但不知道應該走哪條路,需要問這兩個人。 請問應該怎麼問?
46、在一天的24小時之中,時鐘的時針、分針和秒針完全重合在一起的時候有幾次? 都分別是什麼時間? 你怎樣算出來的?
摘自:http://www.biaodianfu.com/google-pm-interview.html
2010年7月25日 星期日
分析httpd的accesslog排列出访问前10的ip地址
日志格式:
192.168.10.234 - - [24/Sep/2009:10:35:58 +0800] "GET /svnroot/platform/branches/1.0sp1/operator HTTP/1.1" 401 470 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2; MAXTHON 2.0)"
命令:
cat svn_access.log |awk '{print $1}'|sort|uniq -c|sort -nr|head -n 10
摘自:http://dev.firnow.com/course/6_system/linux/Linuxjs/20090925/177116.html
192.168.10.234 - - [24/Sep/2009:10:35:58 +0800] "GET /svnroot/platform/branches/1.0sp1/operator HTTP/1.1" 401 470 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2; MAXTHON 2.0)"
命令:
cat svn_access.log |awk '{print $1}'|sort|uniq -c|sort -nr|head -n 10
摘自:http://dev.firnow.com/course/6_system/linux/Linuxjs/20090925/177116.html
用 Apache 拒絕網路流氓的騷擾
Google, Yahoo 的搜尋引擎之所以可以搜尋到很多資料,是因為他們時時刻刻都派著 “robot” 在網路上巡邏,Google 的叫 googlebot, MSN 叫 msnbot, Yahoo! 叫 Yahoo Slurp 等等,任務就是捉新的網頁或更新的網頁回去資料中心. 為了隱私之類的原因,國際組織訂有規則,規範 robot 的行為 — 基本上是 robot 要先參考網站根目錄的一個 robots.txt 的檔案,內容寫著 robot 的名稱及禁止捉取的目錄或檔案,例如:
User-agent: abc
Disallow: /not_for_abc/
User-agent: *
Disallow: /secret/
意思是禁止 abc 這個 robot 捉 /not_for_abc/ 目錄,及禁止所有的 robots 捉 /secret/ 目錄. 網站管理者理論上可以將不喜歡的 robot,或是禁止 robot 捉取的目錄或檔案,寫在這個檔案中.
但是這個只防君子不防小人,碰到網路流氓就沒轍了,有些搜尋引擎的 robot 根本不看網站的 robots.txt,就一路抓下去,實在另人髮指. 網路流氓是什麼,就是這些不遵守遊戲規則,到處亂捉別人網站的內容的壞蛋,這樣會造成網站的流量增加,也就是費用的增加,或是不想被搜尋的資料也被捉走了,侵犯網站的隱私. 很可惡是吧. 下面是幾個例子:
iaskspider 是「愛問」屬於中國新浪網的 robot,完全不管 robots.txt
60.28.164.87 - - [06/Jan/2007:06:28:47 +0800] "GET /wp/archives/2005/08/13/12/46/48/ HTTP/1.0" 200 20969 "-" "Mozilla/5.0 (compatible; iaskspider/1.0; MSIE 6.0)"
60.28.164.87 - - [06/Jan/2007:06:29:34 +0800] "GET /wp/archives/2005/08/13/21/28/00/ HTTP/1.0" 200 19601 "-" "Mozilla/5.0 (compatible; iaskspider/1.0; MSIE 6.0)"
60.28.164.87 - - [06/Jan/2007:06:31:45 +0800] "GET /wp/archives/2005/07/06/22/47/17/ HTTP/1.0" 200 39200 "-" "Mozilla/5.0 (compatible; iaskspider/1.0; MSIE 6.0)"
QihooBot,也是來自中國的「奇虎網」,也是垃圾一個,浪費一堆頻寬,來源 IP 有很多個:
220.181.34.162 - - [03/Jan/2007:11:36:27 +0800] "GET /wp/feed/ HTTP/1.1" 200 21947 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0)"
220.181.34.170 - - [03/Jan/2007:11:38:14 +0800] "GET /wp/archives/2006/12/ HTTP/1.1" 200 5373 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0)"
220.181.34.177 - - [03/Jan/2007:11:38:30 +0800] "GET /wp/archives/category/childtalking/ HTTP/1.1" 200 6554 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0)"
另有 larbin,iearthworm,yodaoice,lanshanbot,Outfoxbot 等等一堆,到網路上徵信一下,這些通通不是什麼好東西,還有一個 WebClipping.com 不知是好人壞人…
碰到這種網路流氓,說實在的也沒什麼積極的辦法,不能叫網路警察把它捉起來...不過消極的辦法還是有的,把網站門戶看好 — Apache 可以擋住特定 IP,但因為 robots 大多有多重 IP,過濾壞蛋的姓名比較有效,可以用 BrowserMatchNoCase 來過濾,用法像是:
Order allow,deny
Allow from all
BrowserMatchNoCase "iaskspider" badguy
BrowserMatchNoCase "QihooBot" badguy
BrowserMatchNoCase "larbin" badguy
deny from env=badguy
如此,它們就會收到 Apache 丟回 403 碼:Forbidden
但是,有些更沒品的還會隱姓埋名,不敢用真面目見人的…
摘自:http://ying.homedns.org/wp/2007/02/190/
User-agent: abc
Disallow: /not_for_abc/
User-agent: *
Disallow: /secret/
意思是禁止 abc 這個 robot 捉 /not_for_abc/ 目錄,及禁止所有的 robots 捉 /secret/ 目錄. 網站管理者理論上可以將不喜歡的 robot,或是禁止 robot 捉取的目錄或檔案,寫在這個檔案中.
但是這個只防君子不防小人,碰到網路流氓就沒轍了,有些搜尋引擎的 robot 根本不看網站的 robots.txt,就一路抓下去,實在另人髮指. 網路流氓是什麼,就是這些不遵守遊戲規則,到處亂捉別人網站的內容的壞蛋,這樣會造成網站的流量增加,也就是費用的增加,或是不想被搜尋的資料也被捉走了,侵犯網站的隱私. 很可惡是吧. 下面是幾個例子:
iaskspider 是「愛問」屬於中國新浪網的 robot,完全不管 robots.txt
60.28.164.87 - - [06/Jan/2007:06:28:47 +0800] "GET /wp/archives/2005/08/13/12/46/48/ HTTP/1.0" 200 20969 "-" "Mozilla/5.0 (compatible; iaskspider/1.0; MSIE 6.0)"
60.28.164.87 - - [06/Jan/2007:06:29:34 +0800] "GET /wp/archives/2005/08/13/21/28/00/ HTTP/1.0" 200 19601 "-" "Mozilla/5.0 (compatible; iaskspider/1.0; MSIE 6.0)"
60.28.164.87 - - [06/Jan/2007:06:31:45 +0800] "GET /wp/archives/2005/07/06/22/47/17/ HTTP/1.0" 200 39200 "-" "Mozilla/5.0 (compatible; iaskspider/1.0; MSIE 6.0)"
QihooBot,也是來自中國的「奇虎網」,也是垃圾一個,浪費一堆頻寬,來源 IP 有很多個:
220.181.34.162 - - [03/Jan/2007:11:36:27 +0800] "GET /wp/feed/ HTTP/1.1" 200 21947 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0)"
220.181.34.170 - - [03/Jan/2007:11:38:14 +0800] "GET /wp/archives/2006/12/ HTTP/1.1" 200 5373 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0)"
220.181.34.177 - - [03/Jan/2007:11:38:30 +0800] "GET /wp/archives/category/childtalking/ HTTP/1.1" 200 6554 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; QihooBot 1.0)"
另有 larbin,iearthworm,yodaoice,lanshanbot,Outfoxbot 等等一堆,到網路上徵信一下,這些通通不是什麼好東西,還有一個 WebClipping.com 不知是好人壞人…
碰到這種網路流氓,說實在的也沒什麼積極的辦法,不能叫網路警察把它捉起來...不過消極的辦法還是有的,把網站門戶看好 — Apache 可以擋住特定 IP,但因為 robots 大多有多重 IP,過濾壞蛋的姓名比較有效,可以用 BrowserMatchNoCase 來過濾,用法像是:
Order allow,deny
Allow from all
BrowserMatchNoCase "iaskspider" badguy
BrowserMatchNoCase "QihooBot" badguy
BrowserMatchNoCase "larbin" badguy
deny from env=badguy
如此,它們就會收到 Apache 丟回 403 碼:Forbidden
但是,有些更沒品的還會隱姓埋名,不敢用真面目見人的…
摘自:http://ying.homedns.org/wp/2007/02/190/
2010年7月23日 星期五
SPEED UP MAC OS X LEOPARD
After a year and a half of running Mac OS X Leopard things have become extraordinarily slow on my MacBook Pro. After googling how to speed up Mac OS X Leopard I have decided to write my own brief tutorial on a handful of things you can do to effectively increase the performance of OS X. This is meant as a programmer’s quick reference guide so if you are not technically savvy you may want to google “performance tune mac os x” for more verbose explanations.
THE 15 BEST MAC PERFORMANCE TUNING APPLICATIONS AND TIPS
Disable Dashboard Widgets. Each dashboard widget you enable consumes both processing power and valuable memory. To disable widgets and speed up your mac follow these steps:
Open up terminal.app located in Applications > Utilities > Terminal
Copy this, paste it in the terminal and hit enter: defaults write com.apple.dashboard mcx-disabled -boolean YES
Then enter this: killall Dock
That’s it! Dashboard widgets are now disabled
Run the Mac OS X disk repair utility location in Applications > Utilities > Disk Utility and then run repair disk permissions. See this article on the repair functions of the disk utility.
Download and run Monolingual to remove all the additional languages that are built into OS X by default and you are likely to never use. I removed everything except English, Spanish, German and French since those are core languages on websites I sometimes frequent.
Download and run XSlimmer to remove all unnecessary PPC (PowerPC) code from Universal Binaries. Only use this if you are using an Intel based Mac. Additionally it is worthwhile noting that I had problems with Photoshop after slimming the application, so perhaps avoid using XSlimmer on CS3 or CS4.
Download and run OnyX. Run the daily, weekly and monthly scripts. Clear out all log files.
Removing unnecessary login items by going to System Preferences > Accounts > Login Items. Note that in order to actually remove a login item you need to select the item and then hit the minus button at the bottom of the preferences screen.
Even though Mac OS X has a journaled filesystem that should automatically handle defragmentation on the fly, it doesn’t do a great job of keeping the drive from becoming fragmented. iDefrag solves these problems and more, by defragmenting and optimizing your Mac’s filesystem at boot time. All you have to do is restart your computer, run the iDefrag boot DVD and it will defragment the entire hard-drive. I noticed a substantial performance boost (I would say up to around 20%) after using this.
Minimize by using the scale effect by going to System Preferences > Dock and changing the default from the Genie effect to the Scale effect. Also you can uncheck “animate opening applications” to boost performance.
Ensure you have a minimum of 10% disk space available so that OS X can run effectively. If you don’t have this much space free try using GrandPerspective to determine what is using space on your hard drive and what you might be able to delete.
Remove fonts that you don’t use. You can do this by going to the finder and removing fonts from your home folder > library > fonts.
Turn off Universal Access by navigating to System Preferences > Universal Access and turn off anything you’re not using.
Turn off Bluetooth by navigating to to System Preferences > Bluetooth.
Turn off Internet Sharing by navigating to to System Preferences > Sharing > Internet.
Check the Activity Monitor located in Applications > Utilities > Activity Monitor to see if there is anything running that is consuming processing or memory resources. This should go without saying.
On older computers you may notice massive performance issues particularly when Spotlight is running. To avoid these issues disable spotlight from indexing your entire hard-drive. You can do this by navigating to System Preferences > Spotlight and then unticking anything that you don’t want to see in search results. If you hit the Privacy tab you can also remove specific folders. I typically remove the Library folder, and also the System folder.
4 COMMAND LINE PERFORMANCE TUNING TIPS
You can speed up TCP connections by opening the terminal.app and typing pico /etc/sysctl.conf and adding the following lines to the file:
net.inet.tcp.mssdflt=1460
net.inet.tcp.sendspace=262144
net.inet.tcp.recvspace=262144
net.inet.udp.recvspace=74848
net.inet.udp.maxdgram=65535
You can speed up SSH connections by opening the terminal.app and typing pico ~/.ssh_config and adding the following lines to the file:
host *
controlmaster auto
controlpath /tmp/ssh-%r@%h:%p
It should be noted here that this may cause some glitches as I have run into some odd controlmaster errors after implementing this command. You can always try it and remove the code if it gives you problems.
Disable dashboard by opening up the terminal.app and running the command:
defaults write com.apple.dashboard mcx-disabled -boolean YES
and then run killall dock to restart the dock.
To optimize firefox’s tab/bookmarks/cache databases on OSX, close firefox, open terminal.app and run #cd ~/Library/Caches/Firefox/Profiles; for i in */*.sqlite; do sqlite3 $i VACUUM;done; cd ~/Library/Application\ Support/Firefox/Profiles; for i in */*.sqlite; do sqlite3 $i VACUUM;done;
THE MISSING MANUAL ON OS X
David Pogue’s missing manual on Mac OS X also covers maintenance related tasks, and is a great starter for those users who want to learn more on the intricacies of OS X. For those not familiar with using Terminal or the command line there is a really helpful chapter on this in specific.
摘自:http://simplestation.com/locomotion/speed-up-mac-os-x-leopard/
THE 15 BEST MAC PERFORMANCE TUNING APPLICATIONS AND TIPS
Disable Dashboard Widgets. Each dashboard widget you enable consumes both processing power and valuable memory. To disable widgets and speed up your mac follow these steps:
Open up terminal.app located in Applications > Utilities > Terminal
Copy this, paste it in the terminal and hit enter: defaults write com.apple.dashboard mcx-disabled -boolean YES
Then enter this: killall Dock
That’s it! Dashboard widgets are now disabled
Run the Mac OS X disk repair utility location in Applications > Utilities > Disk Utility and then run repair disk permissions. See this article on the repair functions of the disk utility.
Download and run Monolingual to remove all the additional languages that are built into OS X by default and you are likely to never use. I removed everything except English, Spanish, German and French since those are core languages on websites I sometimes frequent.
Download and run XSlimmer to remove all unnecessary PPC (PowerPC) code from Universal Binaries. Only use this if you are using an Intel based Mac. Additionally it is worthwhile noting that I had problems with Photoshop after slimming the application, so perhaps avoid using XSlimmer on CS3 or CS4.
Download and run OnyX. Run the daily, weekly and monthly scripts. Clear out all log files.
Removing unnecessary login items by going to System Preferences > Accounts > Login Items. Note that in order to actually remove a login item you need to select the item and then hit the minus button at the bottom of the preferences screen.
Even though Mac OS X has a journaled filesystem that should automatically handle defragmentation on the fly, it doesn’t do a great job of keeping the drive from becoming fragmented. iDefrag solves these problems and more, by defragmenting and optimizing your Mac’s filesystem at boot time. All you have to do is restart your computer, run the iDefrag boot DVD and it will defragment the entire hard-drive. I noticed a substantial performance boost (I would say up to around 20%) after using this.
Minimize by using the scale effect by going to System Preferences > Dock and changing the default from the Genie effect to the Scale effect. Also you can uncheck “animate opening applications” to boost performance.
Ensure you have a minimum of 10% disk space available so that OS X can run effectively. If you don’t have this much space free try using GrandPerspective to determine what is using space on your hard drive and what you might be able to delete.
Remove fonts that you don’t use. You can do this by going to the finder and removing fonts from your home folder > library > fonts.
Turn off Universal Access by navigating to System Preferences > Universal Access and turn off anything you’re not using.
Turn off Bluetooth by navigating to to System Preferences > Bluetooth.
Turn off Internet Sharing by navigating to to System Preferences > Sharing > Internet.
Check the Activity Monitor located in Applications > Utilities > Activity Monitor to see if there is anything running that is consuming processing or memory resources. This should go without saying.
On older computers you may notice massive performance issues particularly when Spotlight is running. To avoid these issues disable spotlight from indexing your entire hard-drive. You can do this by navigating to System Preferences > Spotlight and then unticking anything that you don’t want to see in search results. If you hit the Privacy tab you can also remove specific folders. I typically remove the Library folder, and also the System folder.
4 COMMAND LINE PERFORMANCE TUNING TIPS
You can speed up TCP connections by opening the terminal.app and typing pico /etc/sysctl.conf and adding the following lines to the file:
net.inet.tcp.mssdflt=1460
net.inet.tcp.sendspace=262144
net.inet.tcp.recvspace=262144
net.inet.udp.recvspace=74848
net.inet.udp.maxdgram=65535
You can speed up SSH connections by opening the terminal.app and typing pico ~/.ssh_config and adding the following lines to the file:
host *
controlmaster auto
controlpath /tmp/ssh-%r@%h:%p
It should be noted here that this may cause some glitches as I have run into some odd controlmaster errors after implementing this command. You can always try it and remove the code if it gives you problems.
Disable dashboard by opening up the terminal.app and running the command:
defaults write com.apple.dashboard mcx-disabled -boolean YES
and then run killall dock to restart the dock.
To optimize firefox’s tab/bookmarks/cache databases on OSX, close firefox, open terminal.app and run #cd ~/Library/Caches/Firefox/Profiles; for i in */*.sqlite; do sqlite3 $i VACUUM;done; cd ~/Library/Application\ Support/Firefox/Profiles; for i in */*.sqlite; do sqlite3 $i VACUUM;done;
THE MISSING MANUAL ON OS X
David Pogue’s missing manual on Mac OS X also covers maintenance related tasks, and is a great starter for those users who want to learn more on the intricacies of OS X. For those not familiar with using Terminal or the command line there is a really helpful chapter on this in specific.
摘自:http://simplestation.com/locomotion/speed-up-mac-os-x-leopard/
Apache 防止 DDoS 攻擊
Apache 防止 DDoS 攻擊
DDoS (distributed denial-of-service) 及 DoS (denial-of-service) 在網路上十分常見,而 DoS 攻擊所傳送的請求跟正常的請求一樣,分別在於每秒鐘發出大量請求到伺服器,使伺服器的負載增加,最常見的情況是伺服器暫停服務。
而 mod_evasive 則是一個預防 Apache 遭受 DDos 攻擊的模組,可以防止同一個 IP 對相同 URI 發出的大量請求,可設定的選項有:
– 限制同一個 IP 在一定秒數內請求一個頁面或檔案的次數。
– 限制同一個 IP 一秒內只可發出 50 個請求。
– 設定被禁止的 IP 封鎖時間。
以下是 mod_evasive 的安裝方法:
1. 先將原來的 httpd.conf 備份起來。
2. 到 http://www.zdziarski.com/projects/mod_evasive/ 下載 mod_evasive。
3. 在指令模式解壓及編譯 mod_evasive:
tar zxvf mod_evasive_1.10.1.tar.gz
cd mod_evasive/
apxs -cia mod_evasive20.c
以上的 apxs 會放在 Apache 的 bin 目錄內;如果 Apache 版本是 1.3 的話,指令要改為:
apxs -cia mod_evasive.c
安裝好 mod_evasive 後,便要修改 httpd.conf 內容。
4. 開啟 httpd.conf,加入以內容:
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 100
DOSPageInterval 2
DOSSiteInterval 2
DOSBlockingPeriod 10
DOSBlockingPeriod 600
DOSHashTableSize — 這是佔用記憶體的大小,如果伺服器比較繁忙,這個數值要設定大一點。
DOSPageCount — 同一 IP 在一個時段內可以存取同一頁面的次數,超過會被禁止。
DOSSiteCount — 同一 IP 在一個網站內可以佔用多少 Object,超過會禁止。
DOSPageInterval — DOSPageCount 內的時段設定。
DOSSiteInterval — DOSSiteCount 的時間設定,以秒為單位。
DOSBlockingPeriod — 當發現疑似攻擊後,使用者會收到 403 Forbidden,這是設定封鎖的時間,以秒為單位。
5. 最後重新啟動 Apache 即可。
DDoS (distributed denial-of-service) 及 DoS (denial-of-service) 在網路上十分常見,而 DoS 攻擊所傳送的請求跟正常的請求一樣,分別在於每秒鐘發出大量請求到伺服器,使伺服器的負載增加,最常見的情況是伺服器暫停服務。
而 mod_evasive 則是一個預防 Apache 遭受 DDos 攻擊的模組,可以防止同一個 IP 對相同 URI 發出的大量請求,可設定的選項有:
– 限制同一個 IP 在一定秒數內請求一個頁面或檔案的次數。
– 限制同一個 IP 一秒內只可發出 50 個請求。
– 設定被禁止的 IP 封鎖時間。
以下是 mod_evasive 的安裝方法:
1. 先將原來的 httpd.conf 備份起來。
2. 到 http://www.zdziarski.com/projects/mod_evasive/ 下載 mod_evasive。
3. 在指令模式解壓及編譯 mod_evasive:
tar zxvf mod_evasive_1.10.1.tar.gz
cd mod_evasive/
apxs -cia mod_evasive20.c
以上的 apxs 會放在 Apache 的 bin 目錄內;如果 Apache 版本是 1.3 的話,指令要改為:
apxs -cia mod_evasive.c
安裝好 mod_evasive 後,便要修改 httpd.conf 內容。
4. 開啟 httpd.conf,加入以內容:
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 100
DOSPageInterval 2
DOSSiteInterval 2
DOSBlockingPeriod 10
DOSBlockingPeriod 600
DOSHashTableSize — 這是佔用記憶體的大小,如果伺服器比較繁忙,這個數值要設定大一點。
DOSPageCount — 同一 IP 在一個時段內可以存取同一頁面的次數,超過會被禁止。
DOSSiteCount — 同一 IP 在一個網站內可以佔用多少 Object,超過會禁止。
DOSPageInterval — DOSPageCount 內的時段設定。
DOSSiteInterval — DOSSiteCount 的時間設定,以秒為單位。
DOSBlockingPeriod — 當發現疑似攻擊後,使用者會收到 403 Forbidden,這是設定封鎖的時間,以秒為單位。
5. 最後重新啟動 Apache 即可。
2010年7月22日 星期四
刪除mysql二進制記錄
$date=date('Y-m-d H:i:s',mktime(23,59,59,date('m'),date('d')-4,date('Y')));
$sql="PURGE MASTER LOGS BEFORE '".$date."'";
my_query($sql);
phpgacl setup failed! Specified key was too long; max key length is 1000 bytes
MySQL錯誤「Specified key was too long; max key length is 1000 bytes」的解決辦法
今天在為數據庫中的某兩個字段設置unique索引的時候,出現了Specified key was too long; max key length is 1000 bytes錯誤,經過查詢才知道,是Mysql的字段設置的太長了,於是我把這兩個字段的長度改了一下就好了。
建立索引時,數據庫計算key的長度是累加所有Index用到的字段的char長度後,
再按下面比例乘起來,不能超過限定的key長度1000:
latin1 = 1 byte = 1 character
uft8 = 3 byte = 1 character
gbk = 2 byte = 1 character
舉例能看得更明白些,以GBK為例:
CREATE UNIQUE INDEX `unique_record` ON reports (`report_name`, `report_client`, `report_city`);
其中report_name varchar(200), report_client varchar(200), report_city varchar(200)
(200 + 200 +200) * 2 = 1200 > 1000,所以就會報1071錯誤,
只要將report_city改為varchar(100)那麼索引就能成功建立。
如果表是UTF8字符集,那索引還是建立不了。
現在建立網站大都採UTF-8編碼,以同時兼容各國文字,而不會發生亂碼問題,
但UTF-8編碼佔的位元較多,因此需注意到如果使用的是國外的源碼,
因為國外語言一個字大都一個1 bite,但中文為2bite,所以可能會有長度的問題,
雖然這問題在一般狀況下並不常碰到..... 不過還是被我碰上了,
上網搜一搜才知道問題所在,順便提出來分享。
摘自:http://blog.xuite.net/chu.hsing/Think/33667688
Solutin :
$vi phpgacl/adodb/adodb-datadict.inc.php
今天在為數據庫中的某兩個字段設置unique索引的時候,出現了Specified key was too long; max key length is 1000 bytes錯誤,經過查詢才知道,是Mysql的字段設置的太長了,於是我把這兩個字段的長度改了一下就好了。
建立索引時,數據庫計算key的長度是累加所有Index用到的字段的char長度後,
再按下面比例乘起來,不能超過限定的key長度1000:
latin1 = 1 byte = 1 character
uft8 = 3 byte = 1 character
gbk = 2 byte = 1 character
舉例能看得更明白些,以GBK為例:
CREATE UNIQUE INDEX `unique_record` ON reports (`report_name`, `report_client`, `report_city`);
其中report_name varchar(200), report_client varchar(200), report_city varchar(200)
(200 + 200 +200) * 2 = 1200 > 1000,所以就會報1071錯誤,
只要將report_city改為varchar(100)那麼索引就能成功建立。
如果表是UTF8字符集,那索引還是建立不了。
現在建立網站大都採UTF-8編碼,以同時兼容各國文字,而不會發生亂碼問題,
但UTF-8編碼佔的位元較多,因此需注意到如果使用的是國外的源碼,
因為國外語言一個字大都一個1 bite,但中文為2bite,所以可能會有長度的問題,
雖然這問題在一般狀況下並不常碰到..... 不過還是被我碰上了,
上網搜一搜才知道問題所在,順便提出來分享。
摘自:http://blog.xuite.net/chu.hsing/Think/33667688
Solutin :
$vi phpgacl/adodb/adodb-datadict.inc.php
// Executes the sql array returned by GetTableSQL and GetIndexSQL
function ExecuteSQLArray($sql, $continueOnError = true)
{
$rez = 2;
$conn = &$this->connection;
$saved = $conn->debug;
foreach($sql as $line) {
if(false !== strpos(strtolower($line),'create table')){ //Add This Code Start
$line .= 'default charset=latin1;';
} //Add This Code End
if ($this->debug) $conn->debug = true;
$ok = $conn->Execute($line);
$conn->debug = $saved;
if (!$ok) {
//var_dump($line);exit();
if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
if (!$continueOnError) return 0;
$rez = 1;
}
}
return $rez;
}
2010年7月21日 星期三
jQuery Calendar with time picker
JQuery UI DateTimePicker
Source files
JS Files jquery.ui.datetimepicker.js (txt) jquery.ui.datetimepicker.js.txt
JS MIN Files jquery.ui.datetimepicker.min.js
Based on JQuery UI DatePicker + JavaScript Date Format,
Removed DatePicker option constrainInput.
Removed DatePicker input parsing, replaced with a basic date/time check.
Changed DatePicker formatting options from input/output formatting, to output formatting only.
Implemented JavaScript Date Format option for output formatting.
Added closest year based on absolute (ABS) distance from present year.
2/1/13 chooses 2013.
12/1/88 chooses 1988.
Minimum required dependencies.
1:
2:
3:
4:
5:
6:
Configures form element ID TextBox1 to be a jquery datetimepicker
1:
HTML Elements
1:
2:
3:
6:
7:
摘自:http://projectcodegen.com/JQueryDateTimePicker.aspx
Source files
JS Files jquery.ui.datetimepicker.js (txt) jquery.ui.datetimepicker.js.txt
JS MIN Files jquery.ui.datetimepicker.min.js
Based on JQuery UI DatePicker + JavaScript Date Format,
Removed DatePicker option constrainInput.
Removed DatePicker input parsing, replaced with a basic date/time check.
Changed DatePicker formatting options from input/output formatting, to output formatting only.
Implemented JavaScript Date Format option for output formatting.
Added closest year based on absolute (ABS) distance from present year.
2/1/13 chooses 2013.
12/1/88 chooses 1988.
Minimum required dependencies.
1:
2:
3:
4:
5:
6:
Configures form element ID TextBox1 to be a jquery datetimepicker
1:
HTML Elements
1:
2:
3:
6:
7:
摘自:http://projectcodegen.com/JQueryDateTimePicker.aspx
2010年7月19日 星期一
Server Spec Suggestion
1 Apache server can be smaller.
1.1 RAM: Even 1GB RAM will work.
1.2 Disk: if you have tons of pictures, I would suggest you can get smaller disks and more disk quantity. For example, 36GB X 4. With RAID1, total usable size would be 36G X 2. I think that’s enough for Apache server.
1.2.1 Disk1: OS and Apache server
1.2.2 Disk2: all data
1.3 CPU: Single CPU will work
2 DB server should be bigger
2.1 RAM: 2-4 GB, depends on how fast you want and MySQL’s limitation.
2.2 Disk: the more the better (RAID1 is MUST). My minimum suggestion:
2.2.1 Disk1: System
2.2.2 Disk2: Data & INDEX
2.2.3 Disk3: Transaction Log and Backup files
2.3 CPU: suggest 2 CPUs.
1.1 RAM: Even 1GB RAM will work.
1.2 Disk: if you have tons of pictures, I would suggest you can get smaller disks and more disk quantity. For example, 36GB X 4. With RAID1, total usable size would be 36G X 2. I think that’s enough for Apache server.
1.2.1 Disk1: OS and Apache server
1.2.2 Disk2: all data
1.3 CPU: Single CPU will work
2 DB server should be bigger
2.1 RAM: 2-4 GB, depends on how fast you want and MySQL’s limitation.
2.2 Disk: the more the better (RAID1 is MUST). My minimum suggestion:
2.2.1 Disk1: System
2.2.2 Disk2: Data & INDEX
2.2.3 Disk3: Transaction Log and Backup files
2.3 CPU: suggest 2 CPUs.
2010年7月17日 星期六
Mac OSX tuning
For testing temporary improvements, you can directly use sysctl in a terminal window: (you have to be root to do that)
$ sudo sysctl -w kern.maxfiles=65536
kern.maxfiles: 12288 -> 65536
$ sudo sysctl -w net.inet.tcp.delayed_ack=0
net.inet.tcp.delayed_ack: 3 -> 0
$ sudo sysctl -w net.inet.tcp.win_scale_factor=8
net.inet.tcp.win_scale_factor: 3 -> 8
$ sudo sysctl -w net.inet.tcp.mssdflt=1440
net.inet.tcp.mssdflt: 512 -> 1440
$ sudo sysctl -w net.inet.udp.recvspace= 147456
net.inet.udp.recvspace: 42080 -> 147456
$ sudo sysctl -w net.inet.udp.maxdgram=57344
net.inet.udp.maxdgram: 9216 -> 57344
$ sudo sysctl -w net.inet.tcp.sendspace= 1048576
net.inet.tcp.sendspace: 65536 -> 1048576
$ sudo sysctl -w net.inet.tcp.recvspace= 1048576
net.inet.tcp.recvspace: 65536 -> 1048576
$ sudo sysctl -w net.local.stream.recvspace=65535
net.local.stream.recvspace: 8192 -> 65535
$ sudo sysctl -w net.local.stream.sendspace=65535
net.local.stream.sendspace: 8192 -> 65535
For permanent changes that last over a reboot, insert the appropriate configurations into Ltt>/etc/sysctl.conf. If this file does not exist must create it. So, for the above, just add the following lines to sysctl.conf:
kern.maxfiles=65536
net.inet.tcp.delayed_ack=0
net.inet.tcp.win_scale_factor=8
net.inet.tcp.mssdflt=1440
net.inet.udp.recvspace=147456
net.inet.udp.maxdgram=57344
net.inet.tcp.sendspace=1048576
net.inet.tcp.recvspace=1048576
net.local.stream.recvspace=65535
net.local.stream.sendspace=65535
Note This only works for OSX 10.3 or later! For earlier versions you need to use /etc/rc where you can enter whole sysctl commands.
參考:
http://kb.pert.geant.net/PERTKB/MacOSXOSSpecific
$ sudo sysctl -w kern.maxfiles=65536
kern.maxfiles: 12288 -> 65536
$ sudo sysctl -w net.inet.tcp.delayed_ack=0
net.inet.tcp.delayed_ack: 3 -> 0
$ sudo sysctl -w net.inet.tcp.win_scale_factor=8
net.inet.tcp.win_scale_factor: 3 -> 8
$ sudo sysctl -w net.inet.tcp.mssdflt=1440
net.inet.tcp.mssdflt: 512 -> 1440
$ sudo sysctl -w net.inet.udp.recvspace= 147456
net.inet.udp.recvspace: 42080 -> 147456
$ sudo sysctl -w net.inet.udp.maxdgram=57344
net.inet.udp.maxdgram: 9216 -> 57344
$ sudo sysctl -w net.inet.tcp.sendspace= 1048576
net.inet.tcp.sendspace: 65536 -> 1048576
$ sudo sysctl -w net.inet.tcp.recvspace= 1048576
net.inet.tcp.recvspace: 65536 -> 1048576
$ sudo sysctl -w net.local.stream.recvspace=65535
net.local.stream.recvspace: 8192 -> 65535
$ sudo sysctl -w net.local.stream.sendspace=65535
net.local.stream.sendspace: 8192 -> 65535
For permanent changes that last over a reboot, insert the appropriate configurations into Ltt>/etc/sysctl.conf. If this file does not exist must create it. So, for the above, just add the following lines to sysctl.conf:
kern.maxfiles=65536
net.inet.tcp.delayed_ack=0
net.inet.tcp.win_scale_factor=8
net.inet.tcp.mssdflt=1440
net.inet.udp.recvspace=147456
net.inet.udp.maxdgram=57344
net.inet.tcp.sendspace=1048576
net.inet.tcp.recvspace=1048576
net.local.stream.recvspace=65535
net.local.stream.sendspace=65535
Note This only works for OSX 10.3 or later! For earlier versions you need to use /etc/rc where you can enter whole sysctl commands.
參考:
http://kb.pert.geant.net/PERTKB/MacOSXOSSpecific
2010年7月16日 星期五
台灣固網的客服真的不好,差,有改善的空間
今天在家里用台灣固網的ADSL無法連上網路。
打去給客服時,發生了以下令人苦笑不得的事情...
我:我網路無法開啟網頁
對方:好,讓我來幫你檢查一下您電腦的設定
我:好
對方:請你點選左下方的開始
我:我是用Mac OS
對方:那請你比較懂電腦的朋友來幫你看一下您的網路設定,或者看你是否可以打電話給蘋果公司
我:....
對方:....
我:哦 ... T.T
真的是XXOOOXXXX!!!!~~~~
打去給客服時,發生了以下令人苦笑不得的事情...
我:我網路無法開啟網頁
對方:好,讓我來幫你檢查一下您電腦的設定
我:好
對方:請你點選左下方的開始
我:我是用Mac OS
對方:那請你比較懂電腦的朋友來幫你看一下您的網路設定,或者看你是否可以打電話給蘋果公司
我:....
對方:....
我:哦 ... T.T
真的是XXOOOXXXX!!!!~~~~
在FreeBSD上掛載smbfs (NAS)
最近,在弄lab的ftp整合計畫。
要將另一台Linux的資料透過samba的方式來掛載到ftp那台FreeBSD上。
以下則是在弄的過程所得到的一些Notes。
首先,我們可以透過以下的指令來察看有提供連線的資料
smbutil view
掛載時則使用
mount_smbfs //[username]@[host]/[service] [mountpoint]
若要加入 /etc/fstab 使開機後自動mount,請先編輯 /etc/nsmb.conf
加入[host:user]的 section,注意! host及section都必須為"大寫",既使平常輸入的是小寫!
然後在該section加入
password=[encrypted_password] (由smbutil crypt算出,Plain Text也可以)
最後,在 /etc/fstab 裡加上:
//[username]@[host]/[service] [mountpoint] smbfs rw,-I=xxx.xxx.xxx.xxx,-N,-u=[uid],-g=[gid] 0 0
要測試是否成功可以用:
mount -a
來觀看結果。
摘自:http://lazyflai.blogspot.com/2006/09/freebsdsmbfs.html
要將另一台Linux的資料透過samba的方式來掛載到ftp那台FreeBSD上。
以下則是在弄的過程所得到的一些Notes。
首先,我們可以透過以下的指令來察看有提供連線的資料
smbutil view
掛載時則使用
mount_smbfs //[username]@[host]/[service] [mountpoint]
若要加入 /etc/fstab 使開機後自動mount,請先編輯 /etc/nsmb.conf
加入[host:user]的 section,注意! host及section都必須為"大寫",既使平常輸入的是小寫!
然後在該section加入
password=[encrypted_password] (由smbutil crypt算出,Plain Text也可以)
最後,在 /etc/fstab 裡加上:
//[username]@[host]/[service] [mountpoint] smbfs rw,-I=xxx.xxx.xxx.xxx,-N,-u=[uid],-g=[gid] 0 0
要測試是否成功可以用:
mount -a
來觀看結果。
摘自:http://lazyflai.blogspot.com/2006/09/freebsdsmbfs.html
2010年7月15日 星期四
周思博趣談軟體
程式師的使用介面設計手冊
第 1 章
第 2 章
第 3 章
第 4 章
第 5 章
第 6 章
第 7 章
第 8 章
第 9 章
讓錯的程式看得出錯
2005年5月11日
就是在這個階段你會說出:"該死的混蛋, 我們這裡一定要定出一些一致的編程風格!" 然後第二天寫出一份你們團隊用的編程風格, 接下來用六天來討論"One True Brace Style", 然後再花三星期把舊程式碼改寫成符合"One True Brace Style", 一直做到經理發現並責怪你把時間浪費在不能賺錢的事為止. 你想想其實不需要一次全部改好, 看到哪裡改到哪裡也沒什麼關係. 於是你有一半的程式碼是"True Brace Style"而且沒多久你就忘記這件事了. 接下來你就開始滿腦子想著其他與賺錢無關的事, 比如把某個字串類別換成另一個字串類別等等.
邊開火邊移動
2002年1月6日
當你進入狀況後, 要繼續維持並不算太難. 我的一天通常都是這樣子的: (1) 上班 (2) 看信看網頁等等 (3) 決定應該吃過午飯後再做事 (4) 吃完午飯回來 (5) 看信看網頁等等 (6) 終於決心該開始幹活 (7) 看信看網頁等等 (8) 再度下定決心真的該開始做事 (9) 把該死的編輯器叫出來然後 (10) 不斷地寫程式直到突然發現已經下午7點半了.
第8步和第9步之間似乎有點問題, 因為我不是每次都能順利跨越鴻溝.
無痛錯誤追蹤
2000年11月8日
只要你在寫程式(只有一個人寫也一樣), 如果沒有一套良好的資料庫列出程式中所有的問題, 一定會產生品質低劣的程式碼. 無痛錯誤追蹤
無痛功能規格
2000年10月2日
第一篇: 何必麻煩呢?
第二篇: 規格是什麼?
第三篇: 不過...要怎麼做呢?
第四篇: 提示
約耳測試: 邁向高品質的12個步驟
2000年8月9日
聽說過SEMA嗎? 這是一套相當深奧的系統, 可以測量軟體團隊的好壞. 不要急著連過去看. 光是要搞懂那東西大概就要花上六年了. 所以我自己有一套無責任的簡易方法來衡量軟體團隊的品質. 這套方法的好處是只要花3分鐘左右. 省下的時間足夠讓你唸趟醫學院.
無痛軟體時程
2000年3月29日
為什麼沒人要訂時程呢?首先是執行起來很痛苦.其次是沒人認為值得做.明明知道排出來不準確,為什麼要費事去做呢? 下面提供一個簡單無痛的方法, 可以訂出確實無誤的時程.
軟體人員面試教戰守則
2000年3月23日
錄取合適的人對於Fog Creek軟體公司來說是非常關鍵的。在我們這個領域,有三類人可以挑選。在一個極端, 是哪些混進來的, 甚至缺乏最基本的工作技巧. 只要問這類人兩三個簡單的問題,再讀一下他們的簡歷,就可以輕易地剔除他們。另一個極端的類型是 才華橫溢的超級明星 這些人僅僅爲了好玩就用組合語言爲Palm Pilot(一種手掌電腦)寫了一個Lisp(一種人工智慧編程語言)編譯器。在這兩種極端類型中間的是一大群不能確定水平的候選者,也許他們中的某些人能幹些什麽?這裏的關鍵是明白超級明星和那一大堆屬於中間類型的人的區別,因爲Fog Creek軟體公司只錄取超級明星。下面我要介紹一些找出超級明星的技巧。
摘自:http://chinesetrad.joelonsoftware.com/index.html
第 1 章
第 2 章
第 3 章
第 4 章
第 5 章
第 6 章
第 7 章
第 8 章
第 9 章
讓錯的程式看得出錯
2005年5月11日
就是在這個階段你會說出:"該死的混蛋, 我們這裡一定要定出一些一致的編程風格!" 然後第二天寫出一份你們團隊用的編程風格, 接下來用六天來討論"One True Brace Style", 然後再花三星期把舊程式碼改寫成符合"One True Brace Style", 一直做到經理發現並責怪你把時間浪費在不能賺錢的事為止. 你想想其實不需要一次全部改好, 看到哪裡改到哪裡也沒什麼關係. 於是你有一半的程式碼是"True Brace Style"而且沒多久你就忘記這件事了. 接下來你就開始滿腦子想著其他與賺錢無關的事, 比如把某個字串類別換成另一個字串類別等等.
邊開火邊移動
2002年1月6日
當你進入狀況後, 要繼續維持並不算太難. 我的一天通常都是這樣子的: (1) 上班 (2) 看信看網頁等等 (3) 決定應該吃過午飯後再做事 (4) 吃完午飯回來 (5) 看信看網頁等等 (6) 終於決心該開始幹活 (7) 看信看網頁等等 (8) 再度下定決心真的該開始做事 (9) 把該死的編輯器叫出來然後 (10) 不斷地寫程式直到突然發現已經下午7點半了.
第8步和第9步之間似乎有點問題, 因為我不是每次都能順利跨越鴻溝.
無痛錯誤追蹤
2000年11月8日
只要你在寫程式(只有一個人寫也一樣), 如果沒有一套良好的資料庫列出程式中所有的問題, 一定會產生品質低劣的程式碼. 無痛錯誤追蹤
無痛功能規格
2000年10月2日
第一篇: 何必麻煩呢?
第二篇: 規格是什麼?
第三篇: 不過...要怎麼做呢?
第四篇: 提示
約耳測試: 邁向高品質的12個步驟
2000年8月9日
聽說過SEMA嗎? 這是一套相當深奧的系統, 可以測量軟體團隊的好壞. 不要急著連過去看. 光是要搞懂那東西大概就要花上六年了. 所以我自己有一套無責任的簡易方法來衡量軟體團隊的品質. 這套方法的好處是只要花3分鐘左右. 省下的時間足夠讓你唸趟醫學院.
無痛軟體時程
2000年3月29日
為什麼沒人要訂時程呢?首先是執行起來很痛苦.其次是沒人認為值得做.明明知道排出來不準確,為什麼要費事去做呢? 下面提供一個簡單無痛的方法, 可以訂出確實無誤的時程.
軟體人員面試教戰守則
2000年3月23日
錄取合適的人對於Fog Creek軟體公司來說是非常關鍵的。在我們這個領域,有三類人可以挑選。在一個極端, 是哪些混進來的, 甚至缺乏最基本的工作技巧. 只要問這類人兩三個簡單的問題,再讀一下他們的簡歷,就可以輕易地剔除他們。另一個極端的類型是 才華橫溢的超級明星 這些人僅僅爲了好玩就用組合語言爲Palm Pilot(一種手掌電腦)寫了一個Lisp(一種人工智慧編程語言)編譯器。在這兩種極端類型中間的是一大群不能確定水平的候選者,也許他們中的某些人能幹些什麽?這裏的關鍵是明白超級明星和那一大堆屬於中間類型的人的區別,因爲Fog Creek軟體公司只錄取超級明星。下面我要介紹一些找出超級明星的技巧。
摘自:http://chinesetrad.joelonsoftware.com/index.html
2010年7月14日 星期三
利用ASP+JMAIL發送大量電子報的程式撰寫方式
背景:
Email地址存於MSSql一使用者資訊表中,數量上萬。
公司自有伺服器,集SMTP,POP3,WWW,FTP,MSSql,DNS等多種服務於一身。
JMAIL 有MailMerge對象,但是免費版不能用
要求:
用ASP+JMAIL,利用公司SMTP向所有使用者送出EMAIL
思路:
直接讀取資料庫,多次循環送出,會對本來配置不高的伺服器造成很大壓力。
最好能對EMAIL分批送出,每批送出間隔一段時間,以此來緩解對伺服器造成的壓力。
實做:
對EMAIL分批
讀出記錄到recordset,利用常見的分頁程式,將所有記錄分頁,每頁作為一批,有多少頁就分多少批
間隔延遲
在每頁執行完畢後用來延遲跳轉
減少執行時間:
在循環的過程中,循環新增收件人,而不要循環送出,即
for i=1 to rs.pagesize
msg.AddRecipient rs("Email")
rs.movenext
next
msg.Send ("smtp.abc.com")
減小信件大小
循環新增收件人,會造成一封Email的收件人很多,這樣一封Email的就會很大。
所以,在以上原始碼的基礎上改進一下,在循環內做個判斷,當收件人Email數量到達
20的時候就送出一次。即:
<form action="SendMail.asp" target="Send">;
一個iframe頁面,<iframe name="Send" src="SendMail.asp">
SendMail.asp 包含後台送出程式,循環,延遲跳轉等。
缺點:
送出過程中不能離開該頁面
送出的時間較長,與設定的每批送出數量、網路頻寬、SMTP伺服器效能有關
改進:
可以在Mail.asp中包含多個iframe頁面,每個頁面從不同的page開始發,相當於多線程送出,
對smtp伺服器壓力會增大,但能縮短髮送時間。
可考慮在不同的page中採用不同的smtp伺服器,例如包含多個iframe頁面,在偶數頁用
smtp.abc.com,在奇數頁用smtp.123.com。這樣既減輕伺服器壓力,也達到多線程送出
縮短髮送時間的目的。
Email地址存於MSSql一使用者資訊表中,數量上萬。
公司自有伺服器,集SMTP,POP3,WWW,FTP,MSSql,DNS等多種服務於一身。
JMAIL 有MailMerge對象,但是免費版不能用
要求:
用ASP+JMAIL,利用公司SMTP向所有使用者送出EMAIL
思路:
直接讀取資料庫,多次循環送出,會對本來配置不高的伺服器造成很大壓力。
最好能對EMAIL分批送出,每批送出間隔一段時間,以此來緩解對伺服器造成的壓力。
實做:
對EMAIL分批
讀出記錄到recordset,利用常見的分頁程式,將所有記錄分頁,每頁作為一批,有多少頁就分多少批
間隔延遲
在每頁執行完畢後用來延遲跳轉
減少執行時間:
在循環的過程中,循環新增收件人,而不要循環送出,即
for i=1 to rs.pagesize
msg.AddRecipient rs("Email")
rs.movenext
next
msg.Send ("smtp.abc.com")
減小信件大小
循環新增收件人,會造成一封Email的收件人很多,這樣一封Email的就會很大。
所以,在以上原始碼的基礎上改進一下,在循環內做個判斷,當收件人Email數量到達
20的時候就送出一次。即:
for i=1 to rs.pagesize
msg.AddRecipient rs("Email")
if i mod 20 = 0 then '每 20 個收信人作為一封Email送出一次
msg.Send ("smtp.abc.com")
msg.ClearRecipients '清除已送出的收信人
end if
rs.movenext
next
msg.Send ("smtp.abc.com") '送出餘下的頁面
Mail.asp 包含信件主題、正文的表單,
<form action="SendMail.asp" target="Send">;
一個iframe頁面,<iframe name="Send" src="SendMail.asp">
SendMail.asp 包含後台送出程式,循環,延遲跳轉等。
缺點:
送出過程中不能離開該頁面
送出的時間較長,與設定的每批送出數量、網路頻寬、SMTP伺服器效能有關
改進:
可以在Mail.asp中包含多個iframe頁面,每個頁面從不同的page開始發,相當於多線程送出,
對smtp伺服器壓力會增大,但能縮短髮送時間。
可考慮在不同的page中採用不同的smtp伺服器,例如包含多個iframe頁面,在偶數頁用
smtp.abc.com,在奇數頁用smtp.123.com。這樣既減輕伺服器壓力,也達到多線程送出
縮短髮送時間的目的。
《凡事都有好方法》
搬家法
--------------------------------------------------------------------------------
作者:楊望遠
在工作簡化的研討會上,總有人認為本身工作己純熟順利,不再可能改善,遑論大幅簡化了。
然而,據歸納分析,一般人的工作量中,至少有百分之五十是無效或可改善的,上百分之五十以上的人力閒置,若能完全有發揮,生產力至少提高為四倍。
為何多數人見不及此呢?實乃點滴累積,習不察也。
我有一友,喜收藏堪用之物,全屋都是寶貝,至壅塞不堪。親朋同事屢勸其整理一下,將多餘不用之物捨棄,以改善居住空間,皆見其面露苦色,無一物肯捨棄。
數月,前其不堪噪音及汙濁空氣,而於郊區購一屋一幢,且僱工裝潢得十分華麗。待搬家時,左挑右選,來回細審,無一物值得搬入新家,數十年糾纏之情結,一夕間完全割捨。
同理,若要我等從現有工作中,挑出那幾件不必做或可簡化,往往一件也難;但反過來,先將幾所有工作挪開,再挑出那裡幾件非做不可,便會發現少得多。再換一個說法,若要調往新職,又有幾件工作會隨同卦赴任?接任者是否會接下全部工作 ?
其實搬家法的效用非常適合忙碌的現代人,偶爾或定期將思慮搬家一下,將工作搬家,將檔案搬家一下...,一定會有意想不到的發現。
其歷史悠久的企業,四十餘年來,除每三年一次的粉刷外,不僅人事安定,連辦公室內陳設及工廠內布置也非常固定。某資深主管甚誇稱,閉著眼晴也能來去自如。
結果是長江後浪推前浪,一家家後起企業大幅成長=超越,讓企業的業績仍異常穩定,予人老舊不振之感。
企業若真心追求永續經營,勢將生命貫注在企業內,不斷搬動翻新,維持創新活力。總之凡事有更好的方法,當藉口工作不可能簡化改善時,請以搬家法一試。
差不多是天意
--------------------------------------------------------------------------------
作者:楊望遠
中國人處事不夠精確,凡事「差不多」。
事實上,天意即差不多,既能蘊涵變化契機,亦免於繁瑣滯礙。
如天候預測之難於精確,便是明顯例子。
其他如衣服尺碼,L、M、S,即使訂做,亦未必完全合身;每月薪水固定,但實際工作天數卻不一,信函要分平信、限時、掛號,顯示郵遞中狀況變化。
其實,國人講「差不多,差不多就好」,並非想要混水摸魚,而是不希望精準地釘死在一點,動彈不得;真正用意在能隨狀況變化不斷調適;所謂「此一時,彼一時」,不必計較一時,而求取長期的合理與均衡。
唯中國歷史文化太過悠久,致背景模糊,許多人未能追根究柢,而對「差不多」認識不清,乃有過猶不及的反應。
須知,差不多是天意,是文化的累積、經驗的傳承,亦即脈絡可循的道統,不是個人可以任意更張的。
雖然,有人標榜當今是「不確定的時代」,但「不確定即確定」;同理,差不多不離「大同小異」的原則。也因能有此理念,每個人乃能各取所需,找到最適的發展空間及彈性。
因此,個人須肯定天意的差不多,而採取精確的思考及果敢的行動,切莫淪於「差不多」的皮相,以致一事難成。
士氣衡量
--------------------------------------------------------------------------------
作者:楊望遠
常聽主管抱怨:「我們公司向心力差,士氣低落,簡直無法管理。」
於是,有人問「士氣高低如何衡量?」是憑直覺?還是靠數據?
士氣,表面上看來,的確是十分抽象,致無法具體加以衡量;但深究下去,卻不盡然。
其實,任何事物往往一體兩面,而且皆有因果關係,譬如士氣是「因」,則必有其「果」,「因」固然抽象,「果」卻是具體的,故衡量「果」,亦等於評估「因」。
我們要求士氣高昂,會產生何種結果?不外乎:
1.效率提高。
2.出勤率提高,流動率降低。
3.工作調派配合性好,爭議減少。
4.整理整頓效果顯著。
5.自動加班,適時達成任務 。
6.目標圓滿達成。
雖然,上述的「果」與其他的「因」亦有交互作用,但只要完整收集一段時間的實際過程資料,仍能分出程度高低,予以適當評比,其衡量效力是肯定的。
同理,任何抽象的事物,如向心力、教育訓練、創意、積極主動、忠勇孝悌等,皆可以其果設定衡量指標,評估出程度高低。
因此,身為主管莫再將管理不善歸咎於抽象的名詞,而當設法具體化,並用心改善管理才是。
十倍速提升競爭力
--------------------------------------------------------------------------------
作者:楊望遠
自從「十倍速時代」一書問世以來,焦點似乎集中在所謂高科技產業,而傳統產業則成了沒落不振,必須外移的族群。
然而,綜觀國內大財團,多具有傳統產業的堅實背景,不論石化、紡織、電機、車輛、製鞋、食品...,皆能雄霸一方,各領風騷,一樣具有光明前景。
那麼,比率佔97% 的中小企業,是否成了大企業的防波堤及炮灰,永遠難有出頭天?還是只要肯不斷長進,終成蛻化成為大企業?
有人說:台灣的中小企業韌性堅強,從石油危機開始,經歷了新台幣升值、勞工短缺、土地難求...,直到最近的金融風暴,似乎都能安然少事,屹立微搖。
但,換個角度看,也可說成平時只求得過且過,唯有見到棺材才拚命,卻也多能柳暗花明又一「春」;然後,又安逸地等待下一波危機。
如今,十倍速時代來臨,危機來得既急且密,幾乎是一波未平,一波又起,眼見一口氣換不過來,便將作波臣,恐怕,連好整以暇地坐以待斃都不可得,非得突破傳統隨遇而安的被動做法,必須一次拚盡全力,主動搏命突圍,方能化危為機。
但是,以前也改革過數次,如3210作戰,即效率提高30%、庫存降低20%、成本降低10%、零缺點、零傷害,似乎成效不彰;又如「全員都革新,天天有進步」,結果是煥然一新之後,成了天天有退步...,以致大家都心知肚明,不過是說說就算,頂多熱鬧一陣,不可能會是玩真的,何必卯足全勁白費力氣!
其實,以往的努力並未全然白費,只是久臨門一腳,即能水到渠成;若能拿住竅門,用對方法,不僅能快速(一至三月),而且大幅(三至二十倍)提升各方面競爭力,不必訝異疑忌,皆是可即學即用的實戰心得,一試便知!
如果,用遍地黃金來形容台灣的企業,恐怕視而不見者揉破了眼也看不到,我們將逐一引導「忙、盲、茫」的企業人去開金礦、採寶玉,一定令人目不暇給。
不過,先申明一點,開採所得須用來提升競爭力,切忌驕奢怠慢,淪作波臣!
有關單位
--------------------------------------------------------------------------------
作者:楊望遠
不知從何時開始,「有關單位」成了無所不在、無時或缺的一個有形的單位。
請看:路面坑洞,「通知有關單位處理」。
民眾請願,「轉知有關單位處理」。
兩岸貿易,「召集有關單位研究」。
治安惡化,「責成有關單位改善」。
有關單位到底有多少,到底是哪些單位,從來鮮有人去清楚,否則遊戲的趣味也沒了。
事情辦不好、沒辦成,非己之過,乃有關單位配合不足之故。
事情一延再誤、遲無下文,非己不力,乃有關單位研究討論,力求慎重,無法周全之故。
總之,不論事前、事中、事後,只要將責任推給有關單位,反正沒人清楚,大家推來推去,玩的人趣味十足,等的人可是怨氣沖天。
以IE的眼光來看,根本不該存在有關單位,任何事只有「主辦單位」,必須擔負成敗全責,沒有任何推卸的餘地。
至於事件相關單位,乃對主辦單位負責,不得作為推卸、延宕的藉口。
以「主辦責任大分類法」,凡負責比率最高者為主辦單位,任何事都能歸屬唯一主辦單位,全權負責處理。
若每一個人不再偷懶地將責任推給有關單位,而認清地直指主辦單位,相信在國家、在企業,必能因權責分明,而能有高績效。
到岸不需船
--------------------------------------------------------------------------------
作者:楊望遠
有位媳婦,每次煎魚,都把頭尾剁掉,婆婆看在眼裡,憋在心裡。終於,有一天,婆婆實在憋不住了,假作不經意地問:「煎魚為何要去頭去尾?」媳婦毫不遲疑道:「我娘家都是這麼做,可能是傳統吧!」
婆婆只好笑笑道:「你下次回娘家,問問你媽媽,看他知不知道原因。」媳婦心想婆婆急著要答案,便打電話回娘家,一問之下,連她自己都不好意思。 原來,當時因為鍋子小,不去頭去尾煎不下,想不到換了大鍋,卻忘了原因,舊習慣一直延襲下來。
十多年前,國內生產電腦主機板、監視器,都須經過燒機測試(Burn-in);量小時,空間及時間都還好解決;但,高倍成長後,如此積至壓,的確相當沈重。
有一次,筆者輔導的公司,在經營管理會上,某主管提出:「燒機房容量不夠,必須立即擴建。」但,全廠能用的空間,幾乎都滿了,怎麼辦呢? 七嘴八舌的討論,都是想什麼法子儘快擴建,筆者問了一個很外行的問題:「為什麼要Burm-in?」
大家都楞住了,最後,品保經理挺身而出答:「此乃保證品質的必要製程,避免新購不久就故障。」
筆者問:「目前測試結果,不良率有多少?」
答:「不高,約1%」
再問:「是普遍分布,還是偏向某些規格。」
答:「幾乎都是新產品、新規格、新零件。」
根據一年來的報表數據,也證實確是僅有「新」的部分不合格。
於是,運用層別管理,沒問題的部分不必再燒機,只有少部分須測試,待找出原因,改善穩定後,便可免除。
如此一來,空間空出甚多,庫存大幅降低,出貨也順暢了。 早期,因為技術尚不成熟、另件品質不穩定、分析技巧不進步,故因襲舊制,不敢擅改;久而久之,知其然,不知其所以然,失去了大好改善進步的契機。
某次,英國軍事演習,各國使節觀閱。 一位美國將軍對發炮時,先有一軍士橫跨一步,然後雙手由上而下重重一拉的動作,百思不得其解,乃就教英國將軍。 這位將軍沈吟道:「歷年來一直如此。」顯然也不清楚典故,只好一齊去向一位老將軍討教。
老將軍回憶道:「很久很久以前,炮是由馬拖運,發炮時怕馬驚嚇亂竄必須將馬拉緊...」
結果是,早就改汽車拖運了,這個動作卻莫名所以地保留下來。
到了岸上,為何還把船扛著在陸上行走呢?
從源頭改善
--------------------------------------------------------------------------------
作者:楊望遠
某芬芳劑製造廠,每逢玻瓶內有雜質,須於生產上線前,額外加一組人以手工清洗再吹乾,不僅速度放慢,地面濕滑,也常因趕貨,仍有洗未淨或吹未未乾的情況,因擾甚久,卻無可奈何 。
由於玻璃瓶皆為新製,理當清潔無雜質,為何需要清洗呢?一行人親訪位於新竹的工廠,追蹤雜質由何而來。
一路追蹤的結果,發現玻璃瓶工廠因新竹風大,且門窗洞開,故地上、機上、樑柱上、紙箱上...都積了一層厚厚的粉塵,在空瓶裝箱時,難免落入雜質;其次是裝車運輸過程中,紙箱偶有破損,也不免溢入粉塵;最後是存庫待用時,因進料抽檢後並未封箱,再度使有灰塵落入。
既然知道雜質的由來,解決之道並不難,也不動大工程;首先,將包裝用的紙箱用塑膠布遮蓋,不使沾塵;其次,改變裝箱方式,將瓶口向上改為向下;接著,針對運送途中的破損紙箱,個案處理;最後,存庫待用時確保密封;經過一個月的反覆要求,終能做到需清洗即可上線。
其實,企業內存在許多類似無謂的浪費,如某飲料廠及某礦泉水廠之裝瓶,亦因雜質遭客訴,竟也要求上線前須洗瓶,為何不設法從源頭去改善呢?
如果,因為有人偷東西,是否便認定偷竊合法,而拚命設法補足失竊的物品呢?難道只要積久成習,便真的可以積非成是嗎?
高待遇,高效率
--------------------------------------------------------------------------------
作者:楊望遠
一般人以為,待遇就是領多少薪水,其實不然。 社會上有不少義工,,默默地做著不支薪的工作,他們的待遇是助人的快樂與成就感。 社會上有不少有心青年,不在乎微薄的薪水,拜師勤奮學藝,他們的待遇是終身受用的一技之長。
更有不少人,期盼獲得的待遇,己不再是更高的薪水,而是
◆一展長才與抱負的良好環境。
◆肩負命、承擔重責的肯定與環境。
◆可以成為良師益友的工作夥伴,及至生活夥伴。
◆在安定中,與團體同步成長,共同邁向光明遠景。
可見,越來越少的人,只為了薪水而工作;因此,「待遇」便不只侷限在有形的物質上,而須擴大至所有能滿足人性需求的因素。
待遇高低、好壞,當然也不再取決於薪水高低、福利好壞,那些都包含在高待遇中;統括言之,取決於人性尊重的具體表現,及滿足人性需求的程度。
自古吾等皆認定「人性貪得無饜」,而極力予以壓抑;但以自主管理者的立場來看,人性只要善加疏導,則非常容易滿足,甚至「士為知己者用」,而不先討價反價,談好待遇。 如今,不少快速成長的企業皆印證「高待遇,高效率」,吾等是否還在薪水上斤斤計較,而未用心設法去真正調高待遇?
冰山效應商機大
--------------------------------------------------------------------------------
作者:楊望遠
許多人常嘆:市場就那麼,又遇上不景氣,再加上惡性競爭,生意真是做不下去了!
這些人便是典型的例了,只見到冰山露出冰面的一角,對於沈在水面下,高達十分之九的潛在市場,竟忽略去發掘。
鐵達尼號耗資兩億五千萬美金,許多市場專家都預測會血本無歸,結果是眼鏡跌落滿地,潛在商機迄今未歇。
先讓我們回顧一下各類商品市場開拓的情形:
台塑、奇美在規劃建廠時,產能往往大於市場總需求,結果因價廉物美,取代了許多傳統產品,如今,更將市場擴張至最初的千倍以上。
統一當時引進玉米製沙拉油時,誰也不信市場消化得了;如今,大宗物資採購已成為平衡中美貿易逆差的要角。
如果,每個人一生中只有兩三枝筆,寫到不能寫才換新,市場恐怕不及目前的5 %。
如果,每個人只有兩三套衣服,穿到破才買新衣,目前的成衣廠商恐怕有十分之九要倒閉。
再看看各類用品,如果都到不堪使用才更新,恐怕市場衰退的幅度大蕭條也比不上。
茲以自行車市場為例,說明潛在市場有待開發:
民國七十年左右,台灣市場不過每年二、三十萬台,直到捷安特加入,使市場擴充到五、六十萬台;近十年來,便一直維持一規模,大家也認為市場飽和了。
然而,經過評估,台灣市場當有二、三百萬台的規模,只要每個人的自行車夢能夠實現。
為何大多數人的自行車夢難償呢?有三個主要原因:
一、自行車銷售點不足。
「下次碰到自行車店就幫你買一台!」
可惜磋砣過青少年期, 購買動機亦隨年華飛逝。
二、替代品太多。
直排、機車、電腦.......,青少年的心飄忽不定,看誰能先抓住。
三、活動空間欠缺。
許多國家專設自行車道,連大陸都如此規畫;
但,台灣目前現有的,如淡水河、基隆河,亦未充分推廣呀!
真正的癥結還是第一點,若能突破通路上的不便利,相信可將許多人的潛在心願,包括成年人,一併激發出來。
--------------------------------------------------------------------------------
作者:楊望遠
在工作簡化的研討會上,總有人認為本身工作己純熟順利,不再可能改善,遑論大幅簡化了。
然而,據歸納分析,一般人的工作量中,至少有百分之五十是無效或可改善的,上百分之五十以上的人力閒置,若能完全有發揮,生產力至少提高為四倍。
為何多數人見不及此呢?實乃點滴累積,習不察也。
我有一友,喜收藏堪用之物,全屋都是寶貝,至壅塞不堪。親朋同事屢勸其整理一下,將多餘不用之物捨棄,以改善居住空間,皆見其面露苦色,無一物肯捨棄。
數月,前其不堪噪音及汙濁空氣,而於郊區購一屋一幢,且僱工裝潢得十分華麗。待搬家時,左挑右選,來回細審,無一物值得搬入新家,數十年糾纏之情結,一夕間完全割捨。
同理,若要我等從現有工作中,挑出那幾件不必做或可簡化,往往一件也難;但反過來,先將幾所有工作挪開,再挑出那裡幾件非做不可,便會發現少得多。再換一個說法,若要調往新職,又有幾件工作會隨同卦赴任?接任者是否會接下全部工作 ?
其實搬家法的效用非常適合忙碌的現代人,偶爾或定期將思慮搬家一下,將工作搬家,將檔案搬家一下...,一定會有意想不到的發現。
其歷史悠久的企業,四十餘年來,除每三年一次的粉刷外,不僅人事安定,連辦公室內陳設及工廠內布置也非常固定。某資深主管甚誇稱,閉著眼晴也能來去自如。
結果是長江後浪推前浪,一家家後起企業大幅成長=超越,讓企業的業績仍異常穩定,予人老舊不振之感。
企業若真心追求永續經營,勢將生命貫注在企業內,不斷搬動翻新,維持創新活力。總之凡事有更好的方法,當藉口工作不可能簡化改善時,請以搬家法一試。
差不多是天意
--------------------------------------------------------------------------------
作者:楊望遠
中國人處事不夠精確,凡事「差不多」。
事實上,天意即差不多,既能蘊涵變化契機,亦免於繁瑣滯礙。
如天候預測之難於精確,便是明顯例子。
其他如衣服尺碼,L、M、S,即使訂做,亦未必完全合身;每月薪水固定,但實際工作天數卻不一,信函要分平信、限時、掛號,顯示郵遞中狀況變化。
其實,國人講「差不多,差不多就好」,並非想要混水摸魚,而是不希望精準地釘死在一點,動彈不得;真正用意在能隨狀況變化不斷調適;所謂「此一時,彼一時」,不必計較一時,而求取長期的合理與均衡。
唯中國歷史文化太過悠久,致背景模糊,許多人未能追根究柢,而對「差不多」認識不清,乃有過猶不及的反應。
須知,差不多是天意,是文化的累積、經驗的傳承,亦即脈絡可循的道統,不是個人可以任意更張的。
雖然,有人標榜當今是「不確定的時代」,但「不確定即確定」;同理,差不多不離「大同小異」的原則。也因能有此理念,每個人乃能各取所需,找到最適的發展空間及彈性。
因此,個人須肯定天意的差不多,而採取精確的思考及果敢的行動,切莫淪於「差不多」的皮相,以致一事難成。
士氣衡量
--------------------------------------------------------------------------------
作者:楊望遠
常聽主管抱怨:「我們公司向心力差,士氣低落,簡直無法管理。」
於是,有人問「士氣高低如何衡量?」是憑直覺?還是靠數據?
士氣,表面上看來,的確是十分抽象,致無法具體加以衡量;但深究下去,卻不盡然。
其實,任何事物往往一體兩面,而且皆有因果關係,譬如士氣是「因」,則必有其「果」,「因」固然抽象,「果」卻是具體的,故衡量「果」,亦等於評估「因」。
我們要求士氣高昂,會產生何種結果?不外乎:
1.效率提高。
2.出勤率提高,流動率降低。
3.工作調派配合性好,爭議減少。
4.整理整頓效果顯著。
5.自動加班,適時達成任務 。
6.目標圓滿達成。
雖然,上述的「果」與其他的「因」亦有交互作用,但只要完整收集一段時間的實際過程資料,仍能分出程度高低,予以適當評比,其衡量效力是肯定的。
同理,任何抽象的事物,如向心力、教育訓練、創意、積極主動、忠勇孝悌等,皆可以其果設定衡量指標,評估出程度高低。
因此,身為主管莫再將管理不善歸咎於抽象的名詞,而當設法具體化,並用心改善管理才是。
十倍速提升競爭力
--------------------------------------------------------------------------------
作者:楊望遠
自從「十倍速時代」一書問世以來,焦點似乎集中在所謂高科技產業,而傳統產業則成了沒落不振,必須外移的族群。
然而,綜觀國內大財團,多具有傳統產業的堅實背景,不論石化、紡織、電機、車輛、製鞋、食品...,皆能雄霸一方,各領風騷,一樣具有光明前景。
那麼,比率佔97% 的中小企業,是否成了大企業的防波堤及炮灰,永遠難有出頭天?還是只要肯不斷長進,終成蛻化成為大企業?
有人說:台灣的中小企業韌性堅強,從石油危機開始,經歷了新台幣升值、勞工短缺、土地難求...,直到最近的金融風暴,似乎都能安然少事,屹立微搖。
但,換個角度看,也可說成平時只求得過且過,唯有見到棺材才拚命,卻也多能柳暗花明又一「春」;然後,又安逸地等待下一波危機。
如今,十倍速時代來臨,危機來得既急且密,幾乎是一波未平,一波又起,眼見一口氣換不過來,便將作波臣,恐怕,連好整以暇地坐以待斃都不可得,非得突破傳統隨遇而安的被動做法,必須一次拚盡全力,主動搏命突圍,方能化危為機。
但是,以前也改革過數次,如3210作戰,即效率提高30%、庫存降低20%、成本降低10%、零缺點、零傷害,似乎成效不彰;又如「全員都革新,天天有進步」,結果是煥然一新之後,成了天天有退步...,以致大家都心知肚明,不過是說說就算,頂多熱鬧一陣,不可能會是玩真的,何必卯足全勁白費力氣!
其實,以往的努力並未全然白費,只是久臨門一腳,即能水到渠成;若能拿住竅門,用對方法,不僅能快速(一至三月),而且大幅(三至二十倍)提升各方面競爭力,不必訝異疑忌,皆是可即學即用的實戰心得,一試便知!
如果,用遍地黃金來形容台灣的企業,恐怕視而不見者揉破了眼也看不到,我們將逐一引導「忙、盲、茫」的企業人去開金礦、採寶玉,一定令人目不暇給。
不過,先申明一點,開採所得須用來提升競爭力,切忌驕奢怠慢,淪作波臣!
有關單位
--------------------------------------------------------------------------------
作者:楊望遠
不知從何時開始,「有關單位」成了無所不在、無時或缺的一個有形的單位。
請看:路面坑洞,「通知有關單位處理」。
民眾請願,「轉知有關單位處理」。
兩岸貿易,「召集有關單位研究」。
治安惡化,「責成有關單位改善」。
有關單位到底有多少,到底是哪些單位,從來鮮有人去清楚,否則遊戲的趣味也沒了。
事情辦不好、沒辦成,非己之過,乃有關單位配合不足之故。
事情一延再誤、遲無下文,非己不力,乃有關單位研究討論,力求慎重,無法周全之故。
總之,不論事前、事中、事後,只要將責任推給有關單位,反正沒人清楚,大家推來推去,玩的人趣味十足,等的人可是怨氣沖天。
以IE的眼光來看,根本不該存在有關單位,任何事只有「主辦單位」,必須擔負成敗全責,沒有任何推卸的餘地。
至於事件相關單位,乃對主辦單位負責,不得作為推卸、延宕的藉口。
以「主辦責任大分類法」,凡負責比率最高者為主辦單位,任何事都能歸屬唯一主辦單位,全權負責處理。
若每一個人不再偷懶地將責任推給有關單位,而認清地直指主辦單位,相信在國家、在企業,必能因權責分明,而能有高績效。
到岸不需船
--------------------------------------------------------------------------------
作者:楊望遠
有位媳婦,每次煎魚,都把頭尾剁掉,婆婆看在眼裡,憋在心裡。終於,有一天,婆婆實在憋不住了,假作不經意地問:「煎魚為何要去頭去尾?」媳婦毫不遲疑道:「我娘家都是這麼做,可能是傳統吧!」
婆婆只好笑笑道:「你下次回娘家,問問你媽媽,看他知不知道原因。」媳婦心想婆婆急著要答案,便打電話回娘家,一問之下,連她自己都不好意思。 原來,當時因為鍋子小,不去頭去尾煎不下,想不到換了大鍋,卻忘了原因,舊習慣一直延襲下來。
十多年前,國內生產電腦主機板、監視器,都須經過燒機測試(Burn-in);量小時,空間及時間都還好解決;但,高倍成長後,如此積至壓,的確相當沈重。
有一次,筆者輔導的公司,在經營管理會上,某主管提出:「燒機房容量不夠,必須立即擴建。」但,全廠能用的空間,幾乎都滿了,怎麼辦呢? 七嘴八舌的討論,都是想什麼法子儘快擴建,筆者問了一個很外行的問題:「為什麼要Burm-in?」
大家都楞住了,最後,品保經理挺身而出答:「此乃保證品質的必要製程,避免新購不久就故障。」
筆者問:「目前測試結果,不良率有多少?」
答:「不高,約1%」
再問:「是普遍分布,還是偏向某些規格。」
答:「幾乎都是新產品、新規格、新零件。」
根據一年來的報表數據,也證實確是僅有「新」的部分不合格。
於是,運用層別管理,沒問題的部分不必再燒機,只有少部分須測試,待找出原因,改善穩定後,便可免除。
如此一來,空間空出甚多,庫存大幅降低,出貨也順暢了。 早期,因為技術尚不成熟、另件品質不穩定、分析技巧不進步,故因襲舊制,不敢擅改;久而久之,知其然,不知其所以然,失去了大好改善進步的契機。
某次,英國軍事演習,各國使節觀閱。 一位美國將軍對發炮時,先有一軍士橫跨一步,然後雙手由上而下重重一拉的動作,百思不得其解,乃就教英國將軍。 這位將軍沈吟道:「歷年來一直如此。」顯然也不清楚典故,只好一齊去向一位老將軍討教。
老將軍回憶道:「很久很久以前,炮是由馬拖運,發炮時怕馬驚嚇亂竄必須將馬拉緊...」
結果是,早就改汽車拖運了,這個動作卻莫名所以地保留下來。
到了岸上,為何還把船扛著在陸上行走呢?
從源頭改善
--------------------------------------------------------------------------------
作者:楊望遠
某芬芳劑製造廠,每逢玻瓶內有雜質,須於生產上線前,額外加一組人以手工清洗再吹乾,不僅速度放慢,地面濕滑,也常因趕貨,仍有洗未淨或吹未未乾的情況,因擾甚久,卻無可奈何 。
由於玻璃瓶皆為新製,理當清潔無雜質,為何需要清洗呢?一行人親訪位於新竹的工廠,追蹤雜質由何而來。
一路追蹤的結果,發現玻璃瓶工廠因新竹風大,且門窗洞開,故地上、機上、樑柱上、紙箱上...都積了一層厚厚的粉塵,在空瓶裝箱時,難免落入雜質;其次是裝車運輸過程中,紙箱偶有破損,也不免溢入粉塵;最後是存庫待用時,因進料抽檢後並未封箱,再度使有灰塵落入。
既然知道雜質的由來,解決之道並不難,也不動大工程;首先,將包裝用的紙箱用塑膠布遮蓋,不使沾塵;其次,改變裝箱方式,將瓶口向上改為向下;接著,針對運送途中的破損紙箱,個案處理;最後,存庫待用時確保密封;經過一個月的反覆要求,終能做到需清洗即可上線。
其實,企業內存在許多類似無謂的浪費,如某飲料廠及某礦泉水廠之裝瓶,亦因雜質遭客訴,竟也要求上線前須洗瓶,為何不設法從源頭去改善呢?
如果,因為有人偷東西,是否便認定偷竊合法,而拚命設法補足失竊的物品呢?難道只要積久成習,便真的可以積非成是嗎?
高待遇,高效率
--------------------------------------------------------------------------------
作者:楊望遠
一般人以為,待遇就是領多少薪水,其實不然。 社會上有不少義工,,默默地做著不支薪的工作,他們的待遇是助人的快樂與成就感。 社會上有不少有心青年,不在乎微薄的薪水,拜師勤奮學藝,他們的待遇是終身受用的一技之長。
更有不少人,期盼獲得的待遇,己不再是更高的薪水,而是
◆一展長才與抱負的良好環境。
◆肩負命、承擔重責的肯定與環境。
◆可以成為良師益友的工作夥伴,及至生活夥伴。
◆在安定中,與團體同步成長,共同邁向光明遠景。
可見,越來越少的人,只為了薪水而工作;因此,「待遇」便不只侷限在有形的物質上,而須擴大至所有能滿足人性需求的因素。
待遇高低、好壞,當然也不再取決於薪水高低、福利好壞,那些都包含在高待遇中;統括言之,取決於人性尊重的具體表現,及滿足人性需求的程度。
自古吾等皆認定「人性貪得無饜」,而極力予以壓抑;但以自主管理者的立場來看,人性只要善加疏導,則非常容易滿足,甚至「士為知己者用」,而不先討價反價,談好待遇。 如今,不少快速成長的企業皆印證「高待遇,高效率」,吾等是否還在薪水上斤斤計較,而未用心設法去真正調高待遇?
冰山效應商機大
--------------------------------------------------------------------------------
作者:楊望遠
許多人常嘆:市場就那麼,又遇上不景氣,再加上惡性競爭,生意真是做不下去了!
這些人便是典型的例了,只見到冰山露出冰面的一角,對於沈在水面下,高達十分之九的潛在市場,竟忽略去發掘。
鐵達尼號耗資兩億五千萬美金,許多市場專家都預測會血本無歸,結果是眼鏡跌落滿地,潛在商機迄今未歇。
先讓我們回顧一下各類商品市場開拓的情形:
台塑、奇美在規劃建廠時,產能往往大於市場總需求,結果因價廉物美,取代了許多傳統產品,如今,更將市場擴張至最初的千倍以上。
統一當時引進玉米製沙拉油時,誰也不信市場消化得了;如今,大宗物資採購已成為平衡中美貿易逆差的要角。
如果,每個人一生中只有兩三枝筆,寫到不能寫才換新,市場恐怕不及目前的5 %。
如果,每個人只有兩三套衣服,穿到破才買新衣,目前的成衣廠商恐怕有十分之九要倒閉。
再看看各類用品,如果都到不堪使用才更新,恐怕市場衰退的幅度大蕭條也比不上。
茲以自行車市場為例,說明潛在市場有待開發:
民國七十年左右,台灣市場不過每年二、三十萬台,直到捷安特加入,使市場擴充到五、六十萬台;近十年來,便一直維持一規模,大家也認為市場飽和了。
然而,經過評估,台灣市場當有二、三百萬台的規模,只要每個人的自行車夢能夠實現。
為何大多數人的自行車夢難償呢?有三個主要原因:
一、自行車銷售點不足。
「下次碰到自行車店就幫你買一台!」
可惜磋砣過青少年期, 購買動機亦隨年華飛逝。
二、替代品太多。
直排、機車、電腦.......,青少年的心飄忽不定,看誰能先抓住。
三、活動空間欠缺。
許多國家專設自行車道,連大陸都如此規畫;
但,台灣目前現有的,如淡水河、基隆河,亦未充分推廣呀!
真正的癥結還是第一點,若能突破通路上的不便利,相信可將許多人的潛在心願,包括成年人,一併激發出來。