qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          IT項(xiàng)目風(fēng)險(xiǎn)管理案例和應(yīng)對(duì)之道

          IT項(xiàng)目風(fēng)險(xiǎn)管理案例和應(yīng)對(duì)之道


            IT項(xiàng)目管理從某個(gè)意義上來說,就是風(fēng)險(xiǎn)管理。從理論上講風(fēng)險(xiǎn)管理可以分為三個(gè)部分:風(fēng)險(xiǎn)識(shí)別、風(fēng)險(xiǎn)分析和風(fēng)險(xiǎn)解決。 傳統(tǒng)的風(fēng)險(xiǎn)管理系統(tǒng)只能幫我們較正規(guī)地統(tǒng)計(jì)和管理風(fēng)險(xiǎn),這些系統(tǒng)本身是不能規(guī)避或解決任何風(fēng)險(xiǎn)的。在實(shí)際操作上,由于可能發(fā)生風(fēng)險(xiǎn)的種類很多,處理起來所耗費(fèi)的人力物力也相當(dāng)可觀。在下列的案例中,我們建議的不是一套昂貴而且全面的風(fēng)險(xiǎn)管理系統(tǒng),而是一套扼住最關(guān)鍵部位,高效且低成本,適合于千萬中小企業(yè)的小型解決方案。

            一個(gè)案例

            在2009年某家在北京海淀區(qū)的嵌入式產(chǎn)品公司跟我們討論項(xiàng)目管理時(shí),該公司的王總監(jiān)跟我們做了以下溝通。他們項(xiàng)目風(fēng)險(xiǎn)種類可以概略分為四類:

            (1)需求風(fēng)險(xiǎn) ——對(duì)需求理解不夠透徹或需求變更頻繁;

            (2)人員風(fēng)險(xiǎn) ——人員生病或離職,一時(shí)無法找到替代者;

            (3)技術(shù)風(fēng)險(xiǎn) ——某個(gè)關(guān)鍵的技術(shù)問題無法快速攻克;

            (4)管理風(fēng)險(xiǎn) ——管理人員協(xié)調(diào)能力和執(zhí)行力能力不足,計(jì)劃偏差,流程更改和溝通不良等。

            這些風(fēng)險(xiǎn)的發(fā)生導(dǎo)致的結(jié)果就是項(xiàng)目延期和成本大幅攀升。無法有效處理這些風(fēng)險(xiǎn)的兩個(gè)最大問題在于:

            (1)對(duì)風(fēng)險(xiǎn)的反應(yīng)遲鈍 ——常常是太晚發(fā)現(xiàn)問題,以至于無法彌補(bǔ)或是彌補(bǔ)成本太大;

            (2)對(duì)過程難以掌控 ——雖已有既定的流程,但由于人員變動(dòng)、流程變動(dòng)、系統(tǒng)出錯(cuò)等問題,很難照著走。

            為了讓我們更理解,王總監(jiān)很生動(dòng)的解釋了以上兩個(gè)問題。對(duì)風(fēng)險(xiǎn)反應(yīng)遲鈍的問題,他說,在做項(xiàng)目計(jì)劃時(shí)為求實(shí)際,總會(huì)多估個(gè)20%到40%的時(shí)間。如果項(xiàng)目需求清晰,或是團(tuán)隊(duì)做過類似項(xiàng)目,就用20%或多些;如果是新項(xiàng)目,或風(fēng)險(xiǎn)因素多便用30%到40%。所以,當(dāng)某些風(fēng)險(xiǎn)(如,需求變更或人員變動(dòng))發(fā)生了,一般也未必馬上就造成項(xiàng)目延期。可是,如果風(fēng)險(xiǎn)發(fā)生量繼續(xù)增加,或是某一兩個(gè)風(fēng)險(xiǎn)產(chǎn)生較嚴(yán)重的沖擊,在某個(gè)時(shí)刻就會(huì)過了臨界點(diǎn)。難的地方就是項(xiàng)目大人員多,就是連項(xiàng)目經(jīng)理也是見樹不見林。

            對(duì)過程難以掌控的問題,王總監(jiān)舉了個(gè)例子。公司的研發(fā)制度里規(guī)定,為保證需求的準(zhǔn)確性,一個(gè)需求的變更要經(jīng)過(1)該項(xiàng)目經(jīng)理,(2)一位資深程序員,和(3)該產(chǎn)品經(jīng)理,等三個(gè)關(guān)鍵人審核后才可以進(jìn)行更改。王總監(jiān)說:需求變更的過程在邏輯上看似簡單,但在實(shí)際操作時(shí)卻不斷地發(fā)生問題。舉例來說,內(nèi)部溝通主要是以郵件通知的方式進(jìn)行,需求變更的文檔寄來寄去,版本很多,而且郵件總是遺失。另有一次更嚴(yán)重,產(chǎn)品經(jīng)理因?yàn)樾菁伲瑳]能及時(shí)查郵件。在等了兩天后,因怕誤了工期,項(xiàng)目經(jīng)理便越權(quán)要求程序員把代碼寫了。不巧,產(chǎn)品經(jīng)理對(duì)這需求的更改有他強(qiáng)烈的意見。當(dāng)他看到在沒得到他的同意下就把代碼寫了,火冒三丈,直接在會(huì)議中就和項(xiàng)目經(jīng)理吵了起來。

            兩個(gè)控制風(fēng)險(xiǎn)的原則

            雖然風(fēng)險(xiǎn)總是發(fā)生,但就如同大多數(shù)的公司一樣,該公司也不愿意花費(fèi)太多的精力和時(shí)間在這風(fēng)險(xiǎn)管控上,所以在尋求一個(gè)低成本又高效的管控方法。王總監(jiān)和我們?cè)谘杏懞螅褂霉ぞ逥evSuite基于下列兩個(gè)原則做了處理。(為避免篇幅太大,以下我們僅把最精彩的點(diǎn)列出來。)

            (1)提高項(xiàng)目的可視性

            不論是哪一種風(fēng)險(xiǎn),其最后沖擊的基本上就是項(xiàng)目本身,延期是最常見的結(jié)果。如果是對(duì)可能發(fā)生的風(fēng)險(xiǎn)都一一進(jìn)行管控,成本必然很高,而且還可能有疏漏。使用燃盡圖(Burn Down Chart)可能是針對(duì)項(xiàng)目延期最有效的解決辦法,因?yàn)樗艽蟪潭鹊靥岣吡隧?xiàng)目的可視性。在實(shí)際操作時(shí),我們讓團(tuán)隊(duì)成員每天對(duì)其參與的每一任務(wù)都鍵入下列兩項(xiàng)數(shù)字:1)該任務(wù)花費(fèi)時(shí)間,和2)該任務(wù)所剩時(shí)間。結(jié)果就會(huì)生了類似如下的燃盡圖。

            如圖所示,起初這項(xiàng)目被估計(jì)是要3480小時(shí)完成。大致上來說,一般的研發(fā)團(tuán)隊(duì)因著人員請(qǐng)假、會(huì)議和其他突發(fā)事情,平均每人每天只能有六小時(shí)花在實(shí)際項(xiàng)目工作上。現(xiàn)這項(xiàng)目有七個(gè)人參與,估算出來大約需要四個(gè)月完成。(也就是從2009年11月29日到2010年3月29日,圖中紅色直立線為起始線,藍(lán)色直立線為終止線。)這圖里共有三條曲線。紅色號(hào)碼?/span>表示到現(xiàn)在為止在該項(xiàng)目的總花費(fèi)時(shí)間,紅色號(hào)碼?表示估算的項(xiàng)目剩余時(shí)間,紅色號(hào)碼?是到目前為止所花的時(shí)間與剩余時(shí)間之和的曲線。到了2010年3月21日就得到了上面的這個(gè)圖。到了這一天,我們發(fā)現(xiàn)原本估計(jì)的3480總小時(shí)數(shù)是低估了,更可能的是?所示的3740小時(shí)。

            以縱軸的性質(zhì)區(qū)分,燃盡圖可以分為兩大類,即縱軸可以是時(shí)間或是事件。以范圍區(qū)分,燃盡圖至少可以分為三類:項(xiàng)目級(jí)的、任務(wù)級(jí)的和需求級(jí)的。透過燃盡圖,我們可以看到項(xiàng)目進(jìn)行的情況,項(xiàng)目需求是否按計(jì)劃進(jìn)入開發(fā)流程,工作是否有延時(shí),或者工作安排的飽和度是否適合。如上圖所示,我們可以輕易地看到,照著現(xiàn)在的進(jìn)度,這項(xiàng)目最可能會(huì)延期6到7工作天。當(dāng)高層看到這圖時(shí),就可以在資源上做調(diào)動(dòng),以避免延期產(chǎn)生的不良后果。

            我們刻意使用了這個(gè)較理想的圖做講解,為的是讓讀者更容易理解。它不是個(gè)典型的圖。在大多情況,使用燃盡圖會(huì)是比較復(fù)雜的,因?yàn)樗赡馨诵枨笏鸭⒕幊獭卧獪y試、集成測試和缺陷修復(fù),并且還可能有迭代。所以估算時(shí)間會(huì)較困難。這個(gè)燃盡圖的過程是比較穩(wěn)定的,結(jié)果是比較理想的,其原因至少有二:(一)項(xiàng)目里單純地只有編程、單元測試和缺陷修復(fù)任務(wù),全都由程序員搞定;它里頭沒有需求搜集、集成測試或其他任務(wù)。(二)這個(gè)項(xiàng)目復(fù)雜度低,約一半的編碼任務(wù)是機(jī)械性的,所以估出來的時(shí)間較為準(zhǔn)確。

            (2)固化工作流以管控過程

            對(duì)于公司里既定的流程,我們?cè)贒evSuite里以圖形化的工作流將其固化。下圖就是以前面王總監(jiān)提到的需求變更流程設(shè)計(jì)出來的。

            這工作流指明了,在一個(gè)變更事件被創(chuàng)建后,它需要經(jīng)過一個(gè)《評(píng)審》狀態(tài)。在評(píng)審階段里,有三個(gè)人(A,B和C)要全部同意,才能到達(dá)《通過》狀態(tài)。有任何一人不同意,狀態(tài)就轉(zhuǎn)到《拒絕》。當(dāng)一到達(dá)《評(píng)審》狀態(tài),系統(tǒng)馬上促發(fā)郵件和手機(jī)通知,將信息寄給A,B和C。系統(tǒng)可以預(yù)先設(shè)定這三人有兩天的時(shí)間評(píng)審該變更。假如兩天過了,狀態(tài)仍為《評(píng)審》,那就是有人未及時(shí)處理該事件。這時(shí)候,系統(tǒng)會(huì)自動(dòng)將事件升級(jí),把狀態(tài)轉(zhuǎn)換為《升級(jí)處理》,系統(tǒng)馬上促發(fā)郵件,將信息寄給研發(fā)部王總監(jiān)。王總監(jiān)可以斟酌情況,做最妥善的處理。

            使用固化的工作流至少有四個(gè)優(yōu)點(diǎn):1)提高通知效率 ?郵件和手機(jī)自動(dòng)通知提高效率,溝通出錯(cuò)的機(jī)會(huì)減少了;2)避免流程出錯(cuò) ?DevSuite的工作流將流程完全自動(dòng)化,每個(gè)人在收到郵件或短信通知時(shí),照著工作流中既定的步驟操作就行了,省心又省力; 3)工作流變動(dòng)時(shí)處理很容易 ?當(dāng)流程或人員變動(dòng)時(shí),系統(tǒng)配置員可以輕易地花幾分鐘就做完調(diào)整,之后所有團(tuán)隊(duì)成員就照著流程走便行了;4)避免摩擦?人是有情緒的,固化的工作流使得操作完全對(duì)事不對(duì)人,避免了人和人之間不必要的摩擦。

            以上提到的軟件項(xiàng)目風(fēng)險(xiǎn)實(shí)例幾乎在每個(gè)項(xiàng)目中都出現(xiàn),而且,它們?cè)斐傻膿p失也是嚴(yán)重的。所幸,從實(shí)際操作中,我們發(fā)現(xiàn)處理它們的成本并不高:1)培訓(xùn)團(tuán)隊(duì)成員照工作流中既定的步驟操作,學(xué)會(huì)填寫任務(wù)花費(fèi)時(shí)間和任務(wù)所剩時(shí)間,并理解意圖,所花時(shí)間不超過1小時(shí),2)系統(tǒng)配置員要了解需求,設(shè)計(jì)工作流,并設(shè)置人員(如例子中的A、B、C和走流程的人)的權(quán)限等,所花費(fèi)時(shí)間在1到3天之間,也算合理,3)以往當(dāng)團(tuán)隊(duì)人員或評(píng)審流程有變動(dòng),管理人員要更改文檔并向所有人宣布;現(xiàn)系統(tǒng)配置員只要花幾分鐘改系統(tǒng)配置,一切就就緒了。

            小結(jié)

            這并不是一個(gè)全方位的風(fēng)險(xiǎn)管控系統(tǒng);相反的,它是個(gè)相當(dāng)簡化,只對(duì)關(guān)鍵點(diǎn)作處理的系統(tǒng)。雖然只是做在關(guān)鍵點(diǎn)上,但效果卻十分明顯。就拿需求變更來說,需求變更一直都是項(xiàng)目中讓人恨得牙癢癢的瘤。既然需求變更是不可避免,那我們所能做的就是,盡可能減少變更的次數(shù),降低變更造成的沖擊。以往大多數(shù)人審核需求變更時(shí)較為草率,導(dǎo)致同一個(gè)功能點(diǎn)變了又變。在一輪又一輪的返工后,程序員和測試人員會(huì)產(chǎn)生倦怠感,編碼和測試的質(zhì)量一再下降。使用了DevSuite后,所有的操作都在系統(tǒng)里留下記錄,這統(tǒng)計(jì)在年終時(shí)可以作為考評(píng)的參考材料。自然而然地,審核人員就很嚴(yán)謹(jǐn)?shù)貙徍嗣恳粋€(gè)需求變更。而且,因?yàn)橄到y(tǒng)設(shè)置了每人只有兩天的時(shí)間處理,審核人員處理需求變更時(shí)不僅是快,而且較仔細(xì)。單單就這個(gè)變化,就使得整個(gè)團(tuán)隊(duì)的氣象煥然一新。

            在系統(tǒng)實(shí)施后半年,我們做了客戶回訪,我劈頭就問王總監(jiān),說的那位產(chǎn)品經(jīng)理還跟項(xiàng)目經(jīng)理還吵架嗎?瞪了我一眼,停了一下,然后皺了皺眉頭說:倒是不吵架了。他們倆現(xiàn)在成了好朋友,聯(lián)合起來一起對(duì)付我了。他自己呵呵呵地笑了起來

          posted @ 2011-12-08 14:57 順其自然EVO 閱讀(185) | 評(píng)論 (0)編輯 收藏

          如何有效實(shí)現(xiàn)軟件的需求管理(5)

          需求分析階段完了以后,就是需求設(shè)計(jì),然后就是需求實(shí)現(xiàn)了,過程看起來很簡單,但是實(shí)際工作不簡單,上面談到的需求管理的幾點(diǎn)嚴(yán)格要求一直貫穿著整個(gè)過程的始末。

            接下來我會(huì)結(jié)合我們公司實(shí)際的流程來介紹一下需求管理的實(shí)際實(shí)現(xiàn)。

            如果看過我之前的文章,應(yīng)該知道我們公司的背景,我們公司也是做軟件開發(fā)的,所以對(duì)于需求管理這塊也是相當(dāng)重視的。我們是用敏捷的模式來管理整個(gè)軟件開發(fā)的,所以需求管理的階段也是符合敏捷的模式的,但是對(duì)于需求管理的幾點(diǎn)嚴(yán)格要求還是基本上也是遵守的。

            我們公司是用 TechExcel 的需求管理工具 DevSpec 來管理整個(gè)需求過程的,其實(shí)我們是買了他們的整套軟件生命周期管理的解決方案,名稱叫做DevSuite,而DevSpec 是其中一個(gè)工具,能與DevSuite 解決方案的其他工具無縫集成,幫助共同管理開發(fā)、測試、計(jì)劃等階段。

            在DevSpec中,對(duì)于需求的管理是通過條目化的方式來管理的,所謂的條目化就是說一個(gè)需求就是一個(gè)條目,這個(gè)條目既包括了對(duì)這個(gè)需求的描述,還包括了對(duì)這個(gè)需求的處理過程的跟蹤:

            對(duì)于需求的描述而言,DevSpec是通過屬性字段的方式實(shí)現(xiàn)的,你可以用字段來盡可能真實(shí)描述需求,其中包括標(biāo)題,狀態(tài),負(fù)責(zé)人,描述,時(shí)間,附件等基本字段,當(dāng)然你還可以大量自定義屬性字段和頁面來幫助更好地描述這個(gè)需求。

            對(duì)于需求的處理過程而言,

            我們知道需求的處理是要有流程的,簡單的就是從需求分析-->需求設(shè)計(jì)-->需求實(shí)現(xiàn),復(fù)雜點(diǎn)的還需要加上審核,就像我上面給大家看過的那個(gè)流程圖一樣, 我這里再貼一下

            不過光有流程其實(shí)沒用,我相信任何公司的需求處理都會(huì)有流程,只是嚴(yán)格不嚴(yán)格,認(rèn)真不認(rèn)真的區(qū)別罷了,不遵照流程處理的需求有非常高的可能性不成功,所以為了解決這個(gè)問題,DevSpec 中專門設(shè)計(jì)可自定義的工作流程,你可以自己定義需求需要經(jīng)過哪些流程才能進(jìn)入開發(fā),而一旦流程定義完成以后,需求的處理就會(huì)被強(qiáng)制按照流程的進(jìn)行,你自己想馬虎馬虎,松懈松懈都沒辦法做到。

            在流程中,DevSpec可以給每個(gè)過程設(shè)置不同負(fù)責(zé)人和權(quán)限,比如分析這個(gè)過程是小王處理,所以只有小王才能看到這個(gè)需求并且處理這個(gè)需求,其他人如果沒有權(quán)限就看不到這個(gè)需求;而小王處理完他的工作后,他不一定有權(quán)力把這個(gè)需求轉(zhuǎn)到下一個(gè)過程,因?yàn)樾枰硗庖粋€(gè)人審核以后才能繼續(xù)下去。

            這樣子的話,

            第一,你的處理流程會(huì)很清晰,這一步處理完了,下一步是什么,一目了然;

            第二,你的管理流程也很透明,現(xiàn)在誰處理,接下來該誰處理,清清楚楚。

            第三,你的權(quán)力流程也很明了,什么級(jí)別的人能做什么事情都可以設(shè)置,哪些該做的不該做的,哪些該看不該看的,都很簡單就可以設(shè)置,避免了一些人看到不該看的內(nèi)容,做了不該做的事情。

            有了這些屬性和流程,我們就可以正式開始 DevSpec 的需求管理了.

            (未完待續(xù))

          posted @ 2011-12-08 14:50 順其自然EVO 閱讀(317) | 評(píng)論 (0)編輯 收藏

          如何進(jìn)行高效JavaScript單元測試

               摘要: 如何進(jìn)行高效JavaScript單元測試 導(dǎo)讀:能在一個(gè)瀏覽器上運(yùn)行的JavaScript并不一定能在其他瀏覽器上運(yùn)行。如果沒有對(duì)代碼進(jìn)行單元測試,那么在決定升級(jí)或支持新瀏覽器的時(shí)候,組織就需要花錢測試或重新測試Web應(yīng)用程序。在本文中,了解JavaScript單元測試如何幫助您降低測試成本,輕松支持更多瀏覽器。  一個(gè)損壞的JavaScript代碼示例  Web應(yīng)用程序面臨的一個(gè)最大挑戰(zhàn)是支持不...  閱讀全文

          posted @ 2011-12-08 14:47 順其自然EVO 閱讀(211) | 評(píng)論 (0)編輯 收藏

          小談軟件測試的健忘癥

          測試界,有兩種非常極端的情況:一種是過早充分地測試,包括過早地介入測試,文檔,測試計(jì)劃,用例以及腳本等準(zhǔn)備的非常充分;一種是隨機(jī)測試,無文檔無計(jì)劃,完全靠測試人員的個(gè)人能力。這兩種情況都會(huì)出現(xiàn)測試的健忘癥。

            首先,第一種情況會(huì)出現(xiàn)什么問題呢?剛剛做好的測試計(jì)劃或者測試用例又要重新制定和編寫,原因是介入太早需求還沒有完全確定下來,反復(fù)的工作浪費(fèi)很多的人力和時(shí)間。而且在如今互聯(lián)網(wǎng)需求多變的情況下,如此充分的工作說不好在2個(gè)月后的重構(gòu)中又要重新開始,這時(shí)候,健忘癥體現(xiàn)在:

            1、之前花了很多時(shí)間設(shè)計(jì)的測試用例又要被遺棄或者做大量修改,用例的生命周期很短,測試用例并不是解決健忘癥的最好方法,當(dāng)然,對(duì)于一個(gè)新涉入此功能的測試人員可以通過用例了解到大概的測試點(diǎn),快速熟悉。

            2、看過一本書上介紹的殺蟲劑悖論:當(dāng)你向一塊農(nóng)田噴藥時(shí),將殺死很多的蟲子,但是存活下來的抵抗性將增強(qiáng)。用在軟件測試上也不例外,之前所有的用例執(zhí)行過后能發(fā)現(xiàn)的缺陷已經(jīng)全部暴露,之后的回歸測試只是為了確保原來的功能正常,而原本未被暴露的缺陷已經(jīng)具有抵抗力了。大家已經(jīng)忘記當(dāng)時(shí)使用的什么測試技巧,而現(xiàn)在又該使用什么別的技巧來找出這些隱藏很深的bug呢?

            其次,對(duì)于第二種情況,經(jīng)常出現(xiàn)的事情是,測試的內(nèi)容不夠明確,對(duì)于已經(jīng)測試的部分和未測試的部分都不能明確標(biāo)記,甚者不知道發(fā)現(xiàn)的bug如何復(fù)現(xiàn),為了再次重現(xiàn)此bug都需要時(shí)間,這就是最大的健忘癥,毫無準(zhǔn)備的測試工作,不能保證測試的質(zhì)量。

            如何避免呢?首先要折中一下這兩種情況,對(duì)于項(xiàng)目生命周期很長的,可以較為充分地開展測試工作,準(zhǔn)備充分的文檔以及用例,除此之外,需要文檔化的就是測試策略和測試規(guī)范。對(duì)于生命周期不長需求多變的項(xiàng)目,如web項(xiàng)目,除了有計(jì)劃的開展工作外,還需要把測試策略和技巧記錄下來,并且標(biāo)記哪種最有效,發(fā)現(xiàn)的bug最多,哪種效果稍差,這將有利于日后策略的調(diào)整。不同的測試過程采用不同的測試策略,以發(fā)現(xiàn)更多的缺陷,同時(shí)可以引入交叉測試和探索性測試,來找出隱藏很深的缺陷。而且這些策略可以被日后類似項(xiàng)目復(fù)用,解決了測試的健忘癥。

          posted @ 2011-12-08 14:33 順其自然EVO 閱讀(152) | 評(píng)論 (0)編輯 收藏

          小談軟件測試的健忘癥

          測試界,有兩種非常極端的情況:一種是過早充分地測試,包括過早地介入測試,文檔,測試計(jì)劃,用例以及腳本等準(zhǔn)備的非常充分;一種是隨機(jī)測試,無文檔無計(jì)劃,完全靠測試人員的個(gè)人能力。這兩種情況都會(huì)出現(xiàn)測試的健忘癥。

            首先,第一種情況會(huì)出現(xiàn)什么問題呢?剛剛做好的測試計(jì)劃或者測試用例又要重新制定和編寫,原因是介入太早需求還沒有完全確定下來,反復(fù)的工作浪費(fèi)很多的人力和時(shí)間。而且在如今互聯(lián)網(wǎng)需求多變的情況下,如此充分的工作說不好在2個(gè)月后的重構(gòu)中又要重新開始,這時(shí)候,健忘癥體現(xiàn)在:

            1、之前花了很多時(shí)間設(shè)計(jì)的測試用例又要被遺棄或者做大量修改,用例的生命周期很短,測試用例并不是解決健忘癥的最好方法,當(dāng)然,對(duì)于一個(gè)新涉入此功能的測試人員可以通過用例了解到大概的測試點(diǎn),快速熟悉。

            2、看過一本書上介紹的殺蟲劑悖論:當(dāng)你向一塊農(nóng)田噴藥時(shí),將殺死很多的蟲子,但是存活下來的抵抗性將增強(qiáng)。用在軟件測試上也不例外,之前所有的用例執(zhí)行過后能發(fā)現(xiàn)的缺陷已經(jīng)全部暴露,之后的回歸測試只是為了確保原來的功能正常,而原本未被暴露的缺陷已經(jīng)具有抵抗力了。大家已經(jīng)忘記當(dāng)時(shí)使用的什么測試技巧,而現(xiàn)在又該使用什么別的技巧來找出這些隱藏很深的bug呢?

            其次,對(duì)于第二種情況,經(jīng)常出現(xiàn)的事情是,測試的內(nèi)容不夠明確,對(duì)于已經(jīng)測試的部分和未測試的部分都不能明確標(biāo)記,甚者不知道發(fā)現(xiàn)的bug如何復(fù)現(xiàn),為了再次重現(xiàn)此bug都需要時(shí)間,這就是最大的健忘癥,毫無準(zhǔn)備的測試工作,不能保證測試的質(zhì)量。

            如何避免呢?首先要折中一下這兩種情況,對(duì)于項(xiàng)目生命周期很長的,可以較為充分地開展測試工作,準(zhǔn)備充分的文檔以及用例,除此之外,需要文檔化的就是測試策略和測試規(guī)范。對(duì)于生命周期不長需求多變的項(xiàng)目,如web項(xiàng)目,除了有計(jì)劃的開展工作外,還需要把測試策略和技巧記錄下來,并且標(biāo)記哪種最有效,發(fā)現(xiàn)的bug最多,哪種效果稍差,這將有利于日后策略的調(diào)整。不同的測試過程采用不同的測試策略,以發(fā)現(xiàn)更多的缺陷,同時(shí)可以引入交叉測試和探索性測試,來找出隱藏很深的缺陷。而且這些策略可以被日后類似項(xiàng)目復(fù)用,解決了測試的健忘癥。

          posted @ 2011-12-08 14:33 順其自然EVO 閱讀(128) | 評(píng)論 (0)編輯 收藏

          優(yōu)化Linux下的內(nèi)核TCP參數(shù)以提高系統(tǒng)性能

           內(nèi)核的優(yōu)化跟服務(wù)器的優(yōu)化一樣,應(yīng)本著穩(wěn)定安全的原則。下面以64位的Centos5.5下的Squid服務(wù)器為例來說明,待客戶端與服務(wù)器端建立TCP/IP連接后就會(huì)關(guān)閉SOCKET,服務(wù)器端連接的端口狀態(tài)也就變?yōu)門IME_WAIT了。那是不是所有執(zhí)行主動(dòng)關(guān)閉的SOCKET都會(huì)進(jìn)入TIME_WAIT狀態(tài)呢?有沒有什么情況使主動(dòng)關(guān)閉的SOCKET直接進(jìn)入CLOSED狀態(tài)呢?答案是主動(dòng)關(guān)閉的一方在發(fā)送最后一個(gè)ACK后就會(huì)進(jìn)入TIME_WAIT狀態(tài),并停留2MSL(Max Segment LifeTime)時(shí)間,這個(gè)是TCP/IP必不可少的,也就是“解決”不了的。

            TCP/IP的設(shè)計(jì)者如此設(shè)計(jì),主要原因有兩個(gè):

            防止上一次連接中的包迷路后重新出現(xiàn),影響新的連接(經(jīng)過2MSL時(shí)間后,上一次連接中所有重復(fù)的包都會(huì)消失)。

            為了可靠地關(guān)閉TCP連接。主動(dòng)關(guān)閉方發(fā)送的最后一個(gè)ACK(FIN)有可能會(huì)丟失,如果丟失,被動(dòng)方會(huì)重新發(fā)FIN,這時(shí)如果主動(dòng)方處于CLOSED狀態(tài),就會(huì)響應(yīng)RST而不是ACK。所以主動(dòng)方要處于TIME_WAIT狀態(tài),而不能是CLOSED狀態(tài)。另外,TIME_WAIT并不會(huì)占用很大的資源,除非受到攻擊。

            在Squid服務(wù)器中可輸入查看當(dāng)前連接統(tǒng)計(jì)數(shù)的命令,如下所示:

        1. netstat -n| awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'  
        2. LAST_ACK 14  
        3. SYN_RECV 348  
        4. ESTABLISHED 70  
        5. FIN_WAIT1 229  
        6. FIN_WAIT2 30  
        7. CLOSING 33  
        8. TIME_WAIT 18122
        9.   CLOSED:無連接是活動(dòng)的或正在進(jìn)行中的。

            LISTEN:服務(wù)器在等待進(jìn)入呼叫。

            SYN_RECV:一個(gè)連接請(qǐng)求已經(jīng)到達(dá),等待確認(rèn)。

            SYN_SENT:應(yīng)用已經(jīng)開始,打開一個(gè)連接。

            ESTABLISHED:正常數(shù)據(jù)傳輸狀態(tài)。

            FIN_WAIT1:應(yīng)用說它已經(jīng)完成。

            FIN_WAIT2:另一邊已同意釋放。

            CLOSING:兩邊同時(shí)嘗試關(guān)閉。

            TIME_WAIT:另一邊已初始化一個(gè)釋放。

            LAST_ACK:等待所有分組死掉。

            也就是說,這條命令可以把當(dāng)前系統(tǒng)的網(wǎng)絡(luò)連接狀態(tài)分類匯總。

            在Linux下高并發(fā)的Squid服務(wù)器中,TCP TIME_WAIT套接字?jǐn)?shù)量經(jīng)常可達(dá)兩三萬,服務(wù)器很容易就會(huì)被拖死。不過,我們可以通過修改Linux內(nèi)核參數(shù)來減少Squid服務(wù)器的TIME_WAIT套接字?jǐn)?shù)量,命令如下所示:

          vim /etc/sysctl.conf

            然后,增加以下參數(shù):

        10. net.ipv4.tcp_fin_timeout = 30 
        11. net.ipv4.tcp_keepalive_time = 1200 
        12. net.ipv4.tcp_syncookies = 1 
        13. net.ipv4.tcp_tw_reuse = 1 
        14. net.ipv4.tcp_tw_recycle = 1 
        15. net.ipv4.ip_local_port_range = 1024 65000  
        16. net.ipv4.tcp_max_syn_backlog = 8192 
        17. net.ipv4.tcp_max_tw_buckets = 5000



        18. 其中:

            net.ipv4.tcp_syncookies=1表示開啟SYN Cookies。當(dāng)出現(xiàn)SYN等待隊(duì)列溢出時(shí),啟用cookie來處理,可防范少量的SYN攻擊。默認(rèn)為0,表示關(guān)閉。

            net.ipv4.tcp_tw_reuse=1表示開啟重用。允許將TIME-WAIT套接字重新用于新的TCP連接。默認(rèn)為0,表示關(guān)閉。

            net.ipv4.tcp_tw_recycle=1表示開啟TCP連接中TIME-WAIT套接字的快速回收。默認(rèn)為0,表示關(guān)閉。

            net.ipv4.tcp_fin_timeout=30表示如果套接字由本端要求關(guān)閉,這個(gè)參數(shù)決定了它保持在FIN-WAIT-2狀態(tài)的時(shí)間。

            net.ipv4.tcp_keepalive_time=1200表示當(dāng)keepalive啟用時(shí),TCP發(fā)送keepalive消息的頻度。默認(rèn)是2小時(shí),這里改為20分鐘。

            net.ipv4.ip_local_port_range=1024 65000表示向外連接的端口范圍。默認(rèn)值很小:32768~61000,改為1024~65000。

            net.ipv4.tcp_max_syn_backlog=8192表示SYN隊(duì)列的長度,默認(rèn)為1024,加大隊(duì)列長度為8192,可以容納更多等待連接的網(wǎng)絡(luò)連接數(shù)。

            net.ipv4.tcp_max_tw_buckets=5000表示系統(tǒng)同時(shí)保持TIME_WAIT套接字的最大數(shù)量,如果超過這個(gè)數(shù)字,TIME_WAIT套接字將立刻被清除并打印警告信息。默認(rèn)為180000,改為5000。對(duì)于Apache、Nginx等服務(wù)器,前面介紹的幾個(gè)參數(shù)已經(jīng)可以很好地減少TIME_WAIT套接字?jǐn)?shù)量,但是對(duì)于Squid來說,效果卻不大。有了此參數(shù)就可以控制TIME_WAIT套接字的最大數(shù)量,避免Squid服務(wù)器被大量的TIME_WAIT套接字拖死。

            執(zhí)行以下命令使內(nèi)核配置立即生效:

          /sbin/sysctl -p

            如果是用于Apache或Nginx等的Web服務(wù)器,或Nginx的反向代理,則只需要更改以下幾項(xiàng)即可:

        19. net.ipv4.tcp_syncookies=1 
        20. net.ipv4.tcp_tw_reuse=1 
        21. net.ipv4.tcp_tw_recycle = 1 
        22. net.ipv4.ip_local_port_range = 1024 65000
        23.   執(zhí)行以下命令使內(nèi)核配置立即生效: /sbin/sysctl -p如果是郵件服務(wù)器,則建議內(nèi)核方案如下:

        24. net.ipv4.tcp_fin_timeout = 30 
        25. net.ipv4.tcp_keepalive_time = 300 
        26. net.ipv4.tcp_tw_reuse = 1 
        27. net.ipv4.tcp_tw_recycle = 1 
        28. net.ipv4.ip_local_port_range = 5000 65000  
        29. kernel.shmmax = 134217728
        30.   執(zhí)行以下命令使內(nèi)核配置立即生效: /sbin/sysctl -p當(dāng)然這些都只是最基本的更改,大家還可以根據(jù)自己的需求來更改內(nèi)核的設(shè)置,同樣也要本著穩(wěn)定的原則,如果服務(wù)器不穩(wěn)定的話,一切工作和努力都會(huì)白費(fèi)。如果以上優(yōu)化仍無法滿足你的要求,有可能你需要定制你的服務(wù)器內(nèi)核或升級(jí)服務(wù)器硬件。至于服務(wù)的配置優(yōu)化,超出了本章的內(nèi)容,大家可根據(jù)自己的需求有針對(duì)性地進(jìn)行更改。

          posted @ 2011-12-08 14:30 順其自然EVO 閱讀(1146) | 評(píng)論 (0)編輯 收藏

          輕松解決SQL Server 2005中的常見問題

          問題1:使用.net2005自帶的SQL-Express連接不上。

            解決方法:

            1、網(wǎng)絡(luò)防火墻阻止數(shù)據(jù)庫連接;

            2、默認(rèn)SQL-Express沒有啟動(dòng)Sa賬戶->下載一個(gè)management studio express界面工具管理SQL-Express

            3、無線網(wǎng)絡(luò)會(huì)出現(xiàn)根據(jù)機(jī)器名找不到SQL服務(wù)器的情況,直接用IP連接

            4、服務(wù)端通過開始菜單打開->配置工具->SQL Server外圍應(yīng)用配置器->服務(wù)和連接的外圍應(yīng)用配置器->遠(yuǎn)程連接->右邊選擇“本地連接和遠(yuǎn)程連接”->同時(shí)使用TCP/IP和named pipes.

            問題2:在Win-XP上安裝開發(fā)版提示“對(duì)性能監(jiān)視器計(jì)數(shù)器注冊(cè)表執(zhí)行系統(tǒng)配置檢查失敗”

            解決方法:

            注冊(cè)表定位到/local_machine/software/microsoft/windows nt/currentversion/perflib下,兩個(gè)值last counter 和last help 的值改成和004(英文系統(tǒng)為009)目錄中相關(guān)鍵值的最大值一樣。

            問題3:其他版本的SQL2005數(shù)據(jù)庫通過“復(fù)制”、“導(dǎo)出”、“備份”等方法將數(shù)據(jù)庫復(fù)制到SQL DEV上面去后,右鍵表、新建表等會(huì)出現(xiàn)以下錯(cuò)誤:

            類別不支持集合(或類別對(duì)象為遠(yuǎn)程對(duì)象) (異常來自 HRESULT:0x80040110 (CLASS_E_NOAGGREGATION)) (Microsoft.SqlServer.SqlTools.VSIntegration)

            分析:可能是SQL Server 2005的一個(gè)Bug,也可能是.net framework變化了,比如安裝了其他版本的SQL Server 2005。

            解決方法:

            經(jīng)驗(yàn)證,這樣操作先卸載SQL DEV(網(wǎng)上說是卸載客戶端即可,筆者是把所有的SQL Server 2005都刪掉),再重裝/修復(fù).NET 2.0 Framework,再重裝SQL DEV,解決問題。

            問題4:vs2005中g(shù)ridview不能刪除SQL2005中VARCHAR類型字段,提示--“異常詳細(xì)信息: System.Data.SqlClient.SqlException: 數(shù)據(jù)類型 ntext 和 nvarchar 在 equal to 運(yùn)算符中不兼容。”

            解決方法:

            SqlDataSource連接的時(shí)候不能選擇并發(fā)控制,就可以編輯和刪除了,否則即使不報(bào)錯(cuò),也無法操作。

            注釋:在安裝SQL Server 2005的過程中需要關(guān)閉注冊(cè)表監(jiān)視軟件和病毒防護(hù)等軟件。

          posted @ 2011-12-08 14:29 順其自然EVO 閱讀(361) | 評(píng)論 (0)編輯 收藏

          多線程的那點(diǎn)兒事(基礎(chǔ)篇)

          多線程編程是現(xiàn)代軟件技術(shù)中很重要的一個(gè)環(huán)節(jié)。要弄懂多線程,這就要牽涉到多進(jìn)程?當(dāng)然,要了解到多進(jìn)程,就要涉及到操作系統(tǒng)。不過大家也不要緊張,聽我慢慢道來。這其中的環(huán)節(jié)其實(shí)并不復(fù)雜。

            (1)單CPU下的多線程

            在沒有出現(xiàn)多核CPU之前,我們的計(jì)算資源是唯一的。如果系統(tǒng)中有多個(gè)任務(wù)要處理的話,那么就需要按照某種規(guī)則依次調(diào)度這些任務(wù)進(jìn)行處理。什么規(guī)則呢?可以是一些簡單的調(diào)度方法,比如說

            1)按照優(yōu)先級(jí)調(diào)度

            2)按照FIFO調(diào)度

            3)按照時(shí)間片調(diào)度等等

            當(dāng)然,除了CPU資源之外,系統(tǒng)中還有一些其他的資源需要共享,比如說內(nèi)存、文件、端口、socket等。既然前面說到系統(tǒng)中的資源是有限的,那么獲取這些資源的最小單元體是什么呢,其實(shí)就是進(jìn)程。

            舉個(gè)例子來說,在linux上面每一個(gè)享有資源的個(gè)體稱為task_struct,實(shí)際上和我們說的進(jìn)程是一樣的。我們可以看看task_struct(linux 0.11代碼)都包括哪些內(nèi)容

        31. struct task_struct {  
        32. /* these are hardcoded - don't touch */  
        33.     long state; /* -1 unrunnable, 0 runnable, >0 stopped */  
        34.     long counter;  
        35.     long priority;  
        36.     long signal;  
        37.     struct sigaction sigaction[32];  
        38.     long blocked;   /* bitmap of masked signals */  
        39. /* various fields */  
        40.     int exit_code;  
        41.     unsigned long start_code,end_code,end_data,brk,start_stack;  
        42.     long pid,father,pgrp,session,leader;  
        43.     unsigned short uid,euid,suid;  
        44.     unsigned short gid,egid,sgid;  
        45.     long alarm;  
        46.     long utime,stime,cutime,cstime,start_time;  
        47.     unsigned short used_math;  
        48. /* file system info */  
        49.     int tty;        /* -1 if no tty, so it must be signed */  
        50.     unsigned short umask;  
        51.     struct m_inode * pwd;  
        52.     struct m_inode * root;  
        53.     struct m_inode * executable;  
        54.     unsigned long close_on_exec;  
        55.     struct file * filp[NR_OPEN];  
        56. /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */  
        57.     struct desc_struct ldt[3];  
        58. /* tss for this task */  
        59.     struct tss_struct tss;  
        60. };
        61.   每一個(gè)task都有自己的pid,在系統(tǒng)中資源的分配都是按照pid進(jìn)行處理的。這也就說明,進(jìn)程確實(shí)是資源分配的主體。

            這時(shí)候,可能有朋友會(huì)問了,既然task_struct是資源分配的主體,那為什么又出來thread?為什么系統(tǒng)調(diào)度的時(shí)候是按照thread調(diào)度,而不是按照進(jìn)程調(diào)度呢?原因其實(shí)很簡單,進(jìn)程之間的數(shù)據(jù)溝通非常麻煩,因?yàn)槲覀冎园堰@些進(jìn)程分開,不正是希望它們之間不要相互影響嘛。

            假設(shè)是兩個(gè)進(jìn)程之間數(shù)據(jù)傳輸,那么需要如果需要對(duì)共享數(shù)據(jù)進(jìn)行訪問需要哪些步驟呢

            1)創(chuàng)建共享內(nèi)存

            2)訪問共享內(nèi)存->系統(tǒng)調(diào)用->讀取數(shù)據(jù)

            3)寫入共享內(nèi)存->系統(tǒng)調(diào)用->寫入數(shù)據(jù)

           要是寫個(gè)代碼,大家可能就更明白了

        62. #include <unistd.h>   
        63. #include <stdio.h>   
        64.   
        65. int value = 10;  
        66.   
        67. int main(int argc, char* argv[])  
        68. {  
        69.     int pid = fork();  
        70.     if(!pid){  
        71.         Value = 12;  
        72.         return 0;  
        73.     }  
        74.     printf("value = %d\n", value);  
        75.     return 1;  
        76. }
        77.   上面的代碼是一個(gè)創(chuàng)建子進(jìn)程的代碼,我們發(fā)現(xiàn)打印的value數(shù)值還是10。盡管中間創(chuàng)建了子進(jìn)程,修改了value的數(shù)值,但是我們發(fā)現(xiàn)打印下來的數(shù)值并沒有發(fā)生改變,這就說明了不同的進(jìn)程之間內(nèi)存上是不共享的。

            那么,如果修改成thread有什么好處呢?其實(shí)最大的好處就是每個(gè)thread除了享受單獨(dú)cpu調(diào)度的機(jī)會(huì),還能共享每個(gè)進(jìn)程下的所有資源。要是調(diào)度的單位是進(jìn)程,那么每個(gè)進(jìn)程只能干一件事情,但是進(jìn)程之間是需要相互交互數(shù)據(jù)的,而進(jìn)程之間的數(shù)據(jù)都需要系統(tǒng)調(diào)用才能應(yīng)用,這在無形之中就降低了數(shù)據(jù)的處理效率。

            (2)多核CPU下的多線程

            沒有出現(xiàn)多核之前,我們的CPU實(shí)際上是按照某種規(guī)則對(duì)線程依次進(jìn)行調(diào)度的。在某一個(gè)特定的時(shí)刻,CPU執(zhí)行的還是某一個(gè)特定的線程。然而,現(xiàn)在有了多核CPU,一切變得不一樣了,因?yàn)樵谀骋粫r(shí)刻很有可能確實(shí)是n個(gè)任務(wù)在n個(gè)核上運(yùn)行。我們可以編寫一個(gè)簡單的open mp測試一下,如果還是一個(gè)核,運(yùn)行的時(shí)間就應(yīng)該是一樣的。

        78. #include <omp.h>   
        79. #define MAX_VALUE 10000000   
        80.   
        81. double _test(int value)  
        82. {  
        83.     int index;  
        84.     double result;  
        85.   
        86.     result = 0.0;  
        87.     for(index = value + 1; index < MAX_VALUE; index +=2 )  
        88.         result += 1.0 / index;  
        89.   
        90.     return result;  
        91. }  
        92.   
        93. void test()  
        94. {  
        95.     int index;  
        96.     int time1;  
        97.     int time2;  
        98.     double value1,value2;  
        99.     double result[2];  
        100.   
        101.     time1 = 0;  
        102.     time2 = 0;  
        103.   
        104.     value1 = 0.0;  
        105.     time1 = GetTickCount();  
        106.     for(index = 1; index < MAX_VALUE; index ++)  
        107.         value1 += 1.0 / index;  
        108.   
        109.     time1 = GetTickCount() - time1;  
        110.   
        111.     value2 = 0.0;  
        112.     memset(result , 0, sizeof(double) * 2);  
        113.     time2 = GetTickCount();  
        114.   
        115. #pragma omp parallel for   
        116.     for(index = 0; index < 2; index++)  
        117.         result[index] = _test(index);  
        118.   
        119.     value2 = result[0] + result[1];  
        120.     time2 = GetTickCount() - time2;  
        121.   
        122.     printf("time1 = %d,time2 = %d\n",time1,time2);  
        123.     return;  
        124. }
        125.   (3)多線程編程

            為什么要多線程編程呢?這其中的原因很多,我們可以舉例解決

            1)有的是為了提高運(yùn)行的速度,比如多核cpu下的多線程

            2)有的是為了提高資源的利用率,比如在網(wǎng)絡(luò)環(huán)境下下載資源時(shí),時(shí)延常常很高,我們可以通過不同的thread從不同的地方獲取資源,這樣可以提高效率

            3)有的為了提供更好的服務(wù),比如說是服務(wù)器

            4)其他需要多線程編程的地方等等

          posted @ 2011-12-08 14:28 順其自然EVO 閱讀(175) | 評(píng)論 (0)編輯 收藏

          Java七步創(chuàng)建以JDBC連接數(shù)據(jù)庫的程序

          Java七步創(chuàng)建以JDBC連接數(shù)據(jù)庫的程序

           JDBC連接數(shù)據(jù)庫

            ◆ 創(chuàng)建一個(gè)以JDBC連接數(shù)據(jù)庫的程序,包含7個(gè)步驟:

            1、加載JDBC驅(qū)動(dòng)程序:

            在連接數(shù)據(jù)庫之前,首先要加載想要連接的數(shù)據(jù)庫的驅(qū)動(dòng)到JVM(Java虛擬機(jī)), 這通過java.lang.Class類的靜態(tài)方法forName(String className)實(shí)現(xiàn)。

            例如:

        126. try
        127. //加載MySql的驅(qū)動(dòng)類 
        128. Class.forName("com.mysql.jdbc.Driver") ; 
        129. }catch(ClassNotFoundException e){ 
        130. System.out.println("找不到驅(qū)動(dòng)程序類 ,加載驅(qū)動(dòng)失敗!"); 
        131. e.printStackTrace() ; 
        132. }
        133.   成功加載后,會(huì)將Driver類的實(shí)例注冊(cè)到DriverManager類中。

            2、提供JDBC連接的URL

            ◆ 連接URL定義了連接數(shù)據(jù)庫時(shí)的協(xié)議、子協(xié)議、數(shù)據(jù)源標(biāo)識(shí)。

            ◆ 書寫形式:協(xié)議:子協(xié)議:數(shù)據(jù)源標(biāo)識(shí)

            協(xié)議:在JDBC中總是以jdbc開始

            子協(xié)議:是橋連接的驅(qū)動(dòng)程序或是數(shù)據(jù)庫管理系統(tǒng)名稱。

            數(shù)據(jù)源標(biāo)識(shí):標(biāo)記找到數(shù)據(jù)庫來源的地址與連接端口。

            例如:(MySql的連接URL)

        134. jdbc:mysql: 
        135. //localhost:3306/test?useUnicode=true&characterEncoding=gbk ;
        136.   useUnicode=true:表示使用Unicode字符集。如果characterEncoding設(shè)置為gb2312或GBK,本參數(shù)必須設(shè)置為true 。characterEncoding=gbk:字符編碼方式。

            3、創(chuàng)建數(shù)據(jù)庫的連接

            ◆ 要連接數(shù)據(jù)庫,需要向java.sql.DriverManager請(qǐng)求并獲得Connection對(duì)象,該對(duì)象就代表一個(gè)數(shù)據(jù)庫的連接。

            ◆ 使用DriverManager的getConnectin(String url,String username,String password)方法傳入指定的欲連接的數(shù)據(jù)庫的路徑、數(shù)據(jù)庫的用戶名和 密碼來獲得。

            例如:

        137. //連接MySql數(shù)據(jù)庫,用戶名和密碼都是root 
        138. String url = "jdbc:mysql://localhost:3306/test" ; 
        139. String username = "root" ; 
        140. String password = "root" ; 
        141. try
        142. Connection con = 
        143. DriverManager.getConnection(url , username , password ) ; 
        144. }catch(SQLException se){ 
        145. System.out.println("數(shù)據(jù)庫連接失敗!"); 
        146. se.printStackTrace() ; 
        147. }
        148.   4、創(chuàng)建一個(gè)Statement

            ◆ 要執(zhí)行SQL語句,必須獲得java.sql.Statement實(shí)例,Statement實(shí)例分為以下3種類型:

            1、執(zhí)行靜態(tài)SQL語句。通常通過Statement實(shí)例實(shí)現(xiàn)。

            2、執(zhí)行動(dòng)態(tài)SQL語句。通常通過PreparedStatement實(shí)例實(shí)現(xiàn)。

            3、執(zhí)行數(shù)據(jù)庫存儲(chǔ)過程。通常通過CallableStatement實(shí)例實(shí)現(xiàn)。

            具體的實(shí)現(xiàn)方式:

        149. Statement stmt = con.createStatement() ; 
        150. PreparedStatement pstmt = con.prepareStatement(sql) ; 
        151. CallableStatement cstmt = 
        152. con.prepareCall("{CALL demoSp(? , ?)}") ;
        153. \\\5、執(zhí)行SQL語句

            Statement接口提供了三種執(zhí)行SQL語句的方法:executeQuery 、executeUpdate和execute

            1、ResultSet executeQuery(String sqlString):執(zhí)行查詢數(shù)據(jù)庫的SQL語句,返回一個(gè)結(jié)果集(ResultSet)對(duì)象。

            2、int executeUpdate(String sqlString):用于執(zhí)行INSERT、UPDATE或DELETE語句以及SQL DDL語句,如:CREATE TABLE和DROP TABLE等

            3、execute(sqlString):用于執(zhí)行返回多個(gè)結(jié)果集、多個(gè)更新計(jì)數(shù)或二者組合的語句。

            具體實(shí)現(xiàn)的代碼:

        154. ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ; 
        155. int rows = stmt.executeUpdate("INSERT INTO ...") ; 
        156. boolean flag = stmt.execute(String sql) ;
        157.   6、處理結(jié)果

            兩種情況:

            1、執(zhí)行更新返回的是本次操作影響到的記錄數(shù)。

            2、執(zhí)行查詢返回的結(jié)果是一個(gè)ResultSet對(duì)象。

            ◆ ResultSet包含符合SQL語句中條件的所有行,并且它通過一套get方法提供了對(duì)這些

            行中數(shù)據(jù)的訪問。

            ◆ 使用結(jié)果集(ResultSet)對(duì)象的訪問方法獲取數(shù)據(jù):

        158. while(rs.next()){ 
        159. String name = rs.getString("name") ; 
        160. String pass = rs.getString(1) ; // 此方法比較高效 
        161. }
        162.   (列是從左到右編號(hào)的,并且從列1開始)

            7、關(guān)閉JDBC對(duì)象

            操作完成以后要把所有使用的JDBC對(duì)象全都關(guān)閉,以釋放JDBC資源,關(guān)閉順序和聲明順序相反:

            1、關(guān)閉記錄集

            2、關(guān)閉聲明

            3、關(guān)閉連接對(duì)象

        163. if(rs != null){ // 關(guān)閉記錄集 
        164. try
        165. rs.close() ; 
        166. }catch(SQLException e){ 
        167. e.printStackTrace() ; 
        168. if(stmt != null){ // 關(guān)閉聲明 
        169. try
        170. stmt.close() ; 
        171. }catch(SQLException e){ 
        172. e.printStackTrace() ; 
        173. if(conn != null){ // 關(guān)閉連接對(duì)象 
        174. try
        175. conn.close() ; 
        176. }catch(SQLException e){ 
        177. e.printStackTrace() ; 
        178. }
        179. posted @ 2011-12-08 14:20 順其自然EVO 閱讀(276) | 評(píng)論 (0)編輯 收藏

          Code Review的方式和流程

          Code Review的方式和流程

          經(jīng)過在公司1年多的code review的經(jīng)驗(yàn)回顧:原來有fisheye,開發(fā)提交代碼后旺旺通知測試工程師,并通過讀代碼來了解測試范圍,并發(fā)現(xiàn)代碼中的錯(cuò)誤。

            后來,最近半年的項(xiàng)目、日常測試過程中都是開發(fā)提交代碼后,測試和開發(fā)一起借用SVN工具等代碼版本控制工具,或Eclipse 等IDE進(jìn)行Code Review。

            這其中的一個(gè)轉(zhuǎn)變就是測試由被動(dòng)接收消息,到主動(dòng)查看SVN 的log看代碼變動(dòng)。測試工程師的態(tài)度由被動(dòng)變?yōu)橹鲃?dòng),是個(gè)不小的進(jìn)步。

            目前看來,進(jìn)行 Code Review 的目的或效果有:

            1、讓測試熟悉所測產(chǎn)品的業(yè)務(wù)代碼,提升代碼的閱讀能力;

            2、提早發(fā)現(xiàn)代碼里面的bug,低成本保障質(zhì)量,防患于未然;

            3、提前預(yù)知并評(píng)估并確認(rèn)測試范圍,減少測試工作量;

            4、促進(jìn)開發(fā)、測試間的溝通、交流和協(xié)作。

            功能測試工程師參加code  review提前做的一些準(zhǔn)備:

            1、簡單的編碼規(guī)范

            2、Java編程的基本知識(shí)

            經(jīng)過這Code Review的實(shí)踐,感覺Code Review目前比較適合我們工作的方式是:

          階段

          Code Review的方式

          準(zhǔn)備

          1、了解開發(fā)的UC設(shè)計(jì),及基本的編碼知識(shí);
          2、了解基本的代碼的編碼規(guī)范;
          3、確定code review的范圍:業(yè)務(wù)的核心代碼邏輯。

          形式

          項(xiàng)目:會(huì)議室+投影儀。日常:在開發(fā)/測試的位置上即可。

          參加人員

          PM,PTM,相關(guān)開發(fā)工程師、測試工程師

          可以采用的方法

          1、編碼人員講解,其他開發(fā)、測試人員檢查。
          2、代碼靜態(tài)檢測工具:Findbug
          3、缺陷檢查表,但是這個(gè)太正式了,不一定需要。

          注意點(diǎn)

          1、限時(shí):一般不要超過1個(gè)小時(shí)為宜;如果量大,最好分批review。
          2、不要現(xiàn)場修改代碼,發(fā)現(xiàn)問題后,測試可以直接在bug管理平臺(tái)記錄。

          產(chǎn)出

          1、Bug記錄;
          2、靜態(tài)分析錯(cuò)誤報(bào)告;
          3、結(jié)果:code review 是否通過。

            比較合適的,并且目前使用的流程是:

          posted @ 2011-12-07 11:34 順其自然EVO 閱讀(798) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共394頁: First 上一頁 350 351 352 353 354 355 356 357 358 下一頁 Last 
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 银川市| 雷州市| 龙门县| 林甸县| 永嘉县| 永寿县| 黄平县| 开平市| 东阳市| 略阳县| 封丘县| 广汉市| 平度市| 桐柏县| 青龙| 酉阳| 和平县| 金堂县| 永州市| 永仁县| 满城县| 蒲江县| 天水市| 东港市| 从江县| 科技| 双城市| 获嘉县| 都匀市| 中西区| 伊宁县| 巢湖市| 中方县| 洪湖市| 溧水县| 吕梁市| 铁力市| 巧家县| 青海省| 尼木县| 墨玉县|