轉錄至http://trip.5d3w.us/index.php?op=ViewArticle&articleId=171&blogId=2
覺得文章很棒!!!分享給大家
做軟體開發專案規劃時, 常會碰到助理問我一個問題, SA,SD和SE的差別在那裡 ?
這個問題我以前也有過, 還頗為困擾, 系統分析和系統設計及系統工程到底有什麼差別 ? SA和SD的工作又有何不同 ? 這兩者的養成教育又有何差異 ?在過去, SA,SD及SE的確很難區分, 甚至這些角色常常會透過軟體工程師來混合發展。
隨著IT領域的發展, SA,SD及SE漸漸的成為了大型專案必需要的專業分工, 這三者間是有相當的差異的, 不管是養成過程, 甚或是未來的發展, 都大相徑庭, 而要成為一名稱職的PM, 是要能區分出這三者的差異, 才能妥善的安排工作的。
[SA,系統分析師]
SA是 System Analysis 的縮寫, 一般稱為系統分析, 主要的工作就是透過一系列的分析工作, 把客戶想要的結果產生方式, 以各種文件表達出來, 讓開發團隊可以根據這些文件實作出這個結果。
這樣的解釋比較文縐縐一點, 用個通俗一點的方式比喻, 就像是要做出一道宮保雞丁時, 就會有食譜一樣, 裡面會介紹需要的材料及做菜的順序, 然後裡面也會強調要以怎樣手法才能產生出某種效果, 以促進色香味。
這樣的過程裡, SA是較為偏重於在工作流程和處理邏輯的, 透過SA, 開發團隊才可以理出整個系統的架構, 一種做事的脈絡, 以及系統和工作間的關連性, 最重要的, 是這些結果都會被SA呈現在文件中, 而非放在少數人的腦袋裡。
SA不僅止是要針對電腦裡的東西去運作及規劃, 還包括了現實世界裡的實體流程及組織。在很多的情況下, 配合新系統的組織及流程, 是要由SA來執行的。總結起來, 在一個開發案裡, SA執行以下的工作:
· 藉由系統需求書, 使用者的現有標準作業流程來建立出符合期望的新作業流程及搭配流程的系統功能及模組規劃
· 依據功能及模組規劃案, 定出初步的資料庫內容及系統與使用者間的權限搭配規範
· 定出各個軟體零件的規範, 如物件, 函數庫, ...等等
· 設計新的標準作業流程, 並把系統功能或模組綁入這些流程中
· S.A依據客戶的環境及需求, 尋找合適的SD來搭配
而SA也有以下的特色:
· 對於系統在怎樣的環境及用什麼開發工具, 並不十分在意, 良好的S.A產生出來的文件, 使用不同的開發工具都應該可以完成, 產生相同的結果, 但那一種最合適, 由SD決定
· SA偏重於流程及執行邏輯的表達
· SA著重於軟體邏輯, 對開發工具的學習並不是十分重要, 所以會一種語言即可, 主要是以該語言工具來實踐邏輯觀。
· SA一定要有全局觀, 也就是不能拘泥於一個角度或是一個局部去思考問題, 這一點是尋找優秀SA時最困難的。因為在規劃模組及功能時, 一定要同時考量到所有直接相關及間接相關的程序及邏輯問題, 因此要有全局觀。
相較於SD, SA更側重在邏輯及工作順序搭配的表達, SA並不需要去關切使用什麼作業系統或是什麼開發工具, 如前特色所述, 好的SA文件, 可以用任何一種開發工具來實現。當然, SA不受限於IT技術, 但卻會有專業領域的限制。
很少有SA同時專精於數個領域的, 熟悉汽車業運作規範的SA, 在金融業的開發案裡, 就很難討好, 反之亦然。但SD沒有這種限制, 基本上SD可以和任何行業的專案開發團隊配合運作。
會如此的原因是SA是偏重於流程及管理分析及重新再造工作的。而作業流程, 除了少數領域裡共通性高, 在核心流程上, 是需要長期鑽研的。前面提及的汽車及金融業就是一例。
所以, 一個SA必需具備以下的能力,資歷及專業訓練:
1. 至少熟悉一種程式開發語言
2. 熟悉軟體工程, 對於開發工具的元素及特色熟悉
3. 對管理制度或作業流程設計熟悉
4. 熟悉UML或類似的系統描述工具
5. 邏輯能力良好
6. 良好的溝通能力, 主要作為瞭解需求之用
7. 相關的業界熟悉度
在三者之中, SA是最接近PM的, 所以SA在做生涯規劃時, 不妨以PM做為下一個發展的專業目標。
[SD, 系統設計師]
一般來說, SD在生涯規劃裡, 並不是SA或是PM。當然, 一定要硬來一次也沒有什麼不可以, 但要走這條路, 就要趁早轉職, 因為SD畢竟是較為幕後的工作, 在與客戶的溝通協調上, 並不會有太高的要求, 也較不需要公司管理層面的全局觀。
表面上看起來, SD沒有SA那麼多的工作要求, 但實際上SD是最需要天賦的工作, 不管是畫面的構成, 操作的手順及調整, 甚至於元件的定義及物件的規範, 全都需要一些天賦。很多軟體, 功能很強, 但怎麼看怎麼不順眼, 或者怎麼用就怎麼憋扭, 功能帶來的效益, 全都被這些毛病給遮蓋掉了, 這就是SD的問題。
另外, SD也扮演了系統最佳化的推手。SA所規劃出來的要求及佈置, 都只是邏輯上的構思, 在不同的工具上, 可能有更好的方法可以表現, 也可能會難以展示, 這都需要藉由SD對使用環境及開發工具的瞭解, 來進行調整和規劃。
舉例來說, 同樣是一套財務軟體, 在WINDOWS XP, MAC, X WINDOWS下, 就會有很不一樣的展現模式和技巧。如果再搭配上不同的開發工具, 如C++, JAVA, .NET, PHP, ...那差異更多。對SA而言, 這些東西他都不用去考慮, 但SD就不同了, 這些不同的地方, 並不僅僅只是如此而已, 有時還會包括了開發成本及時間問題, SD的重要度, 由此可知。
在一個客製化專案裡, SD的工作內容如下:
· 設計畫面元素規範
· 設計頁面結構及規則
· 設計系統操作畫面, 並編定欄位規範及防呆處理
· 設計權限管理與系統操作機制
· 撰寫使用手冊
· 調整DB之各項定義, 使其符合畫面欄位規範及操作搭配
· 配合SA撰寫系統開發文件, 供程式師CODING之用
· 撰寫UI(使用者介面)測試計劃書
而做為一名稱職的SD, 以下的條件, 是必要的:
1. 至少對一個作業系統極為熟悉, 對於這個作業系統的各個元件特性及API, 有充分的瞭解
2. 熟悉2種以上的開發工具, 而專案所需的工具, 必需是其擅長的之一, 其熟悉度包含了標準安裝裡的各個函數庫, 系統常數, 物件定義, 語法, 主要的輔助工具開發廠商, 及重要的工具使用方法
3. 具一定的美學感
4. 至少能使用一種繪圖工具軟體
5. 曾經擔任職業軟體工程師三年以上
可以這樣說, SA給了系統靈魂和神經系統, SD則是給了系統軀體和外觀, 兩者的結合, 才能產生出正確, 美觀又好用的系統。如果你覺得自己是個不太愛和太多人打交道的IT人, 又對使用者介面有那麼點執著及天賦, 那麼, SD絕對是適合你的好選擇。
[SE, 系統工程師]
就某種角度來看, SE對PM而言, 算是萬金油, 只要做IT專案, 那就一定用得上, 差別只是要選那一個專業的SE而已。系統建置安裝要SE, 使用者環境要SE, 甚至到硬體選擇及佈建, 都要用到SE, 有什麼IT專案跟這個沒有關係呢 ?
當然, 雖然SE是到處都吃得開, 但相對的也是專案裡面最沈默及少有聲音的一群。他們的工作基本上就是建構出一個可以執行系統的環境, 系統要如何展現, SE可以給SA和SD一些建議, 但建議時機通常都是在系統運行出了些非系統可以掌握的問題後。
系統工程師基本條件上, 和SD最為接近, 但有一點不同, 就是不需要有很好的軟體開發經驗, 也就是不太需要會寫程式。但要對作業系統, 服務器系統, 網路運用環境有相當程度的瞭解。
SE通常是三者中最為博學一員, 好的SE雖然不一定要程式寫的呱呱叫, 但卻不能對編程一無所知, 對作業系統及開發工具也要有一定的熟悉度, 甚至部份網管有關的工作也要有所涉獵, 所以算得上是專案裡的萬金油。
在專案裡, SE所要執行的工作如下:
· 規劃及建置系統執行環境
· 安裝及設定使用者端環境
· SERVER安裝及設定
· 提供環境設置竟見給SA及PM
· 最佳化系統可靠度及效度
· 撰寫可靠度及效能測試計劃書
· 對電腦及相關週邊設備有一定熟悉度
而一名SE則有下列基本要求:
1. 至少熟悉一種作業系統, 尤其是讓系統的設定及微調等相關技術
2. 至少熟悉一種網路伺服器作業系統, 對如何設定及最佳化熟悉
3. 曾任軟體工程師職務一年以上或熟悉一種開發工具
4. 對網路環境有一定的認識, 尤其是一些通訊設置
5. 熟悉可靠度及效能的評估方法, 並瞭解與系統環境相關之設定
基本上, 如果擁有了像SD一樣的技術背景及個性, 但在美學上實在令人不敢恭維, 那麼SE算是極佳的選擇了。一般而言, SE的下一個生涯規劃, 會比較偏重於技術性兵種, 像是DBA或是網管, 對於IT產品比較有狂熱或愛好的人, SE是極佳的出路。
[在專案中的運用時機]
基本上SE是萬金油, 只要是IT的案子裡就一定要塞一個SE進去, 因為沒有IT專案不需要使用工程技術的, 差別只在使用何種工程技術而已。在套裝軟體的導入專案裡, SE負責處理軟體使用環境, 解決非系統性問題, 安置及調整資料庫和網路環境, 然後安裝啟動。所有系統運行所需要的條件, 都要由SE來解決和處理, 但這些工作全都不會出現在眾人的面前, 但卻又重要無比, 算得上是幕後的英雄。
會同時運用到SA,SD及SE的專案, 還是以客製化開發為主的。
在開發型專案裡, SA團隊要負責初期的需求調查及整體架構的規劃, 將所有的系統開發工作內容轉化成井井有條的文件, 並且適度的分割及派送, 並確保未來這些被分割的開發結果能夠在未來可以正確運作。
SD 則在SA的文件中去尋求系統呈現的一致性, 易用性及保證開發工具可以正確無誤的展現SA的要求結果。所以SD要負責操作界面的外觀設計, 訂定一致的展現規範, 設計系統操作畫面及操作手順, 同時配合SA完成系統開發文件。基本上, 開發文件中, 是包含系統使用手冊初稿的。
SD在設計時, 必需與SA充分配合, 以確保設計的系統符合需求及運作要求。
除了上述的工作內容外, 這三者都要撰寫測試計劃, SA著重在於資料的流動符合原先規劃的順序及結果測試, SD則著重在操作畫面中的防呆測試及操作介面的正確性, 而SE則在系統可靠度上進行規劃。
[軟體工程師何時轉職 ?]
每一個寫程式的人心裡都明白, 這工作不可能做一輩子。不單單是體力及腦力問題, 最重要的是寫程式, 經濟價值實在有限。
我不會否認有很多的程式高手, 但重點不在於你有多優秀, 而是有多少老闆願意付出和你努力成正比的薪資來顧用你。不是沒有這種工作, 而是如同鳳毛麟角, 而且, 這種工作通常你也做不久, 因為壓力太大, 消耗青春太劇烈了。
退一步來說, 你也不值得付出這麼多, 在良好的SA及SD的規劃下, 工程師只要達成一般標準, 就可以解決掉九成以上的軟體開發需求, 除非是機緣巧合, 或是你很有興趣, 否則另外那一成的工作, 你是很難有機會碰上, 或者, 就算碰上, 也沒法子養活你一輩子。
軟體工程師總有一天要轉職的, 這是他們的宿命。
當要轉職時, 他們有幾個選擇, SA, SD, SE, 出去當老闆及換一行等諸多選擇。看起來雖多, 但其實晚景淒涼, 因為寫程式都是關起來寫, 長期自閉的結果, 當他們想轉職時, 很難擁有足夠的人脈來支撐他們換個前途光明的事業。一般人羨慕IT人的高薪, 卻不曉得只是寅支卯糧, 沒有妥善的規劃, 後勢看跌的。
前面的五個選項, 基本上最後兩項只是充場面, 只有少數人才能選那兩個, 大多數軟體工程師還是要在前三者中選一個來發展的。
SA看起來最風光, 未來也是潛力最好的, 但很遺憾的, 軟體工程師裡, 只有少數人適合這個職務。因為這個工作是很需要和別人打交道的, 而好的軟體工程師通常這一點非常不擅長。
因此, 如果你自認為擅於溝通, 三姑六婆都是你的紅顏知己, 邏輯能力不錯, 又對管理有興趣, 那麼SA是你很好的選擇, 程式功力並不是你要考慮的重點。
相對的, 你對使用者介面很有心得, 而且在美感上也獲得了同事的一致讚賞, 程式功力也有那麼一點自信, 討厭和不是搞IT的人打屁聊天, 那不要懷疑, SD是你最佳的歸宿。
最後, 你覺得IT的世界對你充滿了吸引力, 無論是作業系統, 開發工具或是軟體及IT設備都是如此的吸引你, 人與人的接觸對你來說並不是人生的首要需求, 層出不窮的IT科技讓你陶醉其中, 那麼, SE絕對是你的首選。
要如何轉職, 每一個軟體工程師是要誠實面對自己的, 而不是依前途來決定自己要選什麼職務, 如果你依這種方式選, 以我個人在職場生涯的經驗, 這樣的人很難散發出光芒, 也難以有他期望的成就。所以, 現在在寫程式, 正在想要轉職的工程師, 請謹慎而且誠實的面對自己, 做出恰當的選擇。
[結語]
以上是個人提供給對於SA, SD及SE或到困惑的朋友, 做為參考及工作分配的依據。這三者的產生, 其實也是源於目前IT技術的成長過於快速, 所以必需針對軟體工程進行適切的分工, 才能應付好日益複雜的IT環境。
2011年7月26日 星期二
2011年7月25日 星期一
轉錄-提問的智慧
提問的智慧
Copyright (C) 2001 by Eric S. Raymond中文版 Copyleft 2001 by D.H.Grand(nOBODY/Ginux)英文版:http://www.tuxedo.org/~esr/faqs/smart-questions.html感謝 Eric 的耐心指點和同意,本文才得以完成並發佈,
本指南 英文版版權為 Eric Steven Raymond 所有,
中文版版權由 D.H.Grand[nOBODY/Ginux] 所有。
在黑客世界裏,當提出一個技術問題時,你能得到怎樣的回答?
這取決於挖出答案的難度,同樣取決於你提問的方法。
本指南旨在幫助你提高發問技巧,以獲取你最想要的答案。
首先你必須明白,黑客們只偏愛艱巨的任務,或者能激發他們思維的好問題。
如若不然,我們還來幹嗎?如果你有值得我們反復咀嚼玩味的好問題,
我們自會對你感激不盡。好問題是激勵,是厚禮,可以提高我們的理解力,
而且通常會暴露我們以前從沒意識到或者思考過的問題。
對黑客而言,“問得好!”是發自內心的大力稱讚。
儘管黑客們有蔑視簡單問題和不友善的壞名聲,有時看起來似乎我們對新手,
對知識貧乏者懷有敵意,但其實不是那樣的。
我們不想掩飾對這樣一些人的蔑視--他們不願思考,
或者在發問前不去完成他們應該做的事。
這種人只會謀殺時間--他們只願索取,從不付出,無端消耗我們的時間,
而我們本可以把時間用在更有趣的問題或者更值得回答的人身上。
我們稱這樣的人為“失敗者”(由於歷史原因,我們有時把它拼作“lusers”)。
我們在很大程度上屬於志願者,從繁忙的生活中抽出時間來解惑答疑,
而且時常被提問淹沒。所以我們無情的濾掉一些話題,
特別是拋棄那些看起來象失敗者的傢伙,以便更高效的利用時間來回答勝利者的問題。
如果你覺得我們過於傲慢的態度讓你不爽,讓你委屈,不妨設身處地想想。
我們並沒有要求你向我們屈服--事實上,我們中的大多數人最喜歡公平交易不過了,
只要你付出小小努力來滿足最起碼的要求,我們就會歡迎你加入到我們的文化中來?但讓我們幫助那些不願意幫助自己的人是沒有意義的。
如果你不能接受這種“歧視”,我們建議你花點錢找家商業公司簽個術支援協議得了,
別向黑客乞求 如果你決定向我們求助,當然不希望被視為失敗者,
更不願成為失敗者中的一員。立刻得到有效答案的最好方法,就是象勝利者那樣提問
—— 聰明、自信、有解決問題的思路,只是偶爾在特定的問題上需要獲得一點幫助。
(歡迎對本指南提出改進意見。任何建議請E-mail至esr@thyrsus.com,
然而 請注意,本文並非網路禮節的通用指南,我通常會拒絕無助於在技術論壇
得到有用答案的建議。) (當然,如果你寫中文,最好還是寄DHGrand@hotmail.com;-)
= 提問之前 =
在通過電郵、新聞組或者聊天室提出技術問題前,檢查你有沒有做到:
1. 通讀手冊,試著自己找答案。
2. 在FAQ裏找答案(一份維護得好的FAQ可以包羅萬象:)。
3. 在網上搜索(個人推薦google~~~)。
4. 向你身邊精於此道的朋友打聽。
當你提出問題的時候,首先要說明在此之前你幹了些什麼;
這將有助於樹立你的形象:你不是一個妄圖不勞而獲的乞討者,不願浪費別人的時間。
如果提問者能從答案中學到東西,我們更樂於回答他的問題。
周全的思考,準備好你的問題,草率的發問只能得到草率的回答,
或者根本得不到任何答案。越表現出在尋求幫助前為解決問題付出的努力,
你越能得到實質性的幫助。
小心別問錯了問題。如果你的問題基於錯誤的假設,普通黑客(J. Random Hacker)
通常會用無意義的字面解釋來答復你,心裏想著“蠢問題...”,
希望著你會從問題的回答(而非你想得到的答案)中汲取教訓。
決不要自以為夠資格得到答案,你沒這種資格。畢竟你沒有為這種服務支付任何報酬。
你要自己去“掙”回一個答案,靠提出一個有內涵的,有趣的,
有思維激勵作用的問題--一個對社區的經驗有潛在貢獻的問題,
而不僅僅是被動的從他人處索要知識--去掙到這個答案。
另一方面,表明你願意在找答案的過程中做點什麼,是一個非常好的開端。
“誰能給點提示?”、“我這個例子裏缺了什麼?”以及“我應該檢查什麼地方?”比“請把確切的過程貼出來”更容易得到答復。因為你顯得只要有人指點正確的方向,
你就有完成它的能力和決心。
= 怎樣提問 =
- 謹慎選擇論壇
小心選擇提問的場合。如果象下面描述的那樣,你很可能被忽略掉或者被看作失敗者:
1. 在風馬牛不相及的論壇貼出你的問題
2. 在探討高級技巧的論壇張貼非常初級的問題;反之亦然
3. 在太多的不同新聞組交叉張貼
- 用辭貼切,語法正確,拼寫無誤
我們從經驗中發現,粗心的寫作者通常也是馬虎的思考者(我敢打包票)。
回答粗心大意者的問題很不值得,我們寧願把時間耗在別處。
正確的拼寫,標點符號和大小寫很重要。
更一般的說,p果你的提問寫得象個半文盲,你很有可能被忽視。
如果你在使用非母語的論壇提問,你可以犯點拼寫和語法上的小錯
--但決不能在思考上馬虎(沒錯,我們能弄清兩者的分別)
- 使用含義豐富,描述準確的標題
在郵件列表或者新聞組中,大約50字以內的主題標題是抓住資深專家注意力的黃金時機。
別用喋喋不休的“幫幫忙”(更別說“救命啊!!!!!”這 樣讓人反感的話)
來浪費這個機會。不要妄想用你的痛苦程度來打動我們, 別用空格代替問題的描述,
哪怕是極其簡短的描述。
蠢問題: 救命啊!我的膝上機不能正常顯示了!
聰明問題: XFree86 4.1下滑鼠游標變形,Fooware MV1005的顯示晶片。
如果你在回復中提出問題,記得要修改內容標題,表明裏面有一個問題。
一個看起來象“Re:測試”或者“Re:新bug”的問題很難引起足夠重視。
另外,引用並刪減前文的內容,給新來的讀者留下線索。
- 精確描述,信息量大
1. 謹慎明確的描述症狀。
2. 提供問題發生的環境(機器配置、作業系統、應用程式以及別的什麼)。
3. 說明你在提問前是怎樣去研究和理解這個問題的。
4. 說明你在提問前採取了什麼步驟去解決它。
5. 羅列最近做過什麼可能有影響的硬體、軟體變更。
儘量想像一個黑客會怎樣反問你,在提問的時候預先給他答案。
Simon Tatham寫過一篇名為《如何有效的報告Bug》的出色短文。強力推薦你也讀一讀。
- 話不在多
你需要提供精確有效的資訊。這並不是要求你簡單的把成噸的出錯代碼或者資料
完全轉儲摘錄到你的提問中。如果你有龐大而複雜的測試條件,
儘量把它剪裁得越小越好。 這樣做的用處至少有三點。
第一,表現出你為簡化問題付出了努力,這可以使你得到回答的機會增加;
第二,簡化問題使你得到有用答案的機會增加;
第三,在提煉 你的bug報告的過
- 只說症狀,不說猜想
告訴黑客們你認為問題是怎樣引起的沒什麼幫助。
(如果你的推斷如此有效,還用向別人求助嗎?),
因此要確信你原原本本告訴了他們問題的症狀,不要加進你自己的理解和推論。
讓黑客們來診斷吧。
蠢問題: 我在內核編譯中一次又一次遇到SIG11錯誤,
我懷疑某條飛線搭在主板的走線上了,這種情況應該怎樣檢查最好?
聰明問題: 我自製的一套K6/233系統,主板是FIC-PA2007 (VIA Apollo VP2晶片組),
256MB Corsair PC133 SDRAM,在內核編譯中頻頻產生SIG11錯誤,
從開機20分鐘以後就有這種情況,開機 前20分鐘內從沒發生過。
重啟也沒有用,但是關機一晚上就又能工作20分鐘。所有記憶體都換過了,沒有效果。
相關部分的典型編譯記錄如下...。
- 按時間順序列出症狀
對找出問題最有幫助的線索,往往就是問題發生前的一系列操作,
因此,你的說明 應該包含操作步驟,以及電腦的反應,直到問題產生。
如果你的說明很長(超過四個段落),在開頭簡述問題會有所幫助,
接下來按時間順序詳述。這樣黑客們就知道該在你的說明中找什麼。
- 明白你想問什麼
漫無邊際的提問近乎無休無止的時間黑洞。最能給你有用答案的人也正是最忙的人
(他們忙是因為要親自完成大部分工作)。這樣的人對無節制的時間黑洞不太感冒,
因此也可以說他們對漫無邊際的提問不大感冒。
如果你明確表述需要回答者做什麼(提供建議,發送一段代碼,檢查你的補丁 或是別的)
,就最有可能得到有用的答案。
這會定出一個時間和精力的上限,便於回答者集中精力來幫你
A這很湊效。要理解專家們生活的世界,要把專業技能想像為充裕的資源,
而回復的時間則是貧乏的資源。解決你的問題需要的時間越少,
越能從忙碌的專家口中掏出答案。
因此,優化問題的結構,儘量減少專家們解決它所需要的時間,
會有很大的幫助--這通常和簡化問題有所區別。
因此,問“我想更好的理解X,能給點提示嗎?”通常比問“你能解釋一下X嗎?更好。
如果你的代碼不能工作,問問它有什麼地方不對,比要求別人替你修改要明智得多。
- 別問應該自己解決的問題
黑客們總是善於分辨哪些問題應該由你自己解決;因為我們中的大多數都曾自己解決
這類問題。同樣,這些問題得由你來搞定,你會從中學到東西。
你可以要求給點提示,但別要求得到完整的解決方案。
- 去除無意義的疑問
別用無意義的話結束提問,例如“有人能幫我嗎?”或者“有答案嗎?”。
首先:如果你對問題的描述不很合適,這樣問更是畫蛇添足。
其次:由於這 樣問是畫蛇添足,黑客們會很厭煩你--而且通常會用邏輯上正確的回答
來表 示他們的蔑視,例如:“沒錯,有人能幫你”或者“不,沒答案”。
- 謙遜絕沒有害處,而且常幫大忙
彬彬有禮,多用“請”和“先道個謝了”。
讓大家都知道你對他們花費時間義務提供幫助心存感激。
然而,如果你有很多問題無法解決,禮貌將會增加你得到有用答案的機會。
(我們注意到,自從本指南發佈後,從資深黑客處得到的唯一嚴重缺陷反饋,
就是對預先道謝這一條。一些黑客覺得“先謝了”的言外之意是過後就不會再感謝
任何人了。我們的建議是:都道謝。)
- 問題解決後,加個簡短說明
問題解決後,向所有幫助過你的人發個說明,讓他們知道問題是怎樣解決的,
並再一次向他們表示感謝。如果問題在新聞組或者郵件列表中引起了廣泛關注,
應該在那裏貼一個補充說明
。補充說明不必很長或是很深入;簡單的一句“你好,原來是網線出了問題!
謝謝大家--Bill”比什麼也不說要強。事實上,除非結論真的很有技術含量,
否則簡短可愛的小結比長篇學
術論文更好。說明問題是怎樣解決的,但大可不必將解決問題的過程復述一遍。
除了表示禮貌和反饋資訊以外,這種補充有助於他人在郵件列表/新聞組/論壇中搜索
對你有過幫助的完整
解決方案,這可能對他們也很有用。最後(至少?),
這種補充有助於所有提供過幫助的人從中得到滿足感。
如果你自己不是老手或者黑客,那就相信我們,這種感覺對於那些你向他們
求助的導師或者專家而言,是非常重要的。問題久拖未決會讓人灰心;
黑客們渴望看到問題被解決。好人有好報,滿足他們的渴望,
你會在下次貼出新問題時嘗到甜頭。
- 還是不懂
如果你不是很理解答案,別立刻要求對方解釋。
象你以前試著自己解決問題時那樣(利用手冊,FAQ,網路,身邊的高手),
去理解它。如果你真的需要對方解釋,記得表現出你已經學
鴗F點什麼。比方說,如果我回答你:“看來似乎是zEntry被阻塞了;
你應該先清除它。”,然後:一個很糟的後續問題:“zEntry是什麼?”聰明的問法應該是這樣:“哦~~~我看過幫助了但是只有-z和-p兩個參數中
提到了zEntry而且還都沒有清楚的解釋:<你是指這兩個中的哪一個嗎?
還是我看漏了什麼?”
=三思而後問 =
以下是幾個經典蠢問題,以及黑客在拒絕回答時的心中所想:
問題:我能在哪找到X程式?
問題:我的程式/配置/SQL申明沒有用
問題:我的Windows有問題,你能幫我嗎?
問題:我在安裝Linux(或者X)時有問題,你能幫我嗎?
問題:我怎麼才能破解root帳號/竊取OP特權/讀別人的郵件呢?
提問:我能在哪找到X程式?
回答:就在我找到它的地方啊蠢貨--搜索引擎的那一頭。天?!還有人不會用Google嗎?
提問:我的程式(配置、SQL申明)沒有用
回答:這不算是問題吧,我對找出你的真正問題沒興趣--如果要我問你二十個問題
才找得出來的話--我有更有意思的事要做呢。
在看到這類問題的時候,我的反應通常不外如下三種
1. 你還有什麼要補充的嗎?
2. 真糟糕,希望你能搞定。
3. 這跟我有什麼鳥相關?
提問:我的Windows有問題,你能幫我嗎?
回答:能啊,扔掉萎軟的垃圾,換Linux吧。
提問:我在安裝Linux(或者X)時有問題,你能幫我嗎?
回答:不能,我只有親自在你的電腦上動手才能找到毛病。
還是去找你當地的Linux用戶組尋求手把手的指導吧(你能在這兒找到用戶組的清單)。
提問:我怎麼才能破解root帳號/竊取OP特權/讀別人的郵件呢?
回答:想要這樣做,說明你是個卑鄙小人;想找個黑客幫你,說明你是個白癡!
= 好問題,壞問題 =
最後,我舉一些例子來說明,怎樣聰明的提問;
同一個問題的兩種問法被放在一起,一種是愚蠢的,另一種才是明智的。
蠢問題:我可以在哪兒找到關於Foonly Flurbamatic的資料?
// 這種問法無非想得到“STFW”這樣的回答。
聰明問題:我用Google搜索過“Foonly Flurbamatic 2600”,
但是沒找到有用的結果。誰知道上哪兒去找對這種設備編程的資料?
// 這個問題已經STFW過了,看起來他真的遇到了麻煩。
蠢問題:我從FOO項目找來的源碼沒法編譯。它怎麼這麼爛?
// 他覺得都是別人的錯,這個傲慢自大的傢伙
聰明問題:FOO專案代碼在Nulix 6.2版下無法編譯通過。
我讀過了FAQ,但裏面沒有提到跟Nulix有關的問題。
這是我編譯過程的記錄,我有什麼做得不對的地方嗎?
// 他講明瞭環境,也讀過了FAQ,還指明了錯誤,
並且他沒有把問題的責任推到別人頭上,這個傢伙值得留意。
蠢問題:我的主板有問題了,誰來幫我?
// 普通黑客對這類問題的回答通常是:“好的,還要幫你拍拍背和換尿布嗎?”
,然後按下刪除鍵。
聰明問題:我在S2464主板上試過了X、Y和Z,但沒什麼作用,
我又試了A、B和C。請注意當我嘗試C時的奇怪現象。顯然邊帶傳輸中出現了收縮,
但結果出人意料。在多處理器主板上引起邊帶洩漏的通常原因是什麼?
誰有好主意接下來我該做些什麼測試才能找出問題?
// 這個傢伙,從另一個角度來看,值得去回答他。他表現出了解決問題的能力,
而不是坐等天上掉答案。
在最後一個問題中,注意“告訴我答案”和“給我啟示,指出我還應該做什麼診斷工作”之間微妙而又重要的區別。
事實上,後一個問題源自於2001年8月在Linux內核郵件列表上的一個真實的提問。
我(Eric)就是那個提出問題的人。我在Tyan S2464主板上觀察到了這種無法解釋的
鎖定現象,列表成員們提供了解決那一問題的重要資訊。
通過我的提問方法,我給了大家值得玩味的東西;我讓人們很容易參與並且被吸引進來。
我顯示了自己具備和他們同等的能力,邀請他們與我共同探討。
我告訴他們我所走過的彎路,以避免他們再浪費時間,這是一種對他人時間價值的尊重。
後來,當我向每個人表示感謝,並且讚賞這套程式(指郵件列表中的討論
--譯者注)運作得非常出色的時候,一個Linux內核?件列(lkml)成員表示,問題得到解決並非由於我是這個列表中的“名人”,
而是因為我用了正確的方式來提問。
我們黑客從某種角度來說是擁有豐富知識但缺乏人情味的傢伙;我相信
他是對的,如果我象個乞討者那樣提問,不論我是誰,一定會惹惱某些人
或者被他們忽視。他建議我記下這件事,給編寫這個指南的人一些指導。
= 找不到答案怎麼辦 =
如果仍得不到答案,請不要以為我們覺得無法幫助你。
有時只是看到你問題的人不知道答案罷了。沒有回應不代表你被忽視,
雖然不可否認這種差別很難區分。
總的說來,簡單的重複張貼問題是個很糟的想法。這將被視為無意義的喧鬧。
你可以通過其他渠道獲得幫助,這些渠道通常更適合初學者的需要。
有許多網上的以及本地的用戶組,由狂熱的軟體愛好者
(即使他們可能從沒親自寫過任何軟體)組成。通常人們組建
這樣的團體來互相幫助並幫助新手。
另外,你可以向很多商業公司尋求幫助,不論公司大還是小
(Red Hat 和LinuxCare 就是兩個最常見的例子)。
別為要付費才能獲得幫助而感到沮喪!畢竟,假使你的汽車發動機汽缸密
封圈爆掉了--完全可能如此--你還得把它送到修車鋪,並且為維修付費。
就算軟體沒花費你一分錢,你也不能強求技術支援總是免費的。
對大眾化的軟體,就象Linux之類而言,每個開發者至少會有上萬名用戶。
根本不可能由一個人來處理來自上萬名用戶的求助電話。
要知道,即使你要為幫助付費,同你必須購買同類軟體相比,
你所付出的也是微不足道的(通常封閉源代碼軟體的技術支援費用比開放源代碼軟體
要高得多,且內容也不那麼豐富)。
RTFM和STFW:別煩我啦
有一個古老而神聖的傳統:如果你收到“RTFM (Read The Fucking Manual)”的
回復,回答者認為你應該去讀TMD手冊。當然,基本上他是對的,你應該讀一讀。
RTFM有一個年輕的親戚。如果答案是“STFW (Search The Fucking Web)”,回
答者認為你應該到TMD的網上去搜索。基本上,他也是對的,你就去找吧。
通常,用這兩句之一回答你的人會給你一份包含你需要內容的手冊或者一個網址,
而且他們打這些字的時候正在閱讀著。
這些答復意味著回答者認為(1). 你需要的 資訊非常容易獲得;
(2). 你自己去搜索這些資訊比灌給你能讓你學到更多。
別為這個而不爽;依照黑客的標準,他沒有對你的要求視而不見,已經能大致能表
示對你的關注。你應該對他祖母般的慈祥表示感謝。
Copyright (C) 2001 by Eric S. Raymond中文版 Copyleft 2001 by D.H.Grand(nOBODY/Ginux)英文版:http://www.tuxedo.org/~esr/faqs/smart-questions.html感謝 Eric 的耐心指點和同意,本文才得以完成並發佈,
本指南 英文版版權為 Eric Steven Raymond 所有,
中文版版權由 D.H.Grand[nOBODY/Ginux] 所有。
在黑客世界裏,當提出一個技術問題時,你能得到怎樣的回答?
這取決於挖出答案的難度,同樣取決於你提問的方法。
本指南旨在幫助你提高發問技巧,以獲取你最想要的答案。
首先你必須明白,黑客們只偏愛艱巨的任務,或者能激發他們思維的好問題。
如若不然,我們還來幹嗎?如果你有值得我們反復咀嚼玩味的好問題,
我們自會對你感激不盡。好問題是激勵,是厚禮,可以提高我們的理解力,
而且通常會暴露我們以前從沒意識到或者思考過的問題。
對黑客而言,“問得好!”是發自內心的大力稱讚。
儘管黑客們有蔑視簡單問題和不友善的壞名聲,有時看起來似乎我們對新手,
對知識貧乏者懷有敵意,但其實不是那樣的。
我們不想掩飾對這樣一些人的蔑視--他們不願思考,
或者在發問前不去完成他們應該做的事。
這種人只會謀殺時間--他們只願索取,從不付出,無端消耗我們的時間,
而我們本可以把時間用在更有趣的問題或者更值得回答的人身上。
我們稱這樣的人為“失敗者”(由於歷史原因,我們有時把它拼作“lusers”)。
我們在很大程度上屬於志願者,從繁忙的生活中抽出時間來解惑答疑,
而且時常被提問淹沒。所以我們無情的濾掉一些話題,
特別是拋棄那些看起來象失敗者的傢伙,以便更高效的利用時間來回答勝利者的問題。
如果你覺得我們過於傲慢的態度讓你不爽,讓你委屈,不妨設身處地想想。
我們並沒有要求你向我們屈服--事實上,我們中的大多數人最喜歡公平交易不過了,
只要你付出小小努力來滿足最起碼的要求,我們就會歡迎你加入到我們的文化中來?但讓我們幫助那些不願意幫助自己的人是沒有意義的。
如果你不能接受這種“歧視”,我們建議你花點錢找家商業公司簽個術支援協議得了,
別向黑客乞求 如果你決定向我們求助,當然不希望被視為失敗者,
更不願成為失敗者中的一員。立刻得到有效答案的最好方法,就是象勝利者那樣提問
—— 聰明、自信、有解決問題的思路,只是偶爾在特定的問題上需要獲得一點幫助。
(歡迎對本指南提出改進意見。任何建議請E-mail至esr@thyrsus.com,
然而 請注意,本文並非網路禮節的通用指南,我通常會拒絕無助於在技術論壇
得到有用答案的建議。) (當然,如果你寫中文,最好還是寄DHGrand@hotmail.com;-)
= 提問之前 =
在通過電郵、新聞組或者聊天室提出技術問題前,檢查你有沒有做到:
1. 通讀手冊,試著自己找答案。
2. 在FAQ裏找答案(一份維護得好的FAQ可以包羅萬象:)。
3. 在網上搜索(個人推薦google~~~)。
4. 向你身邊精於此道的朋友打聽。
當你提出問題的時候,首先要說明在此之前你幹了些什麼;
這將有助於樹立你的形象:你不是一個妄圖不勞而獲的乞討者,不願浪費別人的時間。
如果提問者能從答案中學到東西,我們更樂於回答他的問題。
周全的思考,準備好你的問題,草率的發問只能得到草率的回答,
或者根本得不到任何答案。越表現出在尋求幫助前為解決問題付出的努力,
你越能得到實質性的幫助。
小心別問錯了問題。如果你的問題基於錯誤的假設,普通黑客(J. Random Hacker)
通常會用無意義的字面解釋來答復你,心裏想著“蠢問題...”,
希望著你會從問題的回答(而非你想得到的答案)中汲取教訓。
決不要自以為夠資格得到答案,你沒這種資格。畢竟你沒有為這種服務支付任何報酬。
你要自己去“掙”回一個答案,靠提出一個有內涵的,有趣的,
有思維激勵作用的問題--一個對社區的經驗有潛在貢獻的問題,
而不僅僅是被動的從他人處索要知識--去掙到這個答案。
另一方面,表明你願意在找答案的過程中做點什麼,是一個非常好的開端。
“誰能給點提示?”、“我這個例子裏缺了什麼?”以及“我應該檢查什麼地方?”比“請把確切的過程貼出來”更容易得到答復。因為你顯得只要有人指點正確的方向,
你就有完成它的能力和決心。
= 怎樣提問 =
- 謹慎選擇論壇
小心選擇提問的場合。如果象下面描述的那樣,你很可能被忽略掉或者被看作失敗者:
1. 在風馬牛不相及的論壇貼出你的問題
2. 在探討高級技巧的論壇張貼非常初級的問題;反之亦然
3. 在太多的不同新聞組交叉張貼
- 用辭貼切,語法正確,拼寫無誤
我們從經驗中發現,粗心的寫作者通常也是馬虎的思考者(我敢打包票)。
回答粗心大意者的問題很不值得,我們寧願把時間耗在別處。
正確的拼寫,標點符號和大小寫很重要。
更一般的說,p果你的提問寫得象個半文盲,你很有可能被忽視。
如果你在使用非母語的論壇提問,你可以犯點拼寫和語法上的小錯
--但決不能在思考上馬虎(沒錯,我們能弄清兩者的分別)
- 使用含義豐富,描述準確的標題
在郵件列表或者新聞組中,大約50字以內的主題標題是抓住資深專家注意力的黃金時機。
別用喋喋不休的“幫幫忙”(更別說“救命啊!!!!!”這 樣讓人反感的話)
來浪費這個機會。不要妄想用你的痛苦程度來打動我們, 別用空格代替問題的描述,
哪怕是極其簡短的描述。
蠢問題: 救命啊!我的膝上機不能正常顯示了!
聰明問題: XFree86 4.1下滑鼠游標變形,Fooware MV1005的顯示晶片。
如果你在回復中提出問題,記得要修改內容標題,表明裏面有一個問題。
一個看起來象“Re:測試”或者“Re:新bug”的問題很難引起足夠重視。
另外,引用並刪減前文的內容,給新來的讀者留下線索。
- 精確描述,信息量大
1. 謹慎明確的描述症狀。
2. 提供問題發生的環境(機器配置、作業系統、應用程式以及別的什麼)。
3. 說明你在提問前是怎樣去研究和理解這個問題的。
4. 說明你在提問前採取了什麼步驟去解決它。
5. 羅列最近做過什麼可能有影響的硬體、軟體變更。
儘量想像一個黑客會怎樣反問你,在提問的時候預先給他答案。
Simon Tatham寫過一篇名為《如何有效的報告Bug》的出色短文。強力推薦你也讀一讀。
- 話不在多
你需要提供精確有效的資訊。這並不是要求你簡單的把成噸的出錯代碼或者資料
完全轉儲摘錄到你的提問中。如果你有龐大而複雜的測試條件,
儘量把它剪裁得越小越好。 這樣做的用處至少有三點。
第一,表現出你為簡化問題付出了努力,這可以使你得到回答的機會增加;
第二,簡化問題使你得到有用答案的機會增加;
第三,在提煉 你的bug報告的過
- 只說症狀,不說猜想
告訴黑客們你認為問題是怎樣引起的沒什麼幫助。
(如果你的推斷如此有效,還用向別人求助嗎?),
因此要確信你原原本本告訴了他們問題的症狀,不要加進你自己的理解和推論。
讓黑客們來診斷吧。
蠢問題: 我在內核編譯中一次又一次遇到SIG11錯誤,
我懷疑某條飛線搭在主板的走線上了,這種情況應該怎樣檢查最好?
聰明問題: 我自製的一套K6/233系統,主板是FIC-PA2007 (VIA Apollo VP2晶片組),
256MB Corsair PC133 SDRAM,在內核編譯中頻頻產生SIG11錯誤,
從開機20分鐘以後就有這種情況,開機 前20分鐘內從沒發生過。
重啟也沒有用,但是關機一晚上就又能工作20分鐘。所有記憶體都換過了,沒有效果。
相關部分的典型編譯記錄如下...。
- 按時間順序列出症狀
對找出問題最有幫助的線索,往往就是問題發生前的一系列操作,
因此,你的說明 應該包含操作步驟,以及電腦的反應,直到問題產生。
如果你的說明很長(超過四個段落),在開頭簡述問題會有所幫助,
接下來按時間順序詳述。這樣黑客們就知道該在你的說明中找什麼。
- 明白你想問什麼
漫無邊際的提問近乎無休無止的時間黑洞。最能給你有用答案的人也正是最忙的人
(他們忙是因為要親自完成大部分工作)。這樣的人對無節制的時間黑洞不太感冒,
因此也可以說他們對漫無邊際的提問不大感冒。
如果你明確表述需要回答者做什麼(提供建議,發送一段代碼,檢查你的補丁 或是別的)
,就最有可能得到有用的答案。
這會定出一個時間和精力的上限,便於回答者集中精力來幫你
A這很湊效。要理解專家們生活的世界,要把專業技能想像為充裕的資源,
而回復的時間則是貧乏的資源。解決你的問題需要的時間越少,
越能從忙碌的專家口中掏出答案。
因此,優化問題的結構,儘量減少專家們解決它所需要的時間,
會有很大的幫助--這通常和簡化問題有所區別。
因此,問“我想更好的理解X,能給點提示嗎?”通常比問“你能解釋一下X嗎?更好。
如果你的代碼不能工作,問問它有什麼地方不對,比要求別人替你修改要明智得多。
- 別問應該自己解決的問題
黑客們總是善於分辨哪些問題應該由你自己解決;因為我們中的大多數都曾自己解決
這類問題。同樣,這些問題得由你來搞定,你會從中學到東西。
你可以要求給點提示,但別要求得到完整的解決方案。
- 去除無意義的疑問
別用無意義的話結束提問,例如“有人能幫我嗎?”或者“有答案嗎?”。
首先:如果你對問題的描述不很合適,這樣問更是畫蛇添足。
其次:由於這 樣問是畫蛇添足,黑客們會很厭煩你--而且通常會用邏輯上正確的回答
來表 示他們的蔑視,例如:“沒錯,有人能幫你”或者“不,沒答案”。
- 謙遜絕沒有害處,而且常幫大忙
彬彬有禮,多用“請”和“先道個謝了”。
讓大家都知道你對他們花費時間義務提供幫助心存感激。
然而,如果你有很多問題無法解決,禮貌將會增加你得到有用答案的機會。
(我們注意到,自從本指南發佈後,從資深黑客處得到的唯一嚴重缺陷反饋,
就是對預先道謝這一條。一些黑客覺得“先謝了”的言外之意是過後就不會再感謝
任何人了。我們的建議是:都道謝。)
- 問題解決後,加個簡短說明
問題解決後,向所有幫助過你的人發個說明,讓他們知道問題是怎樣解決的,
並再一次向他們表示感謝。如果問題在新聞組或者郵件列表中引起了廣泛關注,
應該在那裏貼一個補充說明
。補充說明不必很長或是很深入;簡單的一句“你好,原來是網線出了問題!
謝謝大家--Bill”比什麼也不說要強。事實上,除非結論真的很有技術含量,
否則簡短可愛的小結比長篇學
術論文更好。說明問題是怎樣解決的,但大可不必將解決問題的過程復述一遍。
除了表示禮貌和反饋資訊以外,這種補充有助於他人在郵件列表/新聞組/論壇中搜索
對你有過幫助的完整
解決方案,這可能對他們也很有用。最後(至少?),
這種補充有助於所有提供過幫助的人從中得到滿足感。
如果你自己不是老手或者黑客,那就相信我們,這種感覺對於那些你向他們
求助的導師或者專家而言,是非常重要的。問題久拖未決會讓人灰心;
黑客們渴望看到問題被解決。好人有好報,滿足他們的渴望,
你會在下次貼出新問題時嘗到甜頭。
- 還是不懂
如果你不是很理解答案,別立刻要求對方解釋。
象你以前試著自己解決問題時那樣(利用手冊,FAQ,網路,身邊的高手),
去理解它。如果你真的需要對方解釋,記得表現出你已經學
鴗F點什麼。比方說,如果我回答你:“看來似乎是zEntry被阻塞了;
你應該先清除它。”,然後:一個很糟的後續問題:“zEntry是什麼?”聰明的問法應該是這樣:“哦~~~我看過幫助了但是只有-z和-p兩個參數中
提到了zEntry而且還都沒有清楚的解釋:<你是指這兩個中的哪一個嗎?
還是我看漏了什麼?”
=三思而後問 =
以下是幾個經典蠢問題,以及黑客在拒絕回答時的心中所想:
問題:我能在哪找到X程式?
問題:我的程式/配置/SQL申明沒有用
問題:我的Windows有問題,你能幫我嗎?
問題:我在安裝Linux(或者X)時有問題,你能幫我嗎?
問題:我怎麼才能破解root帳號/竊取OP特權/讀別人的郵件呢?
提問:我能在哪找到X程式?
回答:就在我找到它的地方啊蠢貨--搜索引擎的那一頭。天?!還有人不會用Google嗎?
提問:我的程式(配置、SQL申明)沒有用
回答:這不算是問題吧,我對找出你的真正問題沒興趣--如果要我問你二十個問題
才找得出來的話--我有更有意思的事要做呢。
在看到這類問題的時候,我的反應通常不外如下三種
1. 你還有什麼要補充的嗎?
2. 真糟糕,希望你能搞定。
3. 這跟我有什麼鳥相關?
提問:我的Windows有問題,你能幫我嗎?
回答:能啊,扔掉萎軟的垃圾,換Linux吧。
提問:我在安裝Linux(或者X)時有問題,你能幫我嗎?
回答:不能,我只有親自在你的電腦上動手才能找到毛病。
還是去找你當地的Linux用戶組尋求手把手的指導吧(你能在這兒找到用戶組的清單)。
提問:我怎麼才能破解root帳號/竊取OP特權/讀別人的郵件呢?
回答:想要這樣做,說明你是個卑鄙小人;想找個黑客幫你,說明你是個白癡!
= 好問題,壞問題 =
最後,我舉一些例子來說明,怎樣聰明的提問;
同一個問題的兩種問法被放在一起,一種是愚蠢的,另一種才是明智的。
蠢問題:我可以在哪兒找到關於Foonly Flurbamatic的資料?
// 這種問法無非想得到“STFW”這樣的回答。
聰明問題:我用Google搜索過“Foonly Flurbamatic 2600”,
但是沒找到有用的結果。誰知道上哪兒去找對這種設備編程的資料?
// 這個問題已經STFW過了,看起來他真的遇到了麻煩。
蠢問題:我從FOO項目找來的源碼沒法編譯。它怎麼這麼爛?
// 他覺得都是別人的錯,這個傲慢自大的傢伙
聰明問題:FOO專案代碼在Nulix 6.2版下無法編譯通過。
我讀過了FAQ,但裏面沒有提到跟Nulix有關的問題。
這是我編譯過程的記錄,我有什麼做得不對的地方嗎?
// 他講明瞭環境,也讀過了FAQ,還指明了錯誤,
並且他沒有把問題的責任推到別人頭上,這個傢伙值得留意。
蠢問題:我的主板有問題了,誰來幫我?
// 普通黑客對這類問題的回答通常是:“好的,還要幫你拍拍背和換尿布嗎?”
,然後按下刪除鍵。
聰明問題:我在S2464主板上試過了X、Y和Z,但沒什麼作用,
我又試了A、B和C。請注意當我嘗試C時的奇怪現象。顯然邊帶傳輸中出現了收縮,
但結果出人意料。在多處理器主板上引起邊帶洩漏的通常原因是什麼?
誰有好主意接下來我該做些什麼測試才能找出問題?
// 這個傢伙,從另一個角度來看,值得去回答他。他表現出了解決問題的能力,
而不是坐等天上掉答案。
在最後一個問題中,注意“告訴我答案”和“給我啟示,指出我還應該做什麼診斷工作”之間微妙而又重要的區別。
事實上,後一個問題源自於2001年8月在Linux內核郵件列表上的一個真實的提問。
我(Eric)就是那個提出問題的人。我在Tyan S2464主板上觀察到了這種無法解釋的
鎖定現象,列表成員們提供了解決那一問題的重要資訊。
通過我的提問方法,我給了大家值得玩味的東西;我讓人們很容易參與並且被吸引進來。
我顯示了自己具備和他們同等的能力,邀請他們與我共同探討。
我告訴他們我所走過的彎路,以避免他們再浪費時間,這是一種對他人時間價值的尊重。
後來,當我向每個人表示感謝,並且讚賞這套程式(指郵件列表中的討論
--譯者注)運作得非常出色的時候,一個Linux內核?件列(lkml)成員表示,問題得到解決並非由於我是這個列表中的“名人”,
而是因為我用了正確的方式來提問。
我們黑客從某種角度來說是擁有豐富知識但缺乏人情味的傢伙;我相信
他是對的,如果我象個乞討者那樣提問,不論我是誰,一定會惹惱某些人
或者被他們忽視。他建議我記下這件事,給編寫這個指南的人一些指導。
= 找不到答案怎麼辦 =
如果仍得不到答案,請不要以為我們覺得無法幫助你。
有時只是看到你問題的人不知道答案罷了。沒有回應不代表你被忽視,
雖然不可否認這種差別很難區分。
總的說來,簡單的重複張貼問題是個很糟的想法。這將被視為無意義的喧鬧。
你可以通過其他渠道獲得幫助,這些渠道通常更適合初學者的需要。
有許多網上的以及本地的用戶組,由狂熱的軟體愛好者
(即使他們可能從沒親自寫過任何軟體)組成。通常人們組建
這樣的團體來互相幫助並幫助新手。
另外,你可以向很多商業公司尋求幫助,不論公司大還是小
(Red Hat 和LinuxCare 就是兩個最常見的例子)。
別為要付費才能獲得幫助而感到沮喪!畢竟,假使你的汽車發動機汽缸密
封圈爆掉了--完全可能如此--你還得把它送到修車鋪,並且為維修付費。
就算軟體沒花費你一分錢,你也不能強求技術支援總是免費的。
對大眾化的軟體,就象Linux之類而言,每個開發者至少會有上萬名用戶。
根本不可能由一個人來處理來自上萬名用戶的求助電話。
要知道,即使你要為幫助付費,同你必須購買同類軟體相比,
你所付出的也是微不足道的(通常封閉源代碼軟體的技術支援費用比開放源代碼軟體
要高得多,且內容也不那麼豐富)。
RTFM和STFW:別煩我啦
有一個古老而神聖的傳統:如果你收到“RTFM (Read The Fucking Manual)”的
回復,回答者認為你應該去讀TMD手冊。當然,基本上他是對的,你應該讀一讀。
RTFM有一個年輕的親戚。如果答案是“STFW (Search The Fucking Web)”,回
答者認為你應該到TMD的網上去搜索。基本上,他也是對的,你就去找吧。
通常,用這兩句之一回答你的人會給你一份包含你需要內容的手冊或者一個網址,
而且他們打這些字的時候正在閱讀著。
這些答復意味著回答者認為(1). 你需要的 資訊非常容易獲得;
(2). 你自己去搜索這些資訊比灌給你能讓你學到更多。
別為這個而不爽;依照黑客的標準,他沒有對你的要求視而不見,已經能大致能表
示對你的關注。你應該對他祖母般的慈祥表示感謝。
2011年7月16日 星期六
轉錄-JavaScript製作動態選項的三種方法
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style type="text/css">
body{font-family:Courier New, Courier}
select{font-size:8pt;font-family:Courier New, Courier}
input{font-size:8pt;font-family:Courier New, Courier}
</style>
<SCRIPT LANGUAGE="JavaScript">
<!--
var opttext= new Array(1000);
var optvalue=new Array(1000);
function change(object){
opt=object.options[object.selectedIndex];
alert(opt.value+" : "+opt.text);
}
for(i=0;i<opttext.length;i++)
{
opttext[i]="zosatapo"+i;
optvalue[i]="name"+i;
}
function option(){
var opt;
var start;
var end;
start=new Date();
selContainer.innerHTML="";
selContainer.innerHTML="<select id='selShow' onchange='change(this);'></select>";
for(i=0;i<opttext.length;i++)
{ opt=new Option();
//or you may code like below:
//opt=document.createElement("OPTION");
opt.text=opttext[i];
opt.value=optvalue[i];
selShow.options.add(opt);
}
end=new Date();
optionTime.innerText="The Operation Took Time:"+(end.getTime()-start.getTime())+" milliseconds";
}
function object()
{
var start;
var end;
var str="<select id='selShow' onchange='change(this);'>";
start=new Date();
selContainer.innerHTML="";
for(i=0;i<opttext.length;i++)
{
str+="<option value='"+optvalue[i]+"'>"+opttext[i]+"</option>";
}
str+="</select>";
selContainer.innerHTML=str;
end=new Date();
objectTime.innerText="The Operation Took Time:"+(end.getTime()-start.getTime())+" milliseconds";
}
function join()
{
var len=opttext.length;
var arr=new Array(len);
var start;
var end;
start=new Date();
selContainer.innerHTML="";
joinTime.innerText="";
for(i=0;i<len;i++)
{
arr[i]="<option value='"+optvalue[i]+"'>"+opttext[i]+"</option>";
}
selContainer.innerHTML="<select id='selShow' onchange='change(this);'>"+arr.join()+"</select>";
end=new Date();
joinTime.innerText="The Operation Took Time:"+(end.getTime()-start.getTime())+" milliseconds";
}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<p align=center><B><FONT SIZE=4>生成SELECT</FONT></B></p>
Method I:<font color=blue> options.add()</font><br>
<Input type="Button" value="New Option" onclick="option();">
<span id="optionTime">test</span><br><BR>
Method I:<font color=blue>object.innerHTML</font><br>
<Input type="Button" value="Object InnerHTML" onclick="object();">
<span id="objectTime">test</span><br><BR>
Method I:<font color=blue>object.innerHTML & Array.join()</font><br>
<Input type="Button" value="Array Join" onclick="join();">
<span id="joinTime"><a href=#>test</a></span><br><BR>
<font color=blue>演示效果:</font><br><br>
<span id="selContainer">
<select id="selShow"><option >Empty</option></select>
</span>
</BODY>
</HTML>
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style type="text/css">
body{font-family:Courier New, Courier}
select{font-size:8pt;font-family:Courier New, Courier}
input{font-size:8pt;font-family:Courier New, Courier}
</style>
<SCRIPT LANGUAGE="JavaScript">
<!--
var opttext= new Array(1000);
var optvalue=new Array(1000);
function change(object){
opt=object.options[object.selectedIndex];
alert(opt.value+" : "+opt.text);
}
for(i=0;i<opttext.length;i++)
{
opttext[i]="zosatapo"+i;
optvalue[i]="name"+i;
}
function option(){
var opt;
var start;
var end;
start=new Date();
selContainer.innerHTML="";
selContainer.innerHTML="<select id='selShow' onchange='change(this);'></select>";
for(i=0;i<opttext.length;i++)
{ opt=new Option();
//or you may code like below:
//opt=document.createElement("OPTION");
opt.text=opttext[i];
opt.value=optvalue[i];
selShow.options.add(opt);
}
end=new Date();
optionTime.innerText="The Operation Took Time:"+(end.getTime()-start.getTime())+" milliseconds";
}
function object()
{
var start;
var end;
var str="<select id='selShow' onchange='change(this);'>";
start=new Date();
selContainer.innerHTML="";
for(i=0;i<opttext.length;i++)
{
str+="<option value='"+optvalue[i]+"'>"+opttext[i]+"</option>";
}
str+="</select>";
selContainer.innerHTML=str;
end=new Date();
objectTime.innerText="The Operation Took Time:"+(end.getTime()-start.getTime())+" milliseconds";
}
function join()
{
var len=opttext.length;
var arr=new Array(len);
var start;
var end;
start=new Date();
selContainer.innerHTML="";
joinTime.innerText="";
for(i=0;i<len;i++)
{
arr[i]="<option value='"+optvalue[i]+"'>"+opttext[i]+"</option>";
}
selContainer.innerHTML="<select id='selShow' onchange='change(this);'>"+arr.join()+"</select>";
end=new Date();
joinTime.innerText="The Operation Took Time:"+(end.getTime()-start.getTime())+" milliseconds";
}
//-->
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<p align=center><B><FONT SIZE=4>生成SELECT</FONT></B></p>
Method I:<font color=blue> options.add()</font><br>
<Input type="Button" value="New Option" onclick="option();">
<span id="optionTime">test</span><br><BR>
Method I:<font color=blue>object.innerHTML</font><br>
<Input type="Button" value="Object InnerHTML" onclick="object();">
<span id="objectTime">test</span><br><BR>
Method I:<font color=blue>object.innerHTML & Array.join()</font><br>
<Input type="Button" value="Array Join" onclick="join();">
<span id="joinTime"><a href=#>test</a></span><br><BR>
<font color=blue>演示效果:</font><br><br>
<span id="selContainer">
<select id="selShow"><option >Empty</option></select>
</span>
</BODY>
</HTML>
轉錄-解決並分析mysqld-nt.exe大量佔用CPU問題
轉錄 from http://www.k666.com/
早上幫朋友一台服務器解決了Mysql cpu 佔用100% 的問題,稍整理如下,希望對各位有所幫助。
朋友主機(Windows 2003 + IIS + PHP + MYSQL )近來MySQL 服務進程(mysqld-nt.exe) CPU 佔用率總為100% 高居不下。此主機有10個左右的database, 分別給十個網站調用。據朋友測試,導致mysqld-nt.exe cpu 佔用奇高的是網站A,一旦在IIS 中將此網站停止服務,CPU 佔用就降下來了。一啟用,則馬上上升。
MYSQL CPU 佔用 100% 的解決過程
今天早上仔細檢查了一下。目前此網站的七日平均日IP 為2000,PageView 為3萬左右。網站A 用的database 目前有39個表,記錄數60.1萬條,佔空間45MB。按這個數據,MySQL 不可能佔用這麼高的資源。
於是在服務器上運行命令,將mysql 當前的環境變量輸出到文件output.txt:
d:\web\mysql>mysqld.exe--help>output.txt
發現tmp_table_size 的值是默認的32M,於是修改My.ini, 將tmp_table_size 賦值到200M:
d:\web\mysql>notepad c:\windows\my.ini[mysqld]tmp_table_size=200M
然後重啟 MySQL 服務。 CPU 佔用有輕微下降,以前的CPU 佔用波形圖是100% 一根直線,現在則在97%~100%之間起伏。這表明調整tmp_table_size 參數對MYSQL 性能提升有改善作用。但問題還沒有完全解決。
於是進入mysql 的shell 命令行,調用show processlist, 查看當前mysql 使用頻繁的sql 語句:
mysql>show processlist;
反複調用此命令(每秒刷兩次),發現網站A 的兩個SQL 語句經常在process list 中出現,其語法如下:
SELECT t1.pid, t2.userid, t3.count, t1.date FROM _mydata AS t1LEFT JOIN _myuser AS t3 ON t1.userid=t3.useridLEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid ORDER BY t1.pid LIMIT0 ,15
調用 show columns 檢查這三個表的結構 :
mysql>show columns from _myuser;mysql>show columns from _mydata;mysql>show columns from _mydata_body;
終於發現了問題所在:_mydata 表,只根據pid 建立了一個primary key,但並沒有為userid 建立索引。而在這個SQL 語句的第一個LEFT JOIN ON 子句中:
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
_mydata 的userid 被參與了條件比較運算。於是我為給_mydata 表根據字段userid 建立了一個索引:
mysql>ALTER TABLE `_mydata` ADD INDEX ( `userid` )
建立此索引之後,CPU 馬上降到了80% 左右。看到找到了問題所在,於是檢查另一個反復出現在show processlist 中的sql 語句:
SELECT COUNT(*)FROM _mydata AS t1, _mydata_key AS t2WHERE t1.pid=t2.pid and t2.keywords= '孔雀'
經檢查_mydata_key 表的結構,發現它只為pid 建了了primary key, 沒有為keywords 建立index。 _mydata_key 目前有33 萬條記錄,在沒有索引的情況下對33萬條記錄進行文本檢索匹配,不耗費大量的cpu 時間才怪。看來就是針對這個表的檢索出問題了。於是同樣為_mydata_key 表根據字段keywords 加上索引:
mysql>ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` )
建立此索引之後,CPU立刻降了下來,在50%~70%之間震盪。
再次調用show prosslist,網站A 的sql 調用就很少出現在結果列表中了。但發現此主機運行了幾個Discuz 的論壇程序, Discuz論壇的好幾個表也存在著這個問題。於是順手一併解決,cpu佔用再次降下來了。
至此,問題解決。 1. 增加 tmp_table_size 值。 mysql 的配置文件中,tmp_table_size 的默認大小是32M。如果一張臨時表超出該大小,MySQL產生一個The table tbl_name is full 形式的錯誤,如果你做很多高級GROUP BY 查詢,增加tmp_table_size 值。這是 mysql 官方關於此選項的解釋:
tmp_table_size This variable determines the maximum size for a temporary table in memory. If the table becomes too large, a MYISAM table is created on disk. Try to avoid temporary tables by optimizing the queries where possible, but where this is not possible, try to ensure temporary tables are always stored in memory. Watching the processlist for queries with temporary tables that take too long to resolve can give you an early warning that tmp_table_size needs to be upped. Be aware that memory is also allocated per-thread. An example where upping this worked for more was a server where I upped this from 32MB (the default) to 64MB with immediate effect. The quicker resolution of queries resulted in less threads being active at any one time, with all-round benefits for the server, and available memory.
2. 對WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的條件判斷中用到的字段,應該根據其建立索引INDEX。
索引被用來快速找出在一個列上用一特定值的行。沒有索引,MySQL不得不首先以第一條記錄開始並然後讀完整個表直到它找出相關的行。表越大,花費時間越多。如果表對於查詢的列有一個索引,MySQL能快速到達一個位置去搜尋到數據文件的中間,沒有必要考慮所有數據。如果一個表有1000行,這比順序讀取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B樹中存儲。
根據 mysql 的開發文檔:
索引 index 用於:
o 快速找出匹配一個WHERE子句的行 o 當執行聯結(JOIN)時,從其他表檢索行。 o 對特定的索引列找出MAX()或MIN()值 o 如果排序或分組在一個可用鍵的最左面前綴上進行(例如,ORDER BY key_part_1,key_part_2),排序或分組一個表。如果所有鍵值部分跟隨DESC,鍵以倒序被讀取。 o 在一些情況中,一個查詢能被優化來檢索值,不用諮詢數據文件。如果對某些表的所有使用的列是數字型的並且構成某些鍵的最左面前綴,為了更快,值可以從索引樹被檢索出來。
假定你發出下列SELECT語句:
mysql>SELECT*FROM tbl_name WHERE col1=val1 AND col2=val2;
如果一個多列索引存在於col1和col2上,適當的行可以直接被取出。如果分開的單行列索引存在於col1和col2上,優化器試圖通過決定哪個索引將找到更少的行並來找出更具限制性的索引並且使用該索引取行。
開發人員做SQL 數據表設計的時候,一定要通盤考慮清楚。
早上幫朋友一台服務器解決了Mysql cpu 佔用100% 的問題,稍整理如下,希望對各位有所幫助。
朋友主機(Windows 2003 + IIS + PHP + MYSQL )近來MySQL 服務進程(mysqld-nt.exe) CPU 佔用率總為100% 高居不下。此主機有10個左右的database, 分別給十個網站調用。據朋友測試,導致mysqld-nt.exe cpu 佔用奇高的是網站A,一旦在IIS 中將此網站停止服務,CPU 佔用就降下來了。一啟用,則馬上上升。
MYSQL CPU 佔用 100% 的解決過程
今天早上仔細檢查了一下。目前此網站的七日平均日IP 為2000,PageView 為3萬左右。網站A 用的database 目前有39個表,記錄數60.1萬條,佔空間45MB。按這個數據,MySQL 不可能佔用這麼高的資源。
於是在服務器上運行命令,將mysql 當前的環境變量輸出到文件output.txt:
d:\web\mysql>mysqld.exe--help>output.txt
發現tmp_table_size 的值是默認的32M,於是修改My.ini, 將tmp_table_size 賦值到200M:
d:\web\mysql>notepad c:\windows\my.ini[mysqld]tmp_table_size=200M
然後重啟 MySQL 服務。 CPU 佔用有輕微下降,以前的CPU 佔用波形圖是100% 一根直線,現在則在97%~100%之間起伏。這表明調整tmp_table_size 參數對MYSQL 性能提升有改善作用。但問題還沒有完全解決。
於是進入mysql 的shell 命令行,調用show processlist, 查看當前mysql 使用頻繁的sql 語句:
mysql>show processlist;
反複調用此命令(每秒刷兩次),發現網站A 的兩個SQL 語句經常在process list 中出現,其語法如下:
SELECT t1.pid, t2.userid, t3.count, t1.date FROM _mydata AS t1LEFT JOIN _myuser AS t3 ON t1.userid=t3.useridLEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid ORDER BY t1.pid LIMIT0 ,15
調用 show columns 檢查這三個表的結構 :
mysql>show columns from _myuser;mysql>show columns from _mydata;mysql>show columns from _mydata_body;
終於發現了問題所在:_mydata 表,只根據pid 建立了一個primary key,但並沒有為userid 建立索引。而在這個SQL 語句的第一個LEFT JOIN ON 子句中:
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
_mydata 的userid 被參與了條件比較運算。於是我為給_mydata 表根據字段userid 建立了一個索引:
mysql>ALTER TABLE `_mydata` ADD INDEX ( `userid` )
建立此索引之後,CPU 馬上降到了80% 左右。看到找到了問題所在,於是檢查另一個反復出現在show processlist 中的sql 語句:
SELECT COUNT(*)FROM _mydata AS t1, _mydata_key AS t2WHERE t1.pid=t2.pid and t2.keywords= '孔雀'
經檢查_mydata_key 表的結構,發現它只為pid 建了了primary key, 沒有為keywords 建立index。 _mydata_key 目前有33 萬條記錄,在沒有索引的情況下對33萬條記錄進行文本檢索匹配,不耗費大量的cpu 時間才怪。看來就是針對這個表的檢索出問題了。於是同樣為_mydata_key 表根據字段keywords 加上索引:
mysql>ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` )
建立此索引之後,CPU立刻降了下來,在50%~70%之間震盪。
再次調用show prosslist,網站A 的sql 調用就很少出現在結果列表中了。但發現此主機運行了幾個Discuz 的論壇程序, Discuz論壇的好幾個表也存在著這個問題。於是順手一併解決,cpu佔用再次降下來了。
至此,問題解決。 1. 增加 tmp_table_size 值。 mysql 的配置文件中,tmp_table_size 的默認大小是32M。如果一張臨時表超出該大小,MySQL產生一個The table tbl_name is full 形式的錯誤,如果你做很多高級GROUP BY 查詢,增加tmp_table_size 值。這是 mysql 官方關於此選項的解釋:
tmp_table_size This variable determines the maximum size for a temporary table in memory. If the table becomes too large, a MYISAM table is created on disk. Try to avoid temporary tables by optimizing the queries where possible, but where this is not possible, try to ensure temporary tables are always stored in memory. Watching the processlist for queries with temporary tables that take too long to resolve can give you an early warning that tmp_table_size needs to be upped. Be aware that memory is also allocated per-thread. An example where upping this worked for more was a server where I upped this from 32MB (the default) to 64MB with immediate effect. The quicker resolution of queries resulted in less threads being active at any one time, with all-round benefits for the server, and available memory.
2. 對WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的條件判斷中用到的字段,應該根據其建立索引INDEX。
索引被用來快速找出在一個列上用一特定值的行。沒有索引,MySQL不得不首先以第一條記錄開始並然後讀完整個表直到它找出相關的行。表越大,花費時間越多。如果表對於查詢的列有一個索引,MySQL能快速到達一個位置去搜尋到數據文件的中間,沒有必要考慮所有數據。如果一個表有1000行,這比順序讀取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B樹中存儲。
根據 mysql 的開發文檔:
索引 index 用於:
o 快速找出匹配一個WHERE子句的行 o 當執行聯結(JOIN)時,從其他表檢索行。 o 對特定的索引列找出MAX()或MIN()值 o 如果排序或分組在一個可用鍵的最左面前綴上進行(例如,ORDER BY key_part_1,key_part_2),排序或分組一個表。如果所有鍵值部分跟隨DESC,鍵以倒序被讀取。 o 在一些情況中,一個查詢能被優化來檢索值,不用諮詢數據文件。如果對某些表的所有使用的列是數字型的並且構成某些鍵的最左面前綴,為了更快,值可以從索引樹被檢索出來。
假定你發出下列SELECT語句:
mysql>SELECT*FROM tbl_name WHERE col1=val1 AND col2=val2;
如果一個多列索引存在於col1和col2上,適當的行可以直接被取出。如果分開的單行列索引存在於col1和col2上,優化器試圖通過決定哪個索引將找到更少的行並來找出更具限制性的索引並且使用該索引取行。
開發人員做SQL 數據表設計的時候,一定要通盤考慮清楚。
2011年7月14日 星期四
Same origin policy 和 JSONP
Wikipedia 上有清楚的範例說明 Same origin policy, 瀏覽器端的 javascript 只能存取 protocol、domain name、port 一致下的檔案。若沒有這個限制的話 [*1], 網站 A 就能透過使用者取用網站 B 的內容, 後果不堪設想。但是, 現今做網站常需要整合其它網站的內容, 像是在自己的網站用 Flickr 的相片, 用 Google Map 的地圖等, 必須要有方式安全地避開 Same origin policy。
備註 1: 我自己測的結果, 用 ajax 連到其它網域要東西, 對方的 server 還是會收到請求, 並傳回 200, 只是 ajax 不會得到結果, 我猜應該是瀏覽器自己擋掉拿回來的結果。所以, 即使有 same origin policy, 還是有可能讓使用者狂連其它網站, 浪費別人的資源。但也會留下 referral log 就是了。《JavaScript 抓取跨網域外的資料》 清楚的說明避開 Same origin policy 的兩個作法
- 透過自己網站的 proxy script, 就沒有 same origin policy 的限制。也就是說, 自己先寫好一個 proxy script (用 PHP / CGI, 什麼都可以), 要取用其它網域的檔案時, 先連到自家的 proxy script, 透過它連向目標 URL, 再直接傳回收到的結果。缺點是會增加 latency, 還有增加自家網站的負擔。
- html tag 沒有跨網域的限制 (不然連載入其它網站的圖和 CSS 都很麻煩), 可以用 <script type="text/javascript" src="http://OTHER-DOMAIN/some.js"></script> 載入執行另一個網域的 javascript。
由於 HTML 可以動態加入元件, 這讓使用 style tag 的作法有更多彈性, 可以動態載入其它 domain 的 javascript, 執行裡面的內容, 也方便控制執行的順序。若對方的 javascript 知道自己目前的內容 (DOM、javascript), 就可以搭起兩個網域的資料。於是有了 JSONP 的想法: OTHER-DOMAIN 提供一個 URL, 這個 URL 接受一個參數 callback, 表示 OUR-DOMAIN 寫好的函式名稱。OTHER-DOMAIN 則傳回 CALLBACK({...}) 的程式碼, 用 style tag 載入後會自動執行, 結果就是用 OUR-DOMAIN 的 CALLBACK 接受 OTHER-DOMAIN 「傳回」的 JSON 物件 ( 即 {...} ), 達到跨網域的需求。必要時 OTHER-DOMAIN 也可以多產生一些程式碼, 做些 CALLBACK 的前處理和後處理。
Wikipedia 有詳細的 JSONP 例子, 另外這裡和這裡也有不錯的例子, 觀察 server side (即 OTHER-DOMAIN) 和 client side (即 OUR-DOMAIN) 的原始碼和中間產生的 code, 就能明白它運作的機制。
使用 JSONP 的代價就是, 使用者得相信提供 JSONP API 的網站不會亂搞, 偷產生惡意程式碼, 這有點像接受外部的輸入, 再執行 eval 一樣, 方便歸方便, 卻有一定的風險。另外 jQuery 有提供 JSONP 的執行方式, 可以省掉自己產生 style tag 執行, 再砍掉它的步驟。
2011年7月12日 星期二
轉錄:使用 JSON 來讀取你的 Google Data
轉錄 from ericsk.NET
使用 JSON 來讀取你的 Google Data
所以說根本就可以把 Google 當床,然後我以四海為家。
剛才讀到這篇文章,現在你可以把 Google Base、Blogger 及 Google Calendar 的 feed 轉成 JSON 格式,然後在你的 page 上利用 JavaScript 來處理 data。
而使用方法也很簡單,我拿 Google Calendar 上的「台灣假日」(或 Taiwan Holidays)為例,這份日曆的 feed 是:
如此一來你在
就會跳出一個視窗顯示 「Title: 台灣假日」。
JavaScript 的應用真是愈來愈強大囉!
剛才讀到這篇文章,現在你可以把 Google Base、Blogger 及 Google Calendar 的 feed 轉成 JSON 格式,然後在你的 page 上利用 JavaScript 來處理 data。
而使用方法也很簡單,我拿 Google Calendar 上的「台灣假日」(或 Taiwan Holidays)為例,這份日曆的 feed 是:
當然這回傳的會是一份 XML 檔案,所以我們要在這個 URL 的後面加上
http://www.google.com/calendar/feeds/ taiwan__zh_tw%40holiday.calendar.google.com/ public/basic
alt=json-in-script&callback=handleJson
這樣的參數,其中 callback 指的是會用哪個 JavaScript function 來處理回傳的 JSON data,此例中名為 handleJson。所以我們會在網頁上加入像這樣的 code:<script type="text/javascript"> function handleJson(json) { // 處理 data } </script> <script type="text/javascript" src="http://www.google.com/calendar/feeds/ taiwan__zh_tw%40holiday.calendar.google.com/public/ full?orderby=starttime&alt=json-in-script&callback=handleJson"></script>
handleJson
function 中所拿到的 json 變數就是一個 JSON object,至於這個 object 裡面的 field 該怎麼 access,你可以參考說明文件。舉個例子,如果你要取得這個 feed 中的 title 欄位,從說明文件中得知它是在 feed.title.$t
,所以你在 handleJson
function 裡就該用 json.feed.$t
來 access title 欄位的值,比方說:function handleJson(json) { alert('Title: ' + json.feed.title.$t); }
JavaScript 的應用真是愈來愈強大囉!
2011年7月10日 星期日
[MySQL] mysql 中InnoDB和MyISAM的區別
InnoDB和MyISAM是在使用MySQL最常用的兩個表類型,各有優缺點,視具體應用而定。基本的差別為:MyISAM類型不支持事務處理等高級處 理,而InnoDB類型支持。MyISAM類型的表強調的是性能,其執行數度比InnoDB類型更快,但是不提供事務支持,而InnoDB提供事務支持已 經外部鍵等高級數據庫功能。
MyIASM是IASM表的新版本,有如下擴展:
二進制層次的可移植性。
NULL列索引。
對變長行比ISAM表有更少的碎片。
支持大文件。
更好的索引壓縮。
更好的鍵嗎統計分佈。
更好和更快的auto_increment處理。
以下是一些細節和具體實現的差別:
1.InnoDB不支持FULLTEXT類型的索引。
2.InnoDB 中不保存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃瞄一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數即可。注意的是,當count(*)語句包含 where條件時,兩種表的操作是一樣的。
3.對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯合索引。
4.DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5.LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數據後再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。
另外,InnoDB表的行鎖也不是絕對的,如果在執行一個SQL語句時MySQL不能確定要掃瞄的範圍,InnoDB表同樣會鎖全表,例如update table set num=1 where name like 「%aaa%」
任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優勢。
轉自 http://www.phpobject.net/blog/read.php?124
MyIASM是IASM表的新版本,有如下擴展:
二進制層次的可移植性。
NULL列索引。
對變長行比ISAM表有更少的碎片。
支持大文件。
更好的索引壓縮。
更好的鍵嗎統計分佈。
更好和更快的auto_increment處理。
以下是一些細節和具體實現的差別:
1.InnoDB不支持FULLTEXT類型的索引。
2.InnoDB 中不保存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃瞄一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數即可。注意的是,當count(*)語句包含 where條件時,兩種表的操作是一樣的。
3.對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中,可以和其他字段一起建立聯合索引。
4.DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5.LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數據後再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。
另外,InnoDB表的行鎖也不是絕對的,如果在執行一個SQL語句時MySQL不能確定要掃瞄的範圍,InnoDB表同樣會鎖全表,例如update table set num=1 where name like 「%aaa%」
任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優勢。
轉自 http://www.phpobject.net/blog/read.php?124
訂閱:
文章 (Atom)