接口測試從零開始5_教你如何使用ibatis
摘要: 1、創建pojo類 public classPingJia 2、創建Dao接口 publicinterfaceIPingJiaDao 3、使用ibatis編寫實現類 1)通過pom依賴引入ibatis包 <dependency> <groupId>com.ibatis&... 閱讀全文posted @ 2011-12-13 15:50 順其自然EVO 閱讀(567) | 評論 (0) | 編輯 收藏
blog已經轉移至github,大家請訪問 http://qaseven.github.io/
posted @ 2011-12-13 15:50 順其自然EVO 閱讀(567) | 評論 (0) | 編輯 收藏
在對Patrick Copeland的采訪的第二部分,我們主要討論了管理一個全球開發團隊的挑戰;食物刺激對程序員的作用;好的測試工程師和超nb測試工程師之間的區別;以及為何某些公司始終無法提供靠譜的軟件。
問:管理一個跨越一打以上國家的團隊有什么挑戰?在這樣的團隊中管理人員、流程、產品有什么樣的困難?還有,你一般幾點睡覺?
答:“確保對人員的掌控”<談到這個時他臉上掛著邪惡的微笑>不是Google的解決方案。實際上,我們的團隊結構在業界是非典型的。首先,我們是扁平化架構,即使是Google新雇員,和最高管理層之間的層級也只有幾步而已。還有就是公司內的那些半自治人員和團隊。在這個非典型體系中,讓管理者控制一切顯然不太合適。與之相反,我更愿意讓nb的人組成團隊然后讓他們自己管理自己。我的重心會放在幫助團隊提高效率上。大體上來說,我們評價Google管理者的指標就是他們讓聰明人完成任務的能力。而且我們認為,大部分人一旦擁有超過15個下屬,就會陷入混亂,投入到真正的管理上的時間就會減少。
確保我們向同一方向努力的神器是——OKRs,這個東東是董事會成員John Doerr在2000年帶入Google的。John強調由公司級目標派生部門目標的重要性;與之對應的,每個員工的OKRs應該支持團隊和整個公司范圍的目標。在2000年第一季度,我們發布了第一個公司級別的OKRs,其中包括“每秒800萬次搜索”以及“為公司尋找CEO”。自那時起,我們已經取得了長足的進步。
問:我們注意到Google給雇員提供了大量獨特友好的工作環境。對于你們的工程師,這些手段是否依然有效呢?或者(如同我們在uTest做的那樣)你們正準備把工程師拷在桌子上,然后他們每寫一行代碼你們扔一個小食品以示獎勵?不開玩笑了,真正的問題是,如何保證開放的環境下工程師依然可以做出出色的軟件?
答:我們有開放的文化,工程師有足夠的自由去探索他們感興趣的領域。我們有一個“20%時間段”,在這些時間中我們鼓勵工程師去探索他們主要業務之外的領域。
(好的)文化會衍生出好的產品嗎?我們這么認為,但是這二者之間的關系很難判定。有些人會傾向于使用那些“產品化度量”:代碼行數、簽入次數等等。我們(非正式的)阻止這種做法,因為類似這種度量會造成一些不可預知的問題:例如人們會使用一些“技巧”,以在系統中獲得“所謂的成功”。(除了帶給最終客戶的創新)我們衡量績效的最重要方式是每季度一次的同事評審。這種系統會強化你對團隊工作的認識,確保你在同事中擁有影響力,并建筑尊重。這種評判是主觀的,可能看上去很難操作,但是對于塑造個體價值功效顯著。
另外,扔食物在我們那里必然沒效果,因為在Google員工可以免費享用各種美食。
問:好測試工程師和卓越的測試工程師之間有什么區別?
答:好的測試工程師是可以訓練出來的。基礎的要求有:計算機基礎知識,對于應用領域的認識,對于客戶用例的強力理解,客戶角度的視野,對于度量的把握以及對開發流程的關注。
卓越的測試工程師則意味著傳說中的10%,他們非常罕見和稀有。不是每一個人都可以成為卓越的人。從個人經驗角度看,卓越的開發工程師并不一定能成為卓越的測試工程師,但是卓越的測試工程師(擁有很強的設計能力)則可以成為卓越的開發者。這與一種心態和激情有關。從超過100次面試得來的經驗看,我認為,卓越來自于:1)一種發現問題的特殊潛質;2)被潛質指引去測試和發現問題的激情。換句話說,他們喜歡測試并且善于測試。他們也常常感覺到測試中的挑戰,大于等于開發中的挑戰,并為之感到特爽。一個大牛測試工程師,他們有測試的基因,正確的態度,他們總是很容易的找到一份工作。他們就像金子一樣的寶貴。
問:您認為,導致我們無法在帶著(交付日期,優先級,競爭)鐐銬下制作出高質量的產品的最大原因是什么?換句話說,為什么不是每一家公司每一次都可以發布世界級的產品?
答:我經歷的每個產品都有不同的故事。每個故事的情節那就是有一句說一句了。某些產品我們幾乎可以掌控全部(例如技術選擇)。而另外一些產品中我們只能控制一部分。有些因素則完全不受我們的掌控(例如競爭對手想咋整)。
有些公司試圖開發一些規范的流程。這些看上去冠冕堂皇的流程都說自己可以:提高效率,消滅不確定性,維護質量,如此等等。這些重口味開發流程在造大灰機的時候灰常有用——這也確實被一些nb飛機制造商證明了。不過在程序猿們看來,這種流程可能過于繁雜,會破壞他們創造軟件的心情。相反的,木有流程的流程則可能導致你的開發無法被復制。你需要在大流程和沒留成之間做出平衡。
讓我們把灰機制造和軟件開發過程放在一起比一比。在飛行條件具備和飛行員有經驗的情況下,制造灰機的核心就剩下了平衡必要條件:超重或推力不足在一些情況下就會導致災難。同樣的,對于團隊,產品和流程這些虛擬因素也是如此。例如,在項目后期猛招工程師是沒法提供升力的。再比如,采用一套新流程可能會給團隊帶來一時的新推力,但是也可能在中長期破壞團隊的創新能力。
敏捷開發的流行說明程序猿們需要更好的平衡和創造性。我們的軟件質量也確實提升并且過程可控了,我們必須鼓勵創新。我們需要鼓勵那些給客戶帶來價值的或者是解決了困難問題的奇思妙想。話句話說,我們要保持團隊在天上自由的灰啊灰。
posted @ 2011-12-13 15:42 順其自然EVO 閱讀(197) | 評論 (0) | 編輯 收藏
三、評審在高質量軟件開發的實際應用
3.1 高質量軟件開發項目介紹
高質量軟件,如電信軟件、金融證券類軟件等,有較嚴格的要求:可用性要求非常高,并且不會因為系統維護和擴展而帶來運營中斷;支持使用現有管理工具和標準進行遠程管理;能夠提供更出色的性能以及運營在高可用性集群上的能力,減少任何單點的軟硬件失效現象。五個九(99.999%)意味著一個系統的宕機時間一年不超過5分26秒。因此高質量軟件項目是一種對可用性、可靠性、穩定性要求非常高的軟件項目,要求軟件能夠每周7*24工作。
因此高質量軟件開發一般采用嚴格的軟件開發過程,明確定義每個階段的質量目標和要求,嚴格項目軟件開發過程控制。
我們在多個高質量軟件開發項目中成功地采用了評審技術,并發揮了巨大的作用。從這些項目的實際開發過程中,我們針對于規模從30人月——300人月,代碼行數從5萬行——30萬行的運營支撐系統項目制定了項目評審流程和相關要求。
3.2 軟件過程定義
軟件過程主要分為項目立項階段、需求分析階段、設計階段、編碼實現階段、測試階段(包括集成測試、系統測試和用戶驗收測試)、實施階段和維護階段,項目管理工作橫貫于所有的階段。詳細流程見流程圖。
在軟件過程中,我們定義了以下角色:
1)客戶
2)銷售人員
3)項目經理
4)系統分析員
5)系統架構師
6)開發工程師
7)質量工程師
8)技術支持人員
在規劃質量體系時,我們參考PMBOK對項目質量管理的要求,將項目質量管理過程設計為三個階段:
1)質量規劃——確定質量活動的流程和標準,如軟件過程定義,質量達標定義等;
2)實施質量保證——編寫相應的測試計劃、執行測試和評審活動;
3)實施質量控制——監控質量保證活動的結果,判斷是否達標,如不達標,則采取相應的風險防范措施。
3.3 軟件評審過程及標準定義
我們在整體軟件過程中明確定義了需要軟件評審的過程及實施的方法。
3.3.1 采用審查的過程
采用最嚴格最系統的評審方法——審查的軟件過程有:
1)《軟件需求規格說明書》的評審
2)《概要設計說明書》的評審
3)《詳細設計說明書》的評審
4)代碼評審
5)《單元測試計劃》的評審
6)《集成測試計劃》的評審
7)《系統測試計劃》的評審
對于文檔評審以文檔頁數為基數,要求每頁發現的缺陷數有一個目標值,并規定了上下限的范圍。對于代碼評審以代碼行數為基數,要求每千行代碼發現的缺陷數有一個目標值,并規定了上下限的范圍。這個審查的缺陷數標準如下表。
軟件過程審查的質量目標
質量目標 目標 下限 上限
SRS文檔Review缺陷發現密度(個/頁) 0.80 0.50 1.10
HLD文檔Review缺陷發現密度(個/頁) 0.70 0.50 0.90
LLD文檔Review缺陷發現密度(個/頁) 0.43 0.22 0.64
代碼檢視缺陷發現密度(個/KLOC) 10.62 7.43 13.81
單元測試計劃Review缺陷發現密度(個/頁) 0.43 0.22 0.64
集成測試計劃Review缺陷發現密度(個/頁) 0.70 0.50 0.90
系統測試計劃Review缺陷發現密度(個/頁) 0.80 0.50 1.10
如果發現的缺陷密度低于或高于質量目標范圍,則我們需要分析其原因,然后根據原因進行返工或相應處理流程。這要和實際情況相結合,具體情況具體分析:如某個開發工程師的水平和素質非常高,他的代碼一般很少出錯,這樣他的代碼檢視缺陷密度低是屬于正常的;而另外一個工程師水平一般,但發現的缺陷密度也很低,但原因是屬于檢視的過程不嚴格,大家沒有時間來進行嚴格的評審,則此時需要重新進行檢視。
3.3.2 采用小組評審的過程
采用小組評審的軟件過程主要包括對客戶需求的評審、項目計劃的評審和維護計劃的評審。
對客戶需求的評審參加人員有項目經理、系統分析員、系統架構師、質量部主管等。
項目計劃的評審主要由項目經理、系統分析員、系統架構師、質量部主管和部門經理等參加,對人力資源、進度和質量管控等進行評審。
維護計劃由項目經理、技術支持人員、質量部主管和客戶服務人員參加,對人力資源、管控流程等進行評審。
3.3.3 采用走查評審的過程
需求分析過程中,系統分析員、系統架構師相互之間的走查;
設計過程中,系統分析員、系統架構師相互之間的走查;
在進入維護階段時,作者需和維護人員進行走查,讓維護人員能夠維護作者的工作產品。
3.3.4 采用桌查的過程
采用桌查的過程主要集中在代碼提交階段,主要是經驗豐富的開發人員對提交的代碼進行檢查,合格的產品才會提交到CVS上面。
具體實施方法為:開發經驗較少(8年以下開發經驗)的開發人員在提交代碼時,請經驗豐富(10年以上開發經驗)的開發人員進行桌查,沒有明顯問題后才允許提交;經驗豐富的開發人員提交代碼時也需另一名經驗豐富的開發人員桌查后方可提交。
3.3.5 采用臨時評審的過程
代碼編寫階段開發工程師之間的臨時評審;
其他開發階段,開發人員相互之間的臨時評審。
3.3.6 采用結隊編程的過程
針對于需求不明確、采用迭代增量開發過程的小規模項目,采用極限編程時,建議采用結隊編程,但一般不做強制規定。
我們實際采用極限編程思想進行了兩個項目(一個內部項目和一個外部項目)的開發,實際上取得了非常好的效果。開發人員實際產出值達到了5000行代碼/人月以上。當然這些項目不太大,同時文檔編寫比較簡單。
3.4 審查流程定義
我們規定了審查流程的定義,其他評審技術只是采用了其中的流程和管理思想。
3.5 軟件評審效果分析
我們強化了軟件評審技術后,在實際過程中取得了非常好的效果。以一個網絡流量分析的項目為實例,在第一期沒有嚴格實施軟件評審技術,而第二期嚴格實施了軟件評審技術,其中審查數據如下表。
評審過程數據及質量分析實例
文件/模塊 計算基數(頁數/KLOC) 致命 嚴重 一般 提示 總和 標準(目標/下限-上限) 比例 達標與否
SRS 42 1 1 29 10 31 0.8 / 0.5~1.1 0.738 OK
STP 58 22 15 12 37 0.8 / 0.5~1.1 0.638 OK
HLD 34 4 15 29 19 0.7 / 0.5~0.9 0.559 OK
LLD 205 11 59 29 70 0.43 / 0.22~0.64 0.341 OK
UTP 217 15 80 15 95 0.43 / 0.22~0.64 0.438 OK
CodeReview 50 7 372 151 379 10.62 / 7.43~13.8 7.580 OK
SITP 50 6 98 112 30 216 5.65/3.86~8.44 4.320 OK
產生的效果為:
1)產出量:單位開發人員的產出量由950行代碼/人月(全流程)增長到1320行代碼/人月(全流程),增長量為38.9%。關鍵原因在于大在減少了項目后期返工的工作量。考慮由于項目熟悉和學習曲線等的原因,實際的產出增長量應該超過20%。
2)產品質量(遺留缺陷密度):我們從軟件系統的遺留缺陷率來分析系統的質量情況。在半年的維護時間內,第一期代碼行為4萬行,嚴重缺陷有5個,一般缺陷有32個,嚴重缺陷發現密度為0.125個缺陷/千行代碼,總遺留缺陷發現密度為0.925個缺陷/千行代碼;第二期代碼行數為5萬行,嚴重缺陷有1個(屬于客戶需求問題引發的設計缺陷),一般缺陷有15個,嚴重缺陷發現密度為0.02個缺陷/千行代碼,總遺留缺陷發現密度為0.32個缺陷/千行代碼。因此嚴重缺陷發現密度改進了84%,一般缺陷發現密度改進了65.4%。
3)客戶滿意度:第一期客戶嚴重不滿意,稱我們在做玩具,滿意度只有22%;第二期客戶滿意度大幅上升,稱我們是專業人士,非常敬業,為他們所欽佩,滿意度達到了91%。因此滿意度提高了314%。
最主要的是,我們采用了軟件評審技術,規范了軟件開發過程的標準,并積累了實際的軟件開發過程數據,為后面的項目管理和過程控制提供了寶貴的軟件過程財富。
四、總結和展望
在實際工作中,我們以前掌握的過程數據不多,基本上一步一步摸索著前進,對于過程數據也在不斷的收集及整理中。對于評審技術而言,其中最重要的一點是采用多種實際工具和手段,如針對每個過程進行評審的《缺陷檢查表》等,我們也在逐步地完善這套體系和過程數據,從而為我們的過程改進不斷提供支持。
相關鏈接:
posted @ 2011-12-13 15:37 順其自然EVO 閱讀(309) | 評論 (0) | 編輯 收藏
要想了解NoSQL,必須先了解現有的這些工具,去理解那些引導它們開拓出新的存儲領域的設計思路。
NoSQL 其名
在給 NoSQL 下定義之前,我們先來試著從它的名字上做一下解讀。顧名思義,NoSQL 系統的數據操作接口應該是非 SQL 類型的。但在 NoSQL 社區,NoSQL 被賦予了更具有包容性的含義,其意為 Not Only SQL,即 NoSQL 提供了一種與傳統關系型數據庫不同的存儲模式,這為開發者提供了關系型數據庫之外的另一種選擇。
NoSQL 的啟示
NoSQL 運動受到了很多相關研究論文的啟示,在所有資料中,最核心的有兩個:Google 的 BigTable 論文和 Amazon 的 Dynamo 論文。
特性概述
NoSQL 系統舍棄了一些 SQL 標準中的功能,取而代之的是一些簡單靈活的功能。NoSQL 的構建思想就是盡量簡化數據操作,盡量讓操作的執行效率可預估。當你去考查一個 NoSQL 系統時,下面的幾點是值得注意的。
數據模型及操作模型:你的應用層數據模型是行、對象還是文檔型的呢?這個系統是否能支持你進行一些統計工作呢?
可靠性:當你更新數據時,新的數據是否立刻寫到持久化存儲中去了?新的數據是否同步到多臺機器上了?
擴展性:你的數據量有多大,單機是否能容下?你的讀寫量需求單機是否能支持?
分區策略:考慮到對擴展性、可用性或者持久性的要求,你是否需要一份數據被存在多臺機器上?你是否需要知道或者說你能否知道數據在哪臺機器上?
一致性:你的數據是否被復制到了多臺機器上?這些不同節點的數據如何保證一致性?
事務機制:業務是否需要 ACID 事務機制?
單機性能:如果你打算持久化的將數據存在磁盤上,哪種數據結構能滿足你的需求(你的需求是讀多還是寫多)?寫操作是否會成為磁盤瓶頸?
負載可評估:對于一個讀多寫少的應用,諸如響應用戶請求的網絡應用,我們總會花很多精力來關注負載情況。你可能需要進行數據規模的監控,對多個用戶的數據進行匯總統計。你的應用場景是否需要這樣的功能呢?
NoSQL 數據模型及操作模型
數據庫的數據模型指的是數據在數據庫中的組織方式,數據庫的操作模型指的是存取這些數據的方式。通常數據模型包括關系模型、鍵值模型以及各種圖 結構模型。操作語言可能包括 SQL、鍵值查詢及 MapReduce 等。NoSQL 通常結合了多種數據模型和操作模型,提供不一樣的架構方式。
基于Key值存儲的NoSQL數據模型
在鍵值型系統中,復雜的聯合查詢以及滿足多個條件的數據查詢操作就不那么容易實現了,需要換一種思維來建立和使用鍵名。比如要獲取部門號為 20 的所有員工的信息,應用層可以先獲取 Key 為 employee_departments:20的這個列表,然后再循環地拿這個列表中的 ID 通過獲取 employee:ID 得到所有員工的信息。
Key-Value 存儲
Key-Value 存儲可以說是最簡單的 NoSQL 存儲,每個 Key 值對應一個任意的數據值。對 NoSQL 系統來說,這個任意的數據值是什么,它并不關心。比如在員工信念數據庫里,employee:30這個 Key 對應的可能就是一段包含員工所有信息的二進制數據。這個二進制的格式可能是 Protocol Buffer、Thrift 或者 Avro 都無所謂。
Key-結構化數據存儲
Key-結構化數據存儲的典型代表是 Redis,Redis 將 Key-Value 存儲的 Value 變成了結構化的數據類型。Value 的類型包括數字、字符串、列表、集合以及有序集合。除了 set/get/delete 操作以為,Redis 還提供了很多針對以上數據類型的特殊操作,比如針對數字可以執行增、減操作,對 list 可以執行 push/pop 操作,通過提供這種針對單個 Value 進行的特定類型的操作,Redis 可以說實現了功能與性能的平衡。
Key-文檔存儲
Key-文檔存儲的代表有 CouchDB、MongoDB 和 Riak。這種存儲結構下 Key-Value 的 Value 是結構化的文檔,通常這些文檔是被轉換成 JSON 或者類似于 JSON 的結構進行存儲。文檔可以存儲列表,鍵值對以及層次結構復雜的文檔。
BigTable 的列簇式存儲
HBase 和 Cassandra 的數據模型都借鑒自 Google 的 BigTable。這種數據模型的特點是列式存儲,每一行數據的各項被存儲在不同的列中(這些列的集合稱作列簇)。而每一列中每一個數據都包含一個時間戳 屬性,這樣列中的同一個數據項的多個版本都能保存下來。
列式存儲可以這樣理解:將行 ID、列簇號,列號以及時間戳一起,組成一個 Key,然后將 Value 按 Key 的順序進行存儲。Key 值的結構化使這種數據結構能夠實現一些特別的功能,最常用的就是將一個數據的多個版本存成時間戳不同的幾個值,這樣就能方便地保存歷史數據。這種結構也能 天然地進行高效的松散列數據(在很多行中并沒有某列的數據)存儲。當然,對于那些很少有某一行有 NULL 值的列,由于每一個數據必須包含列標識,這又會造成空間的浪費。
圖結構存儲
圖結構存儲是 NoSQL 的另一種存儲實現。其指導思想是:數據并非對等的,關系型的存儲或者鍵值對的存儲,可能都不是最好的存儲方式。圖結構是計算機科學的基礎結構之一,Neo4j 和 HyperGraphDB 是當前最流行的圖結構數據庫。
復雜查詢
在 NoSQL 存儲系統中,有很多比鍵值查找更復雜的操作。比如 MongoDB 可以在任意數據行上建立索引,可以使用 Javascript 語法設定復雜的查詢條件。BigTable 型的系統通常支持對單獨某一行的數據進行遍歷,允許對單列的數據進行按特定條件的篩選。CouchDB 允許你創建同一份數據的多個視圖,通過運行 MapReduce 任務來實現一些更為復雜的查詢或者更新操作。很多 NoSQL 系統都支持與 Hadoop 或者其他 MapReduce 框架結合來進行一些大規模數據分析工作。
事務機制
與關系型數據庫不同的是,NoSQL 系統通常注重性能和擴展性,而非事務機制。傳統的 SQL 數據庫的事務通常都是支持 ACID 的強事務機制。ACID 的支持使得應用者能夠很清楚他們當前的數據狀態。對很多 NoSQL 系統來說,對性能的考慮遠在 ACID 的保證之上。通常 NoSQL 系統僅提供行級別的原子性保證,也就是說同時對同一個 Key 下的數據進行的兩個操作,在實際執行時是會串行的,保證了每一個 Key-Value 對不會被破壞。
Schema-free 的存儲
還有一個很多 NoSQL 的共同點,就是它通常并沒有強制的數據結構約束。即使是在文檔型存儲或者列式存儲上,也不會要求某一個數據列在每一行數據上都必須存在。
數據可靠性
最理想的狀態是,數據庫會把所有寫操作立刻寫到持久化存儲的設備,同時復制多個副本到不同地理位置的不同節點上,以防止數據丟失。但這種對數據安全性的要求對性能是有影響的,所以不同的 NoSQL 系統在自身性能的考慮下,在數據安全上采取了不太一樣的策略。
單機可靠性
單機可靠性理解起來非常簡單,它的定義是寫操作不會由于機器重啟或者斷電而丟失。通常單機可靠性的保證是通過把數據寫到磁盤來完成的,而這通常會造成磁盤I/O成為整個系統的瓶頸。下面我們談談一些在單機可靠性的保證下提高性能的方法。
控制fsync的調用頻率
Redis 提供了幾種對 fsync 調用頻率的控制方法。應用開發者可以配置 Redis 在每次更新操作后都執行一次 fsync,這樣會比較安全,當然也就比較慢。Redis 也可以設置成N秒種調用一次 fsync,這樣性能會更好一點。但這樣的后果就是一旦出現故障,最多可能導致N秒內的數據丟失。而對一些可靠性要求不太高的場合(比如僅僅把 Redis 當 Cache 用的時候),應用開發者甚至可以直接關掉 fsync 的調用:讓操作系統來決定什么時候需要把數據 flush 到磁盤(譯者注:這只是 Redis append only file 的機制,Redis 是可以關閉 aof 日志的,另外,Redis 本身支持將內存中數據 dump 成 rdb 文件的機制,和上面說的不是一回事)。
使用日志型的數據結構
Cassandra、HBase、Redis 和 Riak 都會把寫操作順序的寫入到一個日志文件中。相對于存儲系統中的其他數據結構,上面說到的日志文件可以頻繁地進行 fsync 操作,這樣就把對磁盤的隨機寫變成順序寫了。
通過合并寫操作提高吞吐性能
Cassandra 有一個機制,它會把一小段時間內的幾個并發的寫操作放在一起進行一次 fsync 調用,這種做法叫 group commit。
多機可靠性
由于硬件層面有時會造成無法恢復的損壞,單機可靠性的保證在這時就鞭長莫及了。對于一些重要數據,跨機器做備份保存是必備的安全措施。一些 NoSQL 系統提供了多機可靠性的支持。
Redis 采用傳統的主從數據同步的方式。
MongoDB 提供了一種叫 Replica Sets 高可用架構。
Riak、Cassandra 和 Voldemort 提供了一些更靈活的可配置策略,并提供一個可配置的參數N,代表每一個數據會被備份的份數。為了應對整個數據中心出現故障的情況,需要實現跨數據中心的多機備份功能。
橫向擴展帶來性能提升
橫向擴展的目標是達到線性的效果,即如果你增加一倍的機器,那么負載能力應該也能相應的增加一倍。其主要需要解決的問題是如何讓數據在多臺機器間分布,這里面涉及到分片技術。
分片的意思,就是沒有任何一臺機器可以處理所有寫請求,也沒有任何一臺機器可以處理對所有數據的讀請求。下面我們將會對 hash 分片和范圍分片兩種分片方式進行描述。
如非必要,請勿分片
分片會導致系統復雜程度大增,所以,如果沒有必要,請不要使用分片。普通情況下,我們可以使用讀寫分離和構建緩存的方式來緩解我們的數據讀壓力。但如果寫操作達到單點無法承擔的程度,那我們可能就真的需要進行分片了。
通過協調器進行數據分片
一種分片策略是通過引入一個中間代理層來實現,該代理層記錄數據在各個節點的分布狀況,所有讀寫請求都通過代理層來做路由。比如與 CouchDB 的兩個項目:Lounge 和 BigCouch。類似的,Twitter 自己也實現了一個叫 Gizzard 的協調器,可以實現數據分片和備份功能。
一致性 hash 環算法
一致性 hash 是一種被廣泛應用的技術,其最早在一個叫 distributed hash tables(DHTs)的系統中進行使用。那些類 Dynamo 的應用,比如 Cassandra、Voldemort 和 Riak,基本上都使用了一致性 hash 環算法。
如圖 1 所示,一致性 hash 環算法有一個 hash 函數H,所有存儲數據的節點和數據本身都可以通過這個函數算出一個 hash 值,作為自己在下面環上的位置。然后每個節點會負責存儲其 hash 值到下一個節點間的所有數據的存儲。這樣使得即使節點數變化了,大部分數據并不需要進行遷移。
圖 1 一致性 hash 環算法的 hash 函數
連續范圍分區
使用連續范圍分區的方法進行數據分片,需要我們保存一份映射關系表,標明哪一段 Key 值對應存在哪臺機器上。與一致性 hash 類似,連續范圍分區會把 Key 值按連續的范圍分段,每段數據會被指定保存在某個節點上,然后會被冗余備份到其他節點。
BigTable 的處理方式
Google BigTable 論文中描述了一種范圍分區方式,它將數據切分成一個個的 tablet 數據塊。每個 tablet 保存一定數量的鍵值對。然后存儲在 Tablet 服務器上。tablet 塊的大小會保持在一定范圍,太大的塊會分裂成兩個,太小的塊又會合并成一個。BigTable 通過一個叫 Chubby 的模塊來實現節點狀態檢測。類似的在 Hadoop 中有一個叫 ZooKeeper 的工具實現此功能。
一致性
上面講到了通過將數據冗余存儲到不同的節點來保證數據安全和減輕負載,下面我們來看看這樣做引發的一個問題:保證數據在多個節點間的一致性是非常困難的。在多個點間保持數據的一致性的問題,也就是本章的主題。下面我們首先來看一下在著名的 CAP 理論。
一致性(C):在分布式系統中的所有數據備份,在同一時刻是否同樣的值。
可用性(A):在集群中一部分節點故障后,集群整體是否還能響應客戶端的讀寫請求。
分區容忍性(P):集群中的某些節點在無法聯系后,集群整體是否還能繼續進行服務。
而 CAP 理論就是說在分布式存儲系統中,最多只能實現上面的兩點。再加之當前的網絡硬件肯定會出現延遲丟包等問題,所以分區容忍性是我們必須需要實現的。結果就是我們只能在一致性和可用性之間進行權衡,沒有 NoSQL 系統能同時保證這三點。
對一致性的保證,通常有強一致性和弱一致性的選擇,而在弱一致性里,又以最終一致性的實現較為普遍。
如果我們采用 NRW 的設定,N為數據需要備份的份數,R為讀操作需要讀到的不同節點上的數據份數,W為寫操作需要成功寫到不同節點的數據份數,那么當R+W>N時,既 是強一致性的保證,當R+W
寫在最后的話
目前 NoSQL 系統來處在它的萌芽期,我們上面討論到的很多 NoSQL 系統,它們的架構、設計和接口可能都會改變。本章的目的,不在于讓你了解這些 NoSQL 系統目前是如何工作的,而在于讓你理解這些系統之所以這樣實現的原因。NoSQL 系統把更多的設計工作留給了應用開發工作者來做。理解上面這些組件的架構,不僅能讓你寫出下一個 NoSQL 系統,更讓你對現有系統應用得更好。
posted @ 2011-12-13 15:28 順其自然EVO 閱讀(144) | 評論 (0) | 編輯 收藏
簡單的說,內部類就是將一個類的定義放到另一個類的定義內部。內部類分為:成員內部類、局部內部類、靜態內部類、匿名內部類。
成員內部類:作為外部類的一個成員存在,與外部類的屬性、方法并列。
優點:一方面,內部類作為外部類的成員,可以訪問外部類的私有成員或屬性。(即使聲明為private,但是對于處于其內部的內部類還是可見的。)另一方面,可以內部類定義在外部類不可訪問的屬性。這樣就在外部類中實現了比外部類private還要小的額訪問權限。
注意:
內部類是一個編譯時的概念,一旦編譯成功,就會成為完全不同的兩個類。
對于一個名為Outer的外部類和其內部定義的名為Inner的內部類。編譯完成后出現Outer.class 和 Outer$Inner.class 兩個類
當Outer是一個private類時,外部類對于其外部訪問是私有的,所以就無法建立外部類對象,進而也無法建立內部類對象。
局部內部類
在方法中第一的內部類稱為局部內部類。
與局部變量類似,在局部內部類前不加修飾符public和private,其范圍為定義它的代碼塊
注意:
在類外不可直接生產局部內部類(保證局部內部類對外是不可見的)。
要想使用局部內部類時需要生產對象,對象調用方法,在方法中才能調用局部內部類。
通過內部類和接口達到一個強制的弱耦合,用局部內部類來實現接口,并在方法中返回接口類型,使局部內部類不可見,屏蔽實現類的可見性。
靜態內部類
靜態內部類可以使用public,protected,private修飾
靜態內部類中可以定義靜態和非靜態的成員
注意:
一個靜態內部類不需要一個外部類的成員:只是靜態內部類和成員內部類的區別。靜態內部類的對象可以直接生成
這實際上靜態內部類成為了一個頂級類。
靜態內部類不可用private來進行定義。
當類與接口(或者是接口與接口)發生方法命名沖突的時候,此時必須使用內部類來實現。用接口不能完全地實現多繼承,用接口配合內部類才能實現真正的多繼承。
匿名內部類
匿名內部類就是沒有名字的內部類。
注意:
匿名內部類不能有構造函數
匿名內部類不能定義任何靜態成員、方法和類
匿名內部類不能是public、protected、private、static
只能創建匿名內部類的一個實例
一個匿名內部類用其隱含實現一個接口或實現一個類。
因匿名內部類為局部內部類,所以局部內部類的所有限制都對其生效。
posted @ 2011-12-13 15:26 順其自然EVO 閱讀(309) | 評論 (0) | 編輯 收藏
測試驅動開發的定義
測試驅動開發(Test-driven development)是現代計算機軟件開發方法的一種。利用測試來驅動軟件程序的設計和實現。測試驅動開始流行于20世紀90年代。測試驅動開發是極限編程中倡導的程序開發方法,方法主要是先寫測試程序,然后再編碼使其通過測試。測試驅動開發的目的是取得快速反饋并使用“illustrate the main line”方法來構建程序。
測試驅動開發的比喻。開發可以從兩個方面去看待:實現的功能和質量。測試驅動開發更像兩頂帽子思考法的開發方式,先戴上實現功能的帽子,在測試的輔助下,快速實現正確的功能;再戴上重構的帽子,在測試的保護下,通過去除冗余和重復的代碼,提高代碼重用性,實現對質量的改進。可見測試在測試驅動開發中確實屬于核心地位,貫穿了開發的始終。
最近在學習《重構》,里面強調,實施重構的一個前提是,必須建立一個可靠的測試環境。里面還提到了測試驅動開發,以及測試驅動開發的好處。正好最近在開發一個小的項目,所以便在這個項目中嘗試了一下測試驅動開發,感覺不錯,這里分享一下我的體會。
我開發使用的是C++,我使用的測試框架是Google的c++開源測試框架gtest。另外Google也有一個mock的開源框架gmock,可以和gtest一起使用。至于gtest的使用,可以參照我以前轉載的一個系列文章:玩轉Google單元測試框架gtest系列
首先談一下測試框架gtest。總體感覺gtest使用起來還算比較方便的,而且他們能夠自動運行所有的測試用例,這一點非常重要。在《玩轉Google單元測試框架gtest系列》這個系列的文章中,沒有看到測試框架對private方法測試的描述。后來我看了一下官方網站的說明,它是支持的。另外,這個測試框架的一個不好的地方就是,它主要是通過檢查函數返回值來判斷測試成功或失敗的,對于返回值為void的方法,要判斷執行成功與失敗,則非常的不方便,有的時候,根本無法判斷。不過從總體上來看,這個測試框架還是比較不錯的。
其次那,談一下測試驅動開發帶來的好處。
1、提高軟件質量。毋容置疑,有單元測試保障的軟件產品質量肯定要比沒有經過單元測試的軟件產品質量要好。
2、開發速度。測試驅動開發主張在編碼之前首先編寫測試代碼,這種做法會降低編碼的速度。但是在整個軟件開發過程中,編碼所占用的時間是很少的,我們大部分的時間在調試,定位bug,修改bug。測試驅動對開發速度的提升在于,它可以減少后者的時間,從而在整體上提升開發速度。
3、重構。構建一個可靠的測試環境,可以讓我們大膽的進行重構,而不用擔心會引入潛伏下來的bug。
4、增量開發。使用測試驅動開發,我們可以實現軟件產品的增量開發,而不用擔心增量開發會對原有的功能造成破壞。
5、促進優良的設計:低耦合,高內聚。測試驅動開發一個非常重要的好處就是它可以促進優良的設計。糟糕的設計,一般情況會非常難以進行測試。測試驅動有助于促進低耦合,高內聚的設計,因為這樣的設計才會易于測試。
6、真正實現面向接口編程。
7、避免過度設計。當你構建好測試用例后,也就提供了一個完成設計的目標:讓所有的測試用例測試通過。這樣可以避免過度設計。
雖然測試驅動開發有這么多的好處,但是要在研發人員的推行這個開發方式,面臨的挑戰還是非常大的,畢竟它帶來的是一種全新的開發思路和模式。不過我相信,只要開發人員樂于去嘗試這種開發方式,他一定會喜歡上它的。
posted @ 2011-12-12 14:34 順其自然EVO 閱讀(272) | 評論 (0) | 編輯 收藏
二、單元測試實踐的主要問題
單元測試有個特點:測試簡單獨立的代碼很容易,但要在實際工作中做好單元測試卻很困難。
根據我們的經驗,企業在實施單元測試時,通常會面對四大問題——
● 不愿做:程序員沒有單元測試習慣。
● 沒時間:編寫測試代碼需要耗費大量的時間,項目的周期可能不允許。
● 做不了:代碼具有較高的耦合性,使單元測試難以進行。
● 做不好:測試效果不能令人滿意。我們通常會以覆蓋率來衡量測試效果,但要實現高標準的測試覆蓋很困難。
三、解決思路和方法
如何解決上述問題呢?接下來,談談一些思路和方法,使用的工具是Visual Unit。Visual Unit,簡稱VU,是可視化的C/C++單元測試工具。
3.1 如何解決“不愿做”和“沒時間”
對于“不愿做”,我們采用的對策是可視化,這個可視化,是指程序行為可視,后面我會用案例來演示;對于“沒時間”,采用的對策是自動化,通過自動生成測試代碼、自動打樁等功能,讓測試的時間成本最小化。這兩者結合起來,就是ETDD開發模式。
那么,ETDD是什么呢?
首先來介紹一下TDD,TDD就是測試驅動開發,這個大家可能聽得比較多了。ETDD就是Easy TDD,即:易行版的TDD。ETDD具有以下一些特點:
● 可視化,在開發過程中,程序行為可視。
● 自動化,除了測試數據需要人工設定外,其他基本上都自動完成。
● 現實化,不一定要測試所有代碼,在開始階段,可以只測試功能邏輯復雜的20%代碼。
下面,我用一個案例,講解一下ETDD的過程:
假如我要編寫一個函數,它的功能是刪除字符串左邊的空格。
先寫好函數的框架,能通過編譯就行。在編寫代碼前,程序員必須要做的一件事情,是想清楚代碼的功能。如果我們想的時候,順手把它記錄下來,就可以讓代碼的功能更清晰、更明確。
我們現在來記錄代碼的功能。這里的記錄,不是文字形式的寵統說明,而是數據形式的精確定義,也就是用輸入和輸出的方式來記錄。
首先,記錄最基本的功能,也就是最基本、最常見的輸入和輸出。輸入一個左邊有空格的字符串,輸出是刪除左邊空格后的字符串,返回值跟參數的輸出是一樣的。
然后,記錄詳細的功能。例如,左邊沒有空格的,全是空格的,還有空字符串。 把每種輸入的正確輸出也記錄一下。完成了這個工作后,代碼的功能就完全定義下來了。 現在,我們開始編寫代碼。我的編碼思路是這樣的:分為兩步,第一步計算左邊的空格數量;第二步,將非空格的字符向左移動,覆蓋掉左邊的空格。 以下幾行代碼,計算左邊的空格,現在編譯一下。CTRL+F7。如果編譯通過,測試就會自動運行。 我們可以看到,輸入是什么,執行了哪些代碼,產生了什么輸出。這里,黑色的是當前輸入下所執行的代碼,未執行的話會顯示為紅色。這里全是黑色,表示當前輸入下執行了全部代碼。如果我們想看一下計算左邊空格的結果對不對,這是內部的數據,要指定位置后才會打印出來。按ESC鍵回到開發環境。 用這種語法可以輸出內部數據,適合于程序員開發過程中使用。復雜類型也可以用同樣的語法輸出。 另一種輸出內部數據的語法是,在左邊的代碼窗口,在要輸出的位置點擊一下,右鍵菜單選擇“輸出內部數據”,這樣填一下就行了。這種方式不會修改產品代碼,適合于測試員使用。 再次執行后,可以看到,左邊的空格的數量是4,這是對的,那我們可以繼續編寫。 (待續)
posted @ 2011-12-12 14:30 順其自然EVO 閱讀(161) | 評論 (0) | 編輯 收藏
軟件項目從起頭到竣事,始終都貫穿著頻繁的溝通。可是一個很普遍的現象就是溝通成本往往會遠遠超出了預期,從而大大降低了工作的效率。
熟悉溝通成本
溝通是必需的,可是溝通存在“巨大”成本。這個成本表現在:
1、溝通無法實現100%的信息傳遞,因為信息失蹤導致的成本。
2、溝通自己存在的時間和空間成本。
3、因為一次溝通不到位,導致發生后續多次溝通。
可是這些溝通是否通順,有很多角色配合抉擇,好比PRD,開發,測試。
那從測試人員的角色來說,如何才能降低溝通成本呢?
1、選擇正確的溝通路子
選擇正確的溝通路子對于確保完成溝通方針起到很是主要的浸染。在軟件項目開發中,存在各種各樣的溝通。可能因為溝通的對象分歧,也可能因為溝通的內容分歧,我們可能需要選擇分歧溝通途徑。最有用的是face to face的溝通,尤其是在需求評審階段。有些爭議復雜的用文字容易呈現歧義的問題,面對面以及電話溝通往往是最直接最有用最清楚的。
2、使表述的內容易于理解
溝通的堅苦往往在于無法把想要講述的內容以一種對方容易理解的方式呈現給對方。作為測試人員, bug的描述必然要清楚,主題要簡明簡要,場景規范要描述清楚,好比測試帳號,數據,以及重現的bug。因為,有些爭議小的bug開發可能經由過程看主題就已經可以定位了,不需要在看繁瑣的程序。那場景規范描述的是否清楚直接影響到測試人員和開發之間的溝通成本。
3、溝通技巧
先禮后“兵”,測試和開發的溝通在整個項目過程中都是很主要的一個環節。作為測試人員必然要在明晰自己的立場(保障項目質量和用戶需求)的同時,注重和開發同窗溝通的質量。先禮后“兵”很主要,有問題先要很好的溝通,需要的時候可以從他們的立場出發去追求打破,不要破損和開發之間的友好關系,可是在問題得不到解決,或者會直接影響到項目的進度及質量的時候,也要堅定的向上一級追求輔佐,讓更有講話權的人來作出溝通和確定。
posted @ 2011-12-12 14:17 順其自然EVO 閱讀(184) | 評論 (0) | 編輯 收藏
【本篇為《如何有效實現軟件的需求管理》第七篇,(第一篇,第二篇,第三篇,第四篇,第五篇,第六篇)】
版本控制:
在我們公司的實際需求管理中,需求的版本控制用的地方非常多,比如
第一,因為一個需求從獲取到最終能拿去開發,中間也需要經歷非常多次的改動。既然有改動,就肯定也會出現類似寫代碼一樣,這次寫錯了,想看看上次的這類情況,所以還是需要能看到不同的版本。
第二,有時候,一個需求改了N次,到最后想比較各個版本看看,來得出一個最終版本。
第三,還有種情況,改了很久,突然發現前面有一次不錯,所以想回滾到原來的設計。
第四,當經常有變更的時候,開發和測試就需要獲取最新的設計文檔,這時候版本控制總是能讓他們馬上獲取最新的版本。
第五,有些項目我們會使用軟件基線(Baseline),而基線也是版本控制的一部分。
在DevSpec中,版本控制我們用到的功能就是版本功能與基線功能,基本上能達到我們的預期。
可跟蹤性
可跟蹤性的強大來源于數據記錄與數據挖掘的強大,我們現在用的DevSpec中,對任何操作,任何數據變化,幾乎都會記錄下來,誰在什么時間做了什么事情都能一目了然,這樣的好處也是顯而易見的,簡單而言,一方面,這些數據記下來,以后萬一出現任何“糾紛”都能有理可依了;另一方面,當然也能知道誰真的在干事,獎勵起來也有了依據;還有一方面,完整的數據記錄給報表提供了最真實的依據,能讓你最正確的分析過去,處理現在和面對未來。
需求管理的五點要求基本上講完了,可以說這些要求能很好的實現的話,基本上你們的需求管理水平已經是不錯了,這也是產品能夠成功的前提條件了。
當然,好的產品最終還是需要好的設計的,管理只是能增加產品成功的可能性,但是沒有好的設計產品絕對是不能成功的。
不過今天咱們是在說管理,所以還是回到管理上來說吧,我們公司內部曾經做過評估,發現用了DevSuite系統以后,整個實際效率提高了80%,產品的質量水平提高了200%,員工的積極性也有明顯的上升。顯而易見,用了管理工具以后,效果還是很明顯的。
所以要有效地實現需求管理,關鍵是要把需求管理所要涉及到管理點管好,由于現代軟件的規模已經無法再用純手工/半手工的方式來管理需求了,所以采用一個好的工具無疑是一個好的解決方法。
(全文完)
posted @ 2011-12-12 14:07 順其自然EVO 閱讀(153) | 評論 (0) | 編輯 收藏
一、NIO的出現
NIO是JDK1.4里面才出現的東東,他給大家帶來的最大好處是異步socket。其它file,pipe暫時就不多談了。
在JDK1.4出現之前,如果你需要編寫一個Java服務器,為了實現異步操作,你必須為每個連接請求生成一個Java線程,當連接請求很多時,線程的調度,上下文切換,所付出的代價是非常昂貴,而且由于Java是跨平臺的,各個平臺對線程的支持并不相同,性能也不相同,因此傳統的Java服務器編程架構是低效的且代價貴,dl大俠寫了個util.concurrent包后,總算是減輕了線程調度給java程序員帶來的痛苦,但是相比之與C、C++寫出來的服務器,java服務器在性能要求很高的情況下,基本上沒有什么競爭力,甚至是入圍的權利的都沒有。
二、異步socket的實現
NIO出現后,好像讓java的程序員有了楊眉吐氣的機會,怎么個吐氣法,當時大家是個什么感受,俺是不知道,因為當時俺不搞java,對java的認識有限。
NIO是一個基于事件的IO架構,最基本的思想就是:有事件我通知你,你再去做你的事情,沒事件時你大可以節約大把時間去做其它任何事情。而且NIO的主線程only one,不像傳統的模型,需要N個線程去,也減輕了JVM的工作量,使得JVM處理任務時顯得更加高效。
剛開始接觸NIO時,被N層的Channel架構、網上鋪天蓋地的好評給鎮住了,想想也應當是個很成熟的產品了,網上資料這么多,抄一抄Jetty、Tomcat以及其它一些牛B的源代碼,基本上就能搞定了,此時沒有想到大家受同步的影響這么深,也沒有想到連最基本的異步概念都沒有搞清楚就去寫代碼,搞出一堆的問題來(這是后話,后面再說)。
現在研究了NIO以后,發現NIO實際上在Java中做的工作是很簡單,就是將事件進行收集和分發,我們結合一個經典的調用例子來說明這個問題,我就不從NIO的基本使用說起了,大家可以查其它的資料,網上一大把。
當Channel注冊至Selector以后,我們的最經典的調用方法,是這樣子的。
這只是個小例子啊,什么異常我就懶得抓了。
nio中取得事件通知,就是在selector的select事件中完成的,在selector事件時有一個線程,這個線程具體的處理簡單點說就是:向操作系統詢問,selector中注冊的Channel&&SelectionKey的偶對各種事件是否有發生,如果有則添加到selector的selectedKeys屬性Set中去,并返回本次有多少個感興趣的事情發生。程序員發現這個值>0,表示有事件發生,馬上迭代selectedKeys中的SelectionKey,根據Key中的表示的事件,來做相應的處理。
實際上,這段說明表明了異步socket的核心,即異步socket不過是將多個socket的調度(或者還有他們的線程調度)全部交給操作系統自己去完成,異步的核心Selector,不過是將這些調度收集、分發而已。因為操作系統的socket、線程調度再咋D也比你JVM中要強,效率也高。
而且就算jvm做的和操作系統一樣好,性能一樣高(當然這是不現實的),使用異步socket你至少也節約了一半的系統消耗,想想假定操作系統本身也是使用線程來維護N個socket連接,在傳統的java編程中,你還必須為這些socket還多起一個java線程,那至少是2N個線程,現在只需要N+1。在高并發的情況下,你自己去想吧。
懂了這個道理,異步socket也就好寫了,也不會搞得思路混亂了。
三、異步Socket中應當注意的事情
1、讀
異步socket最基本的理念就是事件通知,前面也說了,有事件通知你了,你才該做你應當做的事情。在異步socket中當注冊了一個OP_READ事件后,你就等著Selector通知你吧,如果沒有通知你,你在家睡大覺都行。
在這里,我們有人出現的錯誤就是受同步的影響,自己去主動讀,而且還搞出了多線程,如果仔細考慮一下,就不會出現這個問題了。同步socket中,調用read方法讀取IO中的數據時,通常情況下如果沒有數據read方法會阻塞,且是同步的,所以當多個線程同時訪問時,read方法是線程安全的。
而在異步下就不同,異步是不會阻塞的,有什么就返回什么,你主動去讀,只要有數據,你就可以拿走,在多線程的情況下,也許你是想讓第一個線程讀取,but此時來數據時正好是線程2讀到了,那線程2就高高興興的拿去,而線程1還在苦苦等待,這樣導致數據混亂不說,如果后面再也不來數據了,線程1就是死循環啦。
2、寫
在異步socket中,寫是唯一一個主動點的操作,但是也不能直接去寫Channel,而是應當先把自身注冊為OP_WRITABLE,這時Selector就會發現你的存在,并把給發一個write事件,你這時后就可以寫了,不過這時候有個小小的技巧,就是你執行寫操作之前,請取消掉你的寫注冊,否則你的cpu肯定是100%。
3、等待
在傳統的服務器編程中,由于對于每個請求都是產生的一個線程,因此你在你每個請求線程中wait也好,sleep也好,不會影響別人。但是異步不同,他的主線程只有一個,基本上每個處理都是線性的,也就是說處理完第一個,然后才能處理第二個,因此nio是一個極好的處理短連接的架構。
我們現在出現的問題是,有人受同步的影響,沒有搞清異步是如何處理,竟然在方法處理中用上sleep,而且一等還是3秒,這意味著什么,3秒才能處理一個請求,My god,我要一個3秒才能處理一個請求的服務器干嘛啊,還是60年代啊
如果出現這樣的需要等待的情況,應當另起一個線程(推薦使用線程池)去完成這個“長”時間的任務,或者將其它交給一個消息隊列,通過發消息的方式將給別人去完成也行,客戶端能等,你服務器怎么也能等呢?寫出這樣的代碼,基本上一個服務器也就廢了。
posted @ 2011-12-12 13:52 順其自然EVO 閱讀(231) | 評論 (0) | 編輯 收藏