軟件項目管理
????? 軟件項目管理是為了使軟件項目能夠按照預定的成本、進度、質量順利完成,而對人員(People)、產品(Product)、過程(Process)和項目(Project)進行分析和管理的活動。
????? 軟件項目管理的根本目的是為了讓軟件項目尤其是大型項目的整個軟件生命周期(從分析、設計、編碼到測試、維護全過程)都能在管理者的控制之下,以預定成本按期,按質的完成軟件交付用戶使用。而研究軟件項目管理為了從已有的成功或失敗的案例中總結出能夠指導今后開發的通用原則,方法,同時避免前人的失誤。
????? 軟件項目管理的提出是在20世紀70年代中期的美國,當時美國國防部專門研究了軟件開發不能按時提交,預算超支和質量達不到用戶要求的原因,結果發現70%的項目是因為管理不善引起的,而非技術原因。于是軟件開發者開始逐漸重視起軟件開發中的各項管理。到了20世紀90年代中期,軟件研發項目管理不善的問題仍然存在。據美國軟件工程實施現狀的調查,軟件研發的情況仍然很難預測,大約只有10%的項目能夠在預定的費用和進度下交付。
????? 1995年,據統計,美國共取消了810億美元的商業軟件項目,其中31%的項目未做完就被取消,53%的軟件項目進度通常要延長50%的時間,只有9%的軟件項目能夠及時交付并且費用也控制在預算之內。
????? 軟件項目管理和其他的項目管理相比有相當的特殊性。首先,軟件是純知識產品,其開發進度和質量很難估計和度量,生產效率也難以預測和保證。其次,軟件系統的復雜性也導致了開發過程中各種風險的難以預見和控制。Windows這樣的操作系統有1500萬行以上的代碼,同時有數千個程序員在進行開發,項目經理都有上百個。這樣龐大的系統如果沒有很好的管理,其軟件質量是難以想象的。
????? 軟件項目管理的內容主要包括如下幾個方面:人員的組織與管理,軟件度量,軟件項目計劃,風險管理,軟件質量保證,軟件過程能力評估,軟件配置管理等。
?????
這幾個方面都是貫穿、交織于整個軟件開發過程中的,其中人員的組織與管理把注意力集中在項目組人員的構成、優化;軟件度量把關注用量化的方法評測軟件開發
中的費用、生產率、進度和產品質量等要素是否符合期望值,包括過程度量和產品度量兩個方面;軟件項目計劃主要包括工作量、成本、開發時間的估計,并根據估
計值制定和調整項目組的工作;風險管理預測未來可能出現的各種危害到軟件產品質量的潛在因素并由此采取措施進行預防;質量保證是保證產品和服務充分滿足消
費者要求的質量而進行的有計劃,有組織的活動;軟件過程能力評估是對軟件開發能力的高低進行衡量;軟件配置管理針對開發過程中人員、工具的配置、使用提出管理策略。因為大家對人力資源管理和軟件過程能力比較有興趣,下面就詳細的對這兩方面展開討論。
一.軟件項目的計劃
????? 軟件項目計劃是一個軟件項目進入系統實施的啟動階段,主要進行的工作包括:確定詳細的項目實施范圍、定義遞交的工作成果、評估實施過程中主要的風險、制定項目實施的時間計劃、成本和預算計劃、人力資源計劃等。
????? 軟件項目管理過程從項目計劃活動開始,而第一項計劃活動就是估算:需要多長時間、需要多少工作量、以及需要多少人員。此外,我們還必須估算所需要的資源(硬件及軟件)和可能涉及到的風險。
????? 為了估算軟件項目的工作量和完成期限,首先需要預測軟件規模。度量軟件規模的常用方法有直接的方法——LOC(代碼行),間接的方法——FP(功能點)。這兩種方法各有優缺點,應該根據軟件項目的特點選擇適用的軟件規模度量方法。
????? 根據項目的規模可以估算出完成項目所需的工作量,我們可以使用一種或多種技術進行估算,這些技術主要分為兩大類:分解和經驗建模。分解技術需要劃分出主要的軟件功能,接著估算實現每一個功能所需的程序規模或人月數。經驗技術的使用是根據經驗導出的公式來預測工作量和時間。可以使用自動工具來實現某一特定的經驗模型。
????? 精確的項目估算一般至少會用到上述技術中的兩種。通過比較和協調使用不同技術導出的估算值,我們可能得到更精確的估算。軟件項目估算永遠不會是一門精確的科學,但將良好的歷史數據與系統化的技術結合起來能夠提高估算的精確度。
????? 當對軟件項目給予較高期望時,一般都會進行風險分析。在標識、分析和管理風險上花費的時間和人力可以從多個方面得到回報:更加平穩的項目進展過程;更高的跟蹤和控制項目的能力;由于在問題發生之前已經做了周密計劃而產生的信心。
????? 對于一個項目管理者,他的目標是定義所有的項目任務,識別出關鍵任務,跟蹤關鍵任務的進展情況,以保證能夠及時發現拖延進度的情況。為此,項目管理者必須制定一個足夠詳細的進度表,以便監督項目進度并控制整個項目。
?????
常用的制定進度計劃的工具主要有Gantt圖和工程網絡兩種。Gantt圖具有悠久歷史、直觀簡明、容易學習、容易繪制等優點,但是,它不能明顯地表示各
項任務彼此間的依賴關系,也不能明顯地表示關鍵路徑和關鍵任務,進度計劃中的關鍵部分不明確。因此,在管理大型軟件項目時,僅用Gantt圖是不夠的,不
僅難于做出既節省資源又保證進度的計劃,而且還容易發生差錯。
?????
工程網絡不僅能描繪任務分解情況及每項作業的開始時間和結束時間,而且還能清楚地表示各個作業彼此間的依賴關系。從工程網絡圖中容易識別出關鍵路徑和關鍵
任務。因此,工程網絡圖是制定進度計劃的強有力的工具。通常,聯合使用Gantt圖和工程網絡這兩種工具來制定和管理進度計劃,使它們互相補充、取長補
短。
????? 進度安排是軟件項目計劃的首要任務,而項目計劃則是軟件項目管理的首要組成部分。與估算方法和風險分析相結合,進度安排將為項目管理者建立起一張計劃圖。
二.軟件項目的控制
????? 對于軟件開發項目而言,控制是十分重要的管理活動。下面介紹軟件工程控制活動中的質量保證和配置管理。其實上面所提到的風險分析也可以算是軟件工程控制活動的一類。而進度跟蹤則起到連接軟件項目計劃和控制的作用。
????? 軟件質量保證(SQA,Software Quality Insurance)是在軟件過程中的每一步都進行的“保護性活動”。SQA主要有基于非執行的測試(也稱為評審)、基于執行的測試(即通常所說的測試)和程序正確性證明。
?????
軟件評審是最為重要的SQA活動之一。它的作用是,在發現及改正錯誤的成本相對較小時就及時發現并排除錯誤。審查和走查是進行正式技術評審的兩類具體方
法。審查過程不僅步數比走審多,而且每個步驟都是正規的。由于在開發大型軟件過程中所犯的錯誤絕大數是規格說明錯誤或設計錯誤,而正式的技術評審發現這兩
類錯誤的有效性高達75%,因此是非常有效的軟件質量保證方法。
????? 軟件配置管理(SCM,Software configuration management)是應用于整個軟件過程中的保護性活動,它是在軟件整個生命周期內管理變化的一組活動。
????? 軟件配置由一組相互關聯的對象組成,這些對象也稱為軟件配置項,它們是作為某些軟件工程活動的結果而產生的。除了文檔、程序和數據這些軟件配置項之外,用于開發軟件的開發環境也可置于配置控制之下。
????? 一旦一個配置對象已被開發出來并且通過了評審,它就變成了基線。對基線對象的修改導致建立該對象的版本。版本控制是用于管理這些對象而使用的一組規程和工具。
????? 變更控制是一種規程活動,它能夠在對配置對象進行修改時保證質量和一致性。配置審計是一項軟件質量保證活動,它有助于確保在進行修改時仍然保持質量。狀態報告向需要知道關于變化的信息的人,提供有關每項變化的信息。
三、軟件項目管理的組織模式
?????
軟件項目可以是一個單獨的開發項目,也可以與產品項目組成一個完整的軟件產品項目。如果是訂單開發,則成立軟件項目組即可;如果是產品開發,需成立軟件項
目組和產品項目(負責市場調研和銷售),組成軟件產品項目組。公司實行項目管理時,首先要成立項目管理委員會,項目管理委員會下設項目管理小組、項目評審
小組和軟件產品項目組。
????? 3.1、項目管理委員會項目管理委員會是公司項目管理的最高決策機構,一般由公司總經理、副總經理組成。主要職責如下:
(1)依照項目管理相關制度管理項目;
(2)監督項目管理相關制度的執行;
(3)對項目立項、項目撤消進行決策;
(4)任命項目管理小組組長、項目評審委員會主任、項目組組長.
????? 3.2、項目管理小組項目管理小組對項目管理委員會負責,一般由公司管理人員組成。主要職責如下:
(1)草擬項目管理的各項制度;
(2)組織項目階段評審;
(3)保存項目過程中的相關文件和數據;
(4)為優化項目管理提出建議。
????? 3.3、項目評審小組項目評審小組對項目管理委員會負責,可下設開發評審小組和產品評審小組,一般由公司技術專家和市場專家組成。主要職責如下:
(1)對項目可行性報告進行評審;
(2)對市場計劃和階段報告進行評審;
(3)對開發計劃和階段報告進行評審;
(4)項目結束時,對項目總結報告進行評審。
?????
3.4、軟件產品項目組軟件產品項目組對項目管理委員會負責,可下設軟件項目組和產品項目組。軟件項目組和產品項目組分別設開發經理和產品經理。成員一般
由公司技術人員和市場人員構成。主要職責是:根據項目管理委員會的安排具體負責項目的軟件開發和市場調研及銷售工作。
四、軟件項目管理的內容
????? 從軟件工程的角度講,軟件開發主要分為六個階段:需求分析階段、概要設計階段、詳細設計階段、編碼階段、測試階段、安裝及維護階段。不論是作坊式開發,還是團隊協作開發,這六個階段都是不可缺少的。根據公司實際情況,公司在進行軟件項目管理時,重點將軟件配置管理、項目跟蹤和控制管理、軟件風險管理及項目策劃活動管理四方面內容導入軟件開發的整個階段。在20世紀80年代初,著名軟件工程專家B.W.Boehm總結出了軟件開發時需遵循的七條基本原則,同樣,在進行軟件項目管理時,也應該遵循這七條原則。它們是:
(1)用分階段的生命周期計劃嚴格管理;
(2)堅持進行階段評審;
(3)實行嚴格的產品控制;
(4)采用現代程序設計技術;
(5)結果應能夠清楚地審查;
(6)開發小組地人員應該少而精;
(7)承認不斷改進軟件工程實踐的必要性。
五、編寫《軟件項目計劃書》
????? 項目組成立的第一件事是編寫《軟件項目計劃書》,在計劃書中描述開發日程安排、資源需求、項目管理等各項情況的大體內容。計劃書主要向公司各相關人員發放,使他們大體了解該軟件項目的情況。對于計劃書的每個內容,都應有相應具體實施手冊,這些手冊是供項目組相關成員使用的。
六、軟件配置管理
?????
是否進行配置管理與軟件的規模有關,軟件的規模越大,配置管理就顯得越重要。軟件配置管理簡稱SCM(Software Configuration
Management的縮寫),是在團隊開發中,標識、控制和管理軟件變更的一種管理。配置管理的使用取決于項目規模和復雜性以及風險水平。
????? 6.1、目前軟件開發中面臨的問題:在有限的時間、資金內,要滿足不斷增長的軟件產品質量要求;開發的環境日益復雜,代碼共享日益困難,需跨越的平臺增多;程序的規模越來越大;軟件的重用性需要提高;軟件的維護越來越困難。
????? 6.2、軟件配置管理應提供的功能:
?????
在ISO9000.3中,對配置管理系統的功能作了如下描述:唯一地標識每個軟件項的版本;標識共同構成一完整產品的特定版本的每一軟件項的版本;控制由
兩個或多個獨立工作的人員同時對一給定軟件項的更新;控制由兩個或多個獨立工作的人員同時對一給定軟件項的更新;按要求在一個或多個位置對復雜產品的更新
進行協調;標識并跟蹤所有的措施和更改;這些措施和更改是在從開始直到放行期間,由于更改請求或問題引起的。
????? 6.3、版本管理軟件配置管理分為版本管理、問題跟蹤和建立管理三個部分,其中版本管理是基礎。版本管理應完成以下主要任務:
?
????? 建立項目;
????? 重構任何修訂版的某一項或某一文件;
????? 利用加鎖技術防止覆蓋; ?當增加一個修訂版時要求輸入變更描述;
????? 提供比較任意兩個修訂版的使用工具;
????? 采用增量存儲方式;
????? 提供對修訂版歷史和鎖定狀態的報告功能;
????? 提供歸并功能;
????? 允許在任何時候重構任何版本;
????? 權限的設置;
????? 晉升模型的建立;
????? 提供各種報告。
七. 人員組織與管理
????? 軟件開發中的開發人員是最大的資源。對人員的配置、調度安排貫穿整個軟件過程,人員的組織管理是否得當,是影響對軟件項目質量的決定性因素。
?????
首先在軟件開發的一開始,要合理的配置人員,根據項目的工作量、所需要的專業技能,再參考各個人員的能力、性格、經驗,組織一個高效、和諧的開發小組。一
般來說,一個開發小組人數在5到10人之間最為合適,如果項目規模很大,可以采取層級式結構,配置若干個這樣的開發小組。
?????
在選擇人員的問題上,要結合實際情況來決定是否選入一個開發組員。并不是一群高水平的程序員在一起就一定可以組成一個成功的小組。作為考察標準,技術水
平、與本項目相關的技能和開發經驗、以及團隊工作能力都是很重要的因素。一個一天能寫一萬行代碼但卻不能與同事溝通融洽的程序員,未必適合一個對組員之間
通訊要求很高的項目。還應該考慮分工的需要,合理配置各個專項的人員比例。例如一個網站開發項目,小組中有頁面美工、后臺服務程序、數據庫幾個部分,應該合理的組織各項工作的人員配比。對于一個中型農技110網站,對數據采集量要求較高,一個人員配比方案可以是2個美工、2個后臺服務程序編寫、3個數據采集整理人員。
???? 可以用如下公式來對候選人員能力進行評分,達到一定分數的則可以考慮進入開發組,但這個公式不包含對人員數量配比的考慮。
???? Score=∑WiCi(i=1to8)
????? Ci是對項目組人員各項能力的評估。其值含義如下
????? 在決定一個開發組的開發人員數量時,除了考慮候選人素質以外,還要綜合考慮項目規模、工期、預算、開發環境等因素的影響,下面是一個基于規模、工期和開發環境的人員數量計算公式:
????? L=Ck*K1/3*td4/3
????? L:開發規模,以代碼行LOC為度量td:開發時間K:人員數
????? Ck:技術常數表示開發環境的優劣
????? 取值2000:表示開發環境差,沒有系統的開發方法,缺乏文檔規范化設計;
????? 取值8000:表示開發環境較好;
????? 取值11000:表示開發環境優。
?????
在組建開發組時,還應充分估計到開發過程中的人員風險。由于工作環境、待遇、工作強度、公司的整體工作安排和其他無法預知的因素,一個項目尤其是開發周期
較長的項目幾乎無可避免的要面臨人員的流入流出。如果不在項目初期對可能出現的人員風險進行充分的估計,作必要的準備,一旦風險轉化為現實,將有可能給整
個項目開發造成巨大的損失。以較低的代價進行及早的預防是降低這種人員風險的基本策略。具體來說可以從以下幾個方面對人員風險進行控制:
????? a.保證開發組中全職人員的比例,且項目核心部分的工作應該盡量由全職人員來擔任, 以減少兼職人員對項目組人員不穩定性的影響。
????? b.建立良好的文檔管理機制,包擴項目組進度文檔、個人進度文檔、版本控制文檔、整體技術文檔、個人技術文檔、源代碼管理等。一旦出現人員的變動,比如某個組員因病退出,替補的組員能夠根據完整的文檔盡早接手工作。
????? c.加強項目組內技術交流,比如定期開技術交流會,或根據組內分工建立項目組內部的開發小組,是開發小組內的成員能夠相互熟悉對方的工作和進度,能夠在必要的時候替對方工作。
????? d.對于項目經理,可以從一開始就指派一個副經理在項目中協同項目經理管理項目開發工作,如果項目經理退出開發組,副經理可以很快接手。但是只建議在項目經理這樣的高度重要的崗位采用這種冗余復制的策略來預防人員風險,否則將大大增加項目成本。
????? e.為項目開發提供盡可能好的開發環境,包括工作環境、待遇、工作進度安排等等,同 時一個優秀的項目經理應該能夠在項目組內營造一種良好的人際關系和工作氛圍。良好的開發環境對于穩定項目組人員以及提高生產效率都有不可忽視的作用。
八.軟件過程能力評估
????? 軟件過程能力描述了一個開發組織開發軟件開發高質量軟件產品的能力。現行的國際標準主要有兩個:ISO9000.3和CMM。
????? ISO9000.3是ISO9000質量體系認證中關于計算機軟件質
量管理和質量保證標準部分。它從管理職責、質量體系、合同評審、設計控制、文件和資料控制、采購、顧客提供產品的控制、產品標識和可追溯性、過程控制、檢
驗和試驗、檢驗/測量和試驗設備的控制、檢驗和試驗狀態、不合格品的控制、糾正和預防措施、搬運/貯存/包裝/防護和交付、質量記錄的控制、內部質量審
核、培訓、服務、統計系統等二十個方面對軟件質量進行了要求。
????? CMM(能力成熟度模型)是美國卡納基梅隆大學軟件工程研究所(CMU/SEI)于1987年提出的評估和指導軟件研發項目管理的一系列方法,用5個不斷進化的層次來描述軟件過程能力。現在CMM是2.0版本。
?????
ISO9000和CMM的共同點是二者都強調了軟件產品的質量。所不同的是,ISO9000強調的是衡量的準則,但沒有告訴軟件開發人員如何達到好的目
標,如何避免差錯。CMM則提供了一整套完善的軟件研發項目管理的方法。它可告訴軟件開發組織,如果要在原有的水平上提高一個等級,應該關注哪些問題,而
這正是改進軟件過程的工作。
????? CMM描述了五個級別的軟件過程成熟度(初始級,可重復級,已定義級,已定量管理級,優化級),成熟度反映了軟件過程能力的大小。
?????
初始級特點是軟件機構缺乏對軟件過程的有效管理,軟件過程是無序的,有時甚至是混亂的,對過程幾乎沒有定義,其軟件項目的成功來源于偶爾的個人英雄主義而
非群體行為,因此它不是可重復的;可重復級的特點是軟件機構的項目計劃和跟蹤穩定,項目過程可控,項目的成功是可重復的;已定義級的特點在于軟件過程已被
提升成標準化過程,從而更加具有穩定性、可重復性和可控性;已定量管理級的軟件機構中軟件過程和軟件產品都有定量的目標,并被定量地管理,因而其軟件過程
能力是可預測的,其生產的軟件產品是高質量的;優化級的特點是過程的量化反饋和先進的新思想、新技術促進過程不斷改進,技術和過程的改進改進被作為常規的
業務活動加以計劃和管理。
?????
CMM是科學評價一個軟件企業開發能力的標準,但要達到較高的級別也非常困難,根據1995年美國所做的軟件產業成熟度的調查,在美國的軟件產業中,
CMM成熟度等級為初始級的竟占70%,為可重復級的占15%,為定義級的所占比例小于10%,為管理級的所占比例小于5%,為優化級的所占比例小于l
%。而國內企業的水平就更加堪優,到目前為止,只有東軟一家達到優化級,少數幾家能夠達到可定義級。盡快改變這種局面,科學化、規范化、高效的進行軟件開
發活動,從整體提高我國軟件行業的水平,是國內軟件企業的當務之急,也是專業人員應該為自己制定的目標。如果有一天也能指揮一個數千人的龐大開發隊伍,操
作Windows這樣巨型規模的軟件項目,并生產出高質量的產品,才有理由宣稱自己的軟件項目管理能力達到了一個“自主自足”的水平。
九. 為什么要有項目管理?
????? 沒有項目管理,項目也有可能成功。但沒有管理的項目,很難保證項目的利潤空間,對公司來說,虧損的風險就大。所以我們要有項目管理,以保證公司在總體上是盈利的,注意不是每一個項目都要盈利。
?????
另外,有了項目管理,就有了管理改進的基礎,無論剛開始的項目管理多么糟糕,只要有管理,就有了改進的可能性,至于能不能得到改進,以及改進的快慢,則取
決于兩個因素:一個是人,特別是各級管理者;另一個是利益。關鍵是"利益",準確的說是"利益的分配",在權責利明確的前提下,人才能充分的發揮作用。還
需要指出的是"利益"是多元的,這里的多元不僅指利益的具體形式,而且指利益的受眾是多元的,包括客戶方相關人員個人的利益。
十. 為什么要有專職的項目經理?
????? 專業化是一個趨勢,因為在專業化的條件下,可以有效降低成本,提高利潤率。項目經理的工作內容歸根到底只有一項:識別并管理風險。這項工作的目的是控制項目成本。
????? 由于項目的風險是多方面的,而且風險的表現形式也是多種多樣的。從風險范圍上來說,既有公司內部風險,也有和客戶交流、合作的風險;從風險的類型上來說,既有管理風險,也有技術風險;從風險產生的階段來說,包括了從業務分析到上線后維護的項目周期各個階段。
????? 我認為一個項目經理是否優秀,主要是看他/她能在多大程度上提前識別并消除風險,而不是彌補和解決了多少問題(風險未被及時識別或妥善處理,就會轉換成問題)。當然能彌補和解決問題的項目經理也是相當合格的,但還不夠優秀。
十一. 項目組的范圍界限在哪里?
????? 項目組的范圍界限可以有三種劃分:
????? 1、包括客戶方所有參與該項目的立項、調研、審批、測試和使用人員,包括開發商市場開發、管理審批、商務談判、后勤保障和具體負責該項目開發的人員;
????? 2、包括客戶方項目經理、業務需求提出人和測試人,包括開發商具體負責該項目開發的人員;
????? 3、僅包括開發商具體負責該項目開發的人員。
????? 大部分人在思想上可以接受范圍1,而在實務中接受的是范圍3。而我個人認為項目經理,特別是開發商方面的項目經理應該采用的是范圍2。
?????
對項目組范圍理解不同,將影響項目經理對工作的處理方式,范圍1實際上是很虛的,在項目管理實務操作中沒有太大的意義;而范圍3實質是把客戶方和該項目有
密切關系的人與開發商具體負責該項目開發的人對立起來,也就是所謂的甲方、乙方。在這種對立的前提下處理項目的分歧和矛盾,效果肯定要打折扣。
?????
而按范圍2來理解,在項目管理實務中項目經理就必須要讓客戶方和該項目有密切關系的人也接受這一觀點,從而拆除雙方之間的"障礙",達到相互信任、相互尊
重、共同協商解決問題的良性氛圍,以達到降低項目外部風險的目的。當然,這樣就增大了項目經理工作的難度,但對項目的成功則是很重要的。
十二. 怎樣才能算是一個成功的項目?
?????
對"成功項目"的標準解釋為:項目范圍、項目成本、項目開發時間、客戶滿意度四點達到要求。我認為其實只有一點--利益。項目范圍、客戶滿意度主要代表客
戶的利益,項目成本主要代表開發商的利益,項目開發時間同時影響雙方的利益。但每一個人關心的"利益"是不同的。
十三. 軟件項目管理的成功原則
????? 1平衡原則
在我們討論軟件項目為什么會失敗時可以列出了很多的原因,答案有很多,如管理問題、技術問題、人員問題等等,但是有一個根本的思想問題是最容易忽視的,
也是軟件系統的用戶、軟件開發商、銷售代理商最不想正視的,那就是:需求、資源、工期、質量四個要素之間的平衡關系問題。
需求定義
了"做什么",定義了系統的范圍與規模,資源決定了項目的投入(人、財、物),工期定義了項目的交付日期,質量定義了做出的系統好到什么程度,這四個要素
之間是有制約平衡關系的。如果需求范圍很大,要在較少的資源投入下,很短的工期內,很高的質量要求來完成某個項目,那是不現實的,要么需要增加投資,要么
工程延期;如果需求界定清楚了,資源固定了,對系統的質量要求很高,則可能需求延長工期。
對于上述四個要素之間的平衡關系最容易犯的一個錯誤,就是鼓吹"多快好省"四個字,"多快好省",多么理想的境界啊?需求越多越好,工期越短越好,質量越高越好,投入越少越好,這是用戶最常用的口號。
多:需求越多越好嗎?
軟件系統實施的基本原則是"全局規劃,分步實施,步步見效",需求可以多,但是需求一定要分優先級,要分清企業內的主要矛盾與次要矛盾,根據
PARETO的80-20原則,企業中的80%的問題可以用20%的投資來解決,如果你要大而全,對不起,你那20%的次要問題是需要你花費80%的投資
的!而這一點恰恰是很多軟件用戶所不能忍受的。
快:真能快起來嗎?
"快"是用戶、軟件開發商都希望的。傳統企業里
強調資金的周轉情況,軟件企業里強調的是人員的周轉情況,開發人員應盡快做完一個項目再做另外一個項目,通過快速的啟動項目、結束項目來承擔更多的項目,
來獲利。但是"快"不是主觀的拍腦袋定工期就可以完成的,工期的定義一定要基于資源的狀況、需求的多少與質量的需求來進行推算的。軟件畢竟需要一行代碼一
行代碼的寫出來,他的工作量是客觀的,并非?quot;人有多大膽,地有多大產"式的精神鼓動就可以短期完成的。
省:省到什么程度?
"一分錢一分貨",這是中國的俗話,他是符合價值規律的。甲方希望少投入,乙方希望降低自己的生產成本,省到乙方僅能保本的時候,再省,乙方就虧損了。
正視這四個要素之間的平衡關系是軟件用戶、開發商、代理商成熟理智的表現,否則系統的成功就失去了一塊最堅實的理念基礎。
企業實施IT系統的首要目標是要成功,而不是失敗,企業可以容忍小的成功,但不一定容忍小的失敗,所以需要真正理解上述四個要素的平衡關系,確保項目的成功。
????? 2高效原則
在需求、資源、工期、質量四個要素中,很多的項目決策者是將進度放在首位的,現在市場的競爭越來越激烈,"產品早上市一天,就早掙一天錢,掙的就比花的
多,所以一定要多掙",基于這樣一個理念,軟件開發越來越追求開發效率,大家從技術、工具、管理上尋求更多更好的解決之道。
基于高效的原則,對項目的管理需要從幾個方面來考慮:
要選擇精英成員
目標要明確,范圍要清楚
溝通要及時、充分
要在激勵成員上下工夫
????? 3分解原則
"化繁為簡,各個擊破"是自古以來解決復雜問題的不二法門,對于軟件項目來講,可以將將大的項目劃分成幾個小項目來做,將周期長的項目化分成幾個明確的階段。
項目越大對項目組的管理人員、開發人員的要求越高,參與的人員越多,需要協調溝通的渠道越多,周期越長,開發人員也容易疲勞,將大項目拆分成幾個小項
目,可以降低對項目管理人員的要求,減少項目的管理風險,而且能夠充分地將項目管理的權力下放,充分調動人員的積極性,目標會比較具體明確,易于取得階段
性的成果,使開發人員有成就感。
作者主管過的一個產品開發項目代號為SB,該項目前期投入了5人做需求,時間達3個多月,進入開發
階段后,投入了15人,時間達10個月之久,陸續進行了3次封閉開發,在此過程中經歷了需求的裁剪、開發人員的變更、技術路線的調整,項目組成員的壓力極
大,大家疲憊不堪,產品上市時間拖期達4個月。項目完工后總結下來的很致命的一個教訓就是應該將該項目拆成3個小的項目來做,進行階段性版本化發布,以緩
解市場上的壓力,減少項目組成員的挫折感,提高大家的士氣。
????? 4實時控制原則
在一家大型的軟件公司中,
有一位很有個性的項目經理,該項目經理很少談起什么管理理論,也未見其有什么明顯的管理措施,但是他連續做成多個規模很大的軟件項目,而且應用效果很好。
作者一直很奇怪他為什么能做的如此成功,經過仔細觀察,終于發現他的管理可以用"緊盯"2字來概括,即每天他都要仔細檢查項目組每個成員的工作,從軟件演
示到內部的處理邏輯、數據結構等,一絲不茍,如果有問題,改不完是不能去休息的。正是在他這種簡單的措施下,支撐他完成了很多大的項目,當然他也是相當的
辛苦,通常都是在凌晨才去休息。我們并非要推崇這種做法,這種措施也有他的問題,但是,這種實踐卻說明了一個很樸實的道理:如果你沒有更好的辦法,就要辛
苦一點,實時控制項目的進展,要將項目的進展情況完全的實時的置于你的控制之下。
上述的方法中對項目經理的個人能力、犧牲精神要求
是很高,我們需要有一種進行實時控制項目進度的機制,依靠一套規范的過程來保證實時監控項目的進度。如在微軟的管理策略中強?quot;每日構建",這確
實是是一種不錯的方法,即每天要進行一次系統的編譯鏈接,通過編譯鏈接來檢查進度、檢查接口、發現進展中的問題、大家互相鼓勵互相監督。
實時控制確保項目經理能夠及時發現問題、解決問題,保證項目具有很高的可見度,保證項目的正常進展。
????? 5分類管理原則
對于不同的軟件項目其項目目標差別很大,項目規模也是不同的,應用領域是不同的,采用的技術路線差別也很大,因而,針對每個項目的不同特點,其管理的方
法、管理的側重點應該是不同的。就像古人講的,"因材施教","對癥下藥"。對于小項目你肯定不能象管理大項目那樣去做,對于產品開發類的項目,你也不可
能象管理系統集成類的項目那樣去做,項目經理需要根據項目的特點,制訂不同的項目管理的方針政策。如,下表是作者為一家應用軟件公司制訂的項目管理的方
針:
在該案例中,將項目分成了訂單類項目與非訂單類項目,非訂單類項目是指由公司根據市場的需求開發一個標準產品的項目,而訂單類
是指針對某個具體的客戶定制軟件的項目,訂單類的項目根據需要協調的資源的范圍有劃分成了公司級、部門級、個人級三類,非訂單類根據估算的工作量的大小也
分成了A、B、C三類,估算的工作量超過720人天的為A類,超過360人天的為B類,360人天以下的為C類。不同類的項目管理的側重點是不同的,從立
項手續的完備性、計劃的嚴格層度、周報的完備層度、規范的嚴格層度、跟蹤的實時性、是否進行階段總結、是否核算項目成本、是否嚴格進行階段評審等多個方面
來考慮,以確保管理的可行性。
????? 6簡單有效原則
項目經理在進行項目管理的過程中,往往會得到開發人員這
樣的抱怨"太麻煩了,浪費時間,沒有用處",這是很普遍的一種現象。當然這樣的抱怨要從2個方面來分析,一方面從開發人員本身可能存在不理解,或者逆反心
理的情況,另一方面,項目經理也要反思:我所采取的管理措施是否簡單有效?搞管理不是搞學術研究,沒有完美的管理,只有有效的管理,而項目經理往往試圖堵
住所有的漏洞,解決所有的問題,恰恰是這種理想,會使項目的管理陷入一個誤區,作繭自縛,最后無法實施有效的管理,導致項目的失敗。
????? 7規模控制原則
該原則是和上面提到的其他原則相配合使用的,即要控制項目組的規模,不要人數太多,人數多了,進行溝通的渠道就多了,管理的復雜度就高了,對項目經理的要求也就高了。在微軟的?
十四. 軟件項目管理在管理思維中的空白
空白1:為效益而實施項目管理
為什么我們要實施項目管理,是為了提高項目的效益。這里所指的項目的效益是一個綜合性的指標,包括低風險、高產出等。為此我們不難得出我們在實施項目管
理應該掌握的度。即:引入項目管理后所產生的效益減去項目管理的成本后必須大于未引入項目管理時的效益。由于引入項目管理后所產生的效益與項目管理的復雜
度(項目管理的成本)并非線性相關的,因此項目管理的復雜度必然存在一個最優值,這就是我們應該把握的度。也許上面的說法比較抽象。一個實際行之可效的判
斷項目管理的度規則就是:大家認可并且能夠準確地理解和實施。拿美國項目管理專家James P Lewis的話說就是KISS原則(Keep it
simple and stupid),拿物理學家愛因斯坦的話說就是:Keep it simple but not too simple.
空白2:考慮所處環境
任何系統都是建立在一個具體的系統環境中的,一般情況下受上一級系統影響最為顯著,這是系統論的觀點。項目管理是企業管理的下屬層次,因此在很大程度上
項目管理的成功與否常常受企業管理的制度制約(比如說設備采購的批復等待會延誤工期),這就是為什么常常會出現計劃不如變化來的快的原因。因為我們在制定
計劃時根本就沒有考慮自身和客戶雙方的企業管理的環境,所以我們的計劃在實施過程中會受到企業管理環境因素的影響。我敢跟你打賭:在沒有人事激勵機制常常
拖欠或故意克扣員工工資但獲得CMM5認證的公司開發效率不會比一個沒有實施項目管理的開發團隊的效率高多少。因為惡劣的公司人事制度扼殺了開發人員的天
才和積極性。因此,作為一個項目管理者,審視自身的項目所處的企業環境并做出準確的判斷是非常有必要的。缺少良好的項目環境,項目管理者的心血常常白費。
這往往是我們中的一些項目經理在不同的公司里項目管理表現大相徑庭的原因。
此外,正是基于企業環境這樣一個觀點,目前美國
PMI,日本ENAA等提出了項目管理成熟度模型(OPM3和P2M),改變了傳統PMBOK的缺陷(忽略外部因素和自身的靈活性)。有興趣的項目管理者
可以參看有關項目管理成熟度和企業管理方面(建議參看職業經理人方面)的資料。
空白3:合理評判軟件項目管理
我們總是把過多的項目失敗歸罪到項目經理的名頭上。他們的角色常常是替罪羊而不是領導者,他們擁有的更多的是責任而絕非職權。實際上項目失敗并非完全決定于項目管理,比如說信息系統過
低的報價。一個項目按時在預算范圍內完成了而另外一個則沒有按時完成,這不意味著第一個項目管理得比較好。因為前者可能是項目時間和成本寬松的項目而后者
根本就是不可能完成的項目。前者項目管理的意義在于獲得較高的項目效益而后者的意義在于避免更大的項目損失。很可惜,充滿了浮躁的軟件企業沒有諸如此類的
意識,一些項目在未開始前注定就是失敗的,項目經理們一上手便被扣以一責任人的鐐銬。因此,項目管理有無具體效果,需要合理地進行評判,單純以出效益為上
的觀點未必有失偏頗。
空白4:心理學的必要性
沒有一個領域像軟件項目管理中人的因素更為重要,在軟件領域沒有
實現自動化之前,一切試圖取代人的主要作用的機制都是收效甚微的。人的行為是心智活動的表現。開發人員的心理活動決定了其在開發的表現。合適的壓力能夠勾
起開發人員的成功欲望但是過大的壓力卻直接影響著項目參與者的身心健康。特別是后者一直以來都未能引起軟件開發界的重視。很多人曾經有過不明不白的辭職經
歷,在沒有學習《管理心理學》之前,筆者對這些人的"過激"行為有時想想都覺得奇怪。作為一個軟件項目管理者,不了解和掌握管理心理學,很難針對復雜多變
的人的因素采取合理的應對措施,同時自身的心理健康也未必能夠得到保證。為此筆者建議有條件的軟件企業,可以通過聘用心理顧問來處理員工的心理問題,以此
緩和由于工作壓力而導致的員工之間矛盾沖突和項目坍塌。
空白5:尊重常識,系統性考慮問題
這個觀點筆者在《軟
件項目管理原則談》已經重申過。就像不要指望人一秒鐘跑二十米一樣指望項目中有過多的奇跡出現。可惜我們中的大多項目管理者在進行項目管理時依然實施"大
躍進"。我們的管理者都知道自然規律不可違抗性,但是卻很少有人意識到一些社會規律的不可違抗性。他們總以為唯物的主觀能動性能夠替代實際,產生奇跡。加
班被認為是解決資源匱乏的唯一途徑,通過開發人員"無上"的生產力來達成項目的成功。很少有人會意識到加班造成的疲勞會再次使工作效率降低這一事實。這是
一種缺乏常識和系統性思考問題的表現。諸如此類的表現還有"唯工具論"和"唯方法論"。
實際上,項目管理涉及各個方方面面,一味提高某一方面作用而忽略該方面對其它方面的影響,并不能提高項目管理的層次和最終產出,這是制止我們的項目管理者走偏激(極端)立場的一劑良藥,希望項目管理者們能有所意識。
空白6:學會思考
項目管理不是拿來主義,需要項目管理者進行認真的思考。這就是為什么我們項目管理者中不乏PMP和IPMP但是項目卻未能如愿以償的原因。理論和實踐的
差距極大地挫傷項目管理者的積極性。"證書無用論"所持的觀點其依據也在于此。理論是一種完美的抽象,而現實是各種條件的集合。我們的項目管理者在實踐上
往往生搬硬套而忽略其依存條件,這就是招聘項目經理"唯經驗論"的來源。一位項目管理者跟我交流的時候提到無法使用掙值(Earned
Value)的概念,原因是公司人事部和財務部不愿意出示員工的收入清單。我建議他將掙值換為掙時(Earned
Time),以時間替代成本。從項目進度的意義上來看這兩者其實是一致的,問題馬上得到了解決。可惜的是我們的項目管理者往往未學會思考具體概念的真正含
義之前并匆匆上驢,提著長槍去和風車做斗爭去了(注:唐吉訶德)。
空白7:學會計劃
現實中我們往往用補救措施代替計劃,其效果便如軟件缺陷的
放大效應。在項目經理的招聘中,你聽到的只是幾個項目管理白癡問你項目出了什么問題應該怎樣解決的提問,這些項目管理白癡在不斷地做各種問題假設,而你必
須根據假設采取各種符合這些項目管理白癡口味的回答。但是,作為項目管理的來說,項目管理的真正意義在于事先預防各種偏離項目目標的問題出現而不是在于解
決問題。古話說得好"磨刀不誤砍柴工"。你不能期望癌癥有100%的治愈率,但是你可以通過合理的生活習慣和鍛煉來防止癌癥的出現。我們在進行項目管理
時,首先應該考慮如何防止問題的出現,雖然它不能保證所有的問題(風險)都可以避免,但是通過計劃,你將擁有更多問題(風險)應對儲備,能夠在問題出現時
有備無患。一個只會在問題出現時考慮應對措施的項目經理只是一個失敗的項目經理。其項目結果無異是把健康交給醫生而不是自己。作為項目管理的定位來說,項
目管理應該是"管理會計"的角色而不是"成本會計"的角色。
最后,以某電影的臺詞來結束本文;人為什么犯病?簡單的東西想復雜
了,復雜的東西想簡單了,人就會犯病"。拿這句臺詞來形容我們目前的項目管理狀況一點也不為過。軟件項目管理是一個從"自發"走向"自覺"的過程,也是一
個從經驗主義走向理性主義的過程。軟件項目管理是一個主動的管理,而這一切,需要廣大項目管理者的項目管理思維和積極實踐。
?
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1231828
/*
自從XML真正形成以來(我認為是Org.W3C組織發布XML標準時開始),XML得到了很快的發展,
?很多廠商都有推出了自己的XML解析器,如Apache的xalan,IBM的xerces,sun的JDOM等,不過這些都是在
?基于JAXP(java API for XML processing)的,從JDK 1.4.0開始的后續j2sdk里都附加了JAXP,這給開發人員
?帶來了很大的方便,這使得我們在處理一般的XML功能上的問題時不再需要去用第三方的XML處理器了.
?隨著XML的迅速發展,SAX也從1.0到了現在的2.0了(還是能夠和1.0兼容),結構上有了一些較大的變化.
?DOM(document object model)每次讀取XML節點時都要把它load到內存里 來,在文檔很大時,就顯得很慢了,SAX(simple API for XML),是一個XML解析器的接口,它比DOM更低級一些,它是一種基于事件和回調模式的XML處理方式,?因此在解析速度上DOM是沒法比 的(當要解析的XML文檔很大的時更是如此).那么在SAX中事件響應(event)是什么呢 ??我個人認為這一點和Swing,AWT中的事件義有點相似的,都有是指在觸發某些特定的行為時所做的處理,如:mouse 的click事件等到.?這里則是指碰到特定的XML節點的所做的處理,如文檔開始(startDocument),文檔結束 (endDocument),元素開始(startElement)等很多,大家看一下SAX的API中的方法名字就知道有哪些事件了,基本上可以做到見 文知義的.在只想分析XML內容(只讀),要求高性能,靈活性?能夠定位錯誤信息(SAX能夠定位錯誤的行列位置)時,最好用SAX來做.?一般情況下SAX是按下面的原理去使用的:
? <1>設置事件處理器(SAX 1.0是使用一個通過繼承HandlerBase類的實例來設置的,SAX 2.0則是繼承DefaultHandler的,還有用XMLReader方式的,在原理上沒有很大的區別)
? <2>載入要解析的內容
? <3>在需要解析的事件方法里(具體參見SAX API文檔)加入自己的控制邏輯.
? <4>重復<3>直到解析完為止.??????? ?????????
?
?在這里我自己寫了一個描述電影海報信息的XML文件(file.xml),用SAX2.0寫了一個很簡單的XML內容閱讀器來解析它,?和大家交流一下自己的心得.程序在我的機器上經過了測試的(OS: win2k Advanced Server(English version),
?Intel pentium CPU, 256M RAM)
*/
import org.w3c.dom.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import javax.xml.parsers.*;
class MyXMLReader extends DefaultHandler
{??
?//Fields
?private int index;
?private Locator locator;
?//Constructor
?public MyXMLReader(){
??super(); //it must be done !
?}
?//nain method
?public static void main(String[] args){
??try{???
????? SAXParserFactory sf? = SAXParserFactory.newInstance();
????? SAXParser sp = sf.newSAXParser();
????? MyXMLReader reader = new MyXMLReader();
????? sp.parse(new InputSource("film.xml"),reader);
??}
??catch(Exception e){
???e.printStackTrace();
??}
?}?
?//Response the startDocument event
?public void startDocument() {
??System.out.println("\n********************************* (:?元旦電影海報 :)?***********************************\n");
?}??
//Response the startElement event
?public void startElement(String uri, String localName, String qName, Attributes attrs){??
??if( qName.equalsIgnoreCase("film") ){???
???index ++;???
???int attrCount = attrs.getLength();
???for( int i = 0; i < attrCount; i ++ ){
????String attrName = attrs.getQName(i);
????if( attrName.equalsIgnoreCase("name") ){
?????System.out.println("\t第" + index + "場,片名:<<" +? attrs.getValue(i) + ">>");
????}
????if( attrName.equalsIgnoreCase("price") ){
?????System.out.println("\t票價:" + attrs.getValue(i) );?????
????}
????if( attrName.equalsIgnoreCase("station") ){
?????System.out.println("\t放映地點:" + attrs.getValue(i) );?????
????}
????if( attrName.equalsIgnoreCase("time") ){
?????System.out.println("\t放映時間:" + attrs.getValue(i) );
????}
????if( attrName.equalsIgnoreCase("describtion") ){
?????System.out.println("\t影片簡介:" + attrs.getValue(i) );
????}
????System.out.println();
??}
?}
?//Response the endDocument event
?public void endDocument(){
??System.out.println("\t\t\t\t\t\t\t------?共有" + index + "場電影要放映");??
?}
?//Response the endElement event
?public void endElement(String uri, String localName, String qName){
??? ?//add your codes if neccessary ...
?}
?//Print the fata error information
?public void fatalError(SAXParseException e){
??System.out.println("\nFatal error information -->");
??System.out.println("\t" + e.getMessage());
??System.out.println("\tAt line " + locator.getLineNumber() +
????????????????? ",column " + locator.getColumnNumber());
?}
?
?//Print the usual error information
?public void error(SAXParseException e){
??System.out.println("\nUsual error information -->");??
??System.out.println("\t" + e.getMessage());
??System.out.println("\tAt line " + locator.getLineNumber() +
????????????????? ",column " + locator.getColumnNumber());
?}
?
?//Print the warning information
?public void warning(SAXParseException e){
??System.out.println("\nWarning information -->");????
??System.out.println("\t" + e.getMessage());??
??System.out.println("\tAt line " + locator.getLineNumber() +
????????????????? ",column " + locator.getColumnNumber());
?}
?//Store the error locator object
?public void setDocumentLocator(Locator lct){
??locator = lct;
?}
}//End class MyXMLReader
附
: film.xml完全的內容:
<?xml version="1.0" encoding="GB2312"?>
?? <!-- 2003年元月1號長沙市各大影院落放映列表 -->
?? <common city="ChangSha China" date="01/01/2003">
???? <film name="英雄" price="30" station="田漢大劇場" time="19:00"
??????? describtion="國產最新大片,張藝謀導演,梁朝偉,張曼玉,李連杰等眾多大明星主演">
??</film>
??<film name="無間道" price="20" station="長沙市演藝中心" time="15:00"
??????? describtion="韓國大片">
??</film>
??<film name="武士" price="20" station="湖南省電影院" time="17:00"
??????? describtion="韓國大片,有點像英雄">
??</film>??
??<film name="長排山之戰" price="15" station="長沙市電影超市A1廳" time="19:00"
??????? describtion="反映對越自衛反擊戰時期中國軍人的故事片">
? ??? </film>
??<film name="高山下的花環" price="15" station="長沙市電影超市A2廳" time="19:00"
??????? describtion="反映對越自衛反擊戰時期中國軍人的故事片">
??</film>??
??? <film name="這里的黎明靜悄悄" price="15" station="長沙市電影超市A3廳" time="19:00"
??????? describtion="反映對越自衛反擊戰時期中國軍人的故事片">
??</film>
??<film name="子夜" price="15" station="長沙市電影超市B1廳" time="19:00"
??????? describtion="反映對越自衛反擊戰時期中國軍人的故事片">
??</film>
? </common>
?
First of all, if you develop your application by Eclipse, it means you have had the ant tool and you need not to download the internet.
A project has three attributes:
Attribute
|
Description
|
Required
|
name |
the name of the project. |
No |
default |
the default target to use when no target is supplied. |
No; however, since Ant 1.6.0, every project includes an implicit target that contains any and all top-level tasks and/or types. This target will always be executed as part of the project's initialization, even when Ant is run with the -projecthelp option. |
basedir |
the base directory from which all path calculations are done. This attribute might be overridden by setting the "basedir" property beforehand. When this is done, it must be omitted in the project tag. If neither the attribute nor the property have been set, the parent directory of the buildfile will be used. |
No |
Optionally, a description for the project can be provided as a top-level <description>
element (see the
description
type).
Each project defines one or more targets. A target is a set of tasks you want to be executed. When starting Ant, you can select which target(s) you want to have executed. When no target is given, the project's default is used.
A target can depend on other targets. You might have a target for compiling, for example, and a target for creating a distributable. You can only build a distributable when you have compiled first, so the distribute target depends on the compile target. Ant resolves these dependencies.
It should be noted, however, that Ant's depends
attribute only specifies the order in which targets should be executed - it does not affect whether the target that specifies the dependency(s) gets executed if the dependent target(s) did not (need to) run.
Ant tries to execute the targets in the depends
attribute in the order they appear (from left to right). Keep in mind that it is possible that a target can get executed earlier when an earlier target depends on it:
<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>
Suppose we want to execute target D. From its depends
attribute, you might think that first target C, then B and then A is executed. Wrong! C depends on B, and B depends on A, so first A is executed, then B, then C, and finally D.
In a chain of dependencies stretching back from a given target such as D above, each target gets executed only once, even when more than one target depends on it. Thus, executing the D target will first result in C being called, which in turn will first call B, which in turn will first call A. After A, then B, then C have executed, execution returns to the dependency list of D, which will not call B and A, since they were already called in process of dependency resolution for C and B respectively as dependencies of D. Had no such dependencies been discovered in processing C and B, B and A would have been executed after C in processing D's dependency list.
A target also has the ability to perform its execution if (or unless) a property has been set. This allows, for example, better control on the building process depending on the state of the system (java version, OS, command-line property defines, etc.). To make a target sense this property, you should add the if
(or unless
) attribute with the name of the property that the target should react to. Note: Ant will only check whether the property has been set, the value doesn't matter. A property set to the empty string is still an existing property. For example:
<target name="build-module-A" if="module-A-present"/>
<target name="build-own-fake-module-A" unless="module-A-present"/>
In the first example, if the module-A-present
property is set (to any value), the target will be run. In the second example, if the module-A-present
property is set (again, to any value), the target will not be run.
If no if
and no unless
attribute is present, the target will always be executed.
Important: the if
and unless
attributes only enable or disable the target to which they are attached. They do not control whether or not targets that a conditional target depends upon get executed. In fact, they do not even get evaluated until the target is about to be executed, and all its predecessors have already run.
The optional description
attribute can be used to provide a one-line description of this target, which is printed by the -projecthelp
command-line option. Targets without such a description are deemed internal and will not be listed, unless either the -verbose
or -debug
option is used.
It is a good practice to place your
tstamp
tasks in a so-called initialization target, on which all other targets depend. Make sure that target is always the first one in the depends list of the other targets. In this manual, most initialization targets have the name "init"
.
If the depends attribute and the if/unless attribute are set, the depends attribute is executed first.
A target has the following attributes:
Attribute
|
Description
|
Required
|
name
|
the name of the target.
|
Yes
|
depends
|
a comma-separated list of names of targets on which this target depends.
|
No
|
if
|
the name of the property that must be set in order for this target to execute.
|
No
|
unless
|
the name of the property that must not be set in order for this target to execute.
|
No
|
description
|
a short description of this target's function.
|
No
|
A target name can be any alphanumeric string valid in the encoding of the XML file. The empty string "" is in this set, as is comma "," and space " ". Please avoid using these, as they will not be supported in future Ant versions because of all the confusion they cause. IDE support of unusual target names, or any target name containing spaces, varies with the IDE.
Targets beginning with a hyphen such as "-restart"
are valid, and can be used to name targets that should not be called directly from the command line.
A task is a piece of code that can be executed.
A task can have multiple attributes (or arguments, if you prefer). The value of an attribute might contain references to a property. These references will be resolved before the task is executed.
Tasks have a common structure:
<nameattribute1="value1" attribute2="value2" ... />
where name is the name of the task, attributeN is the attribute name, and valueN is the value for this attribute.
There is a set of
built-in tasks
, along with a number of
optional tasks
, but it is also very easy to
write your own
.
All tasks share a task name attribute. The value of this attribute will be used in the logging messages generated by Ant.
Tasks can be assigned an id
attribute:
<taskname id="taskID" ... />
where taskname is the name of the task, and taskID is a unique identifier for this task. You can refer to the corresponding task object in scripts or other tasks via this name. For example, in scripts you could do:
<script ... >
task1.setFoo("bar");
</script>
to set the foo
attribute of this particular task instance. In another task (written in Java), you can access the instance via project.getReference("task1")
.
Note1: If "task1" has not been run yet, then it has not been configured (ie., no attributes have been set), and if it is going to be configured later, anything you've done to the instance may be overwritten.
Note2: Future versions of Ant will most likely not be backward-compatible with this behaviour, since there will likely be no task instances at all, only proxies.
A project can have a set of properties. These might be set in the buildfile by the
property
task, or might be set outside Ant. A property has a name and a value; the name is case-sensitive. Properties may be used in the value of task attributes. This is done by placing the property name between "${
" and "}
" in the attribute value. For example, if there is a "builddir" property with the value "build", then this could be used in an attribute like this: ${builddir}/classes
. This is resolved at run-time as build/classes
.
Ant provides access to all system properties as if they had been defined using a <property>
task. For example, ${os.name}
expands to the name of the operating system.
For a list of system properties see
the Javadoc of System.getProperties
.
In addition, Ant has some built-in properties:
basedir the absolute path of the project's basedir (as set
with the basedir attribute of <project>).
ant.file the absolute path of the buildfile.
ant.version the version of Ant
ant.project.name the name of the project that is currently executing;
it is set in the name attribute of <project>.
ant.java.version the JVM version Ant detected; currently it can hold
the values "1.1", "1.2", "1.3", "1.4" and "1.5".
Example Buildfile
<project name="MyProject" default="dist" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<!-- Create the time stamp -->
<tstamp/>
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init"
description="compile the source " >
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile"
description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>
<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean"
description="clean up" >
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>
Notice that we are declaring properties outside any target. As of Ant 1.6 all tasks can be declared outside targets (earlier version only allowed <property>,<typedef> and <taskdef>). When you do this they are evaluated before any targets are executed. Some tasks will generate build failures if they are used outside of targets as they may cause infinite loops otherwise (<antcall>
for example).
We have given some targets descriptions; this causes the projecthelp invocation option to list them as public targets with the descriptions; the other target is internal and not listed.
Finally, for this target to work the source in the src subdirectory should be stored in a directory tree which matches the package names. Check the <javac> task for details.
Token Filters
A project can have a set of tokens that might be automatically expanded if found when a file is copied, when the filtering-copy behavior is selected in the tasks that support this. These might be set in the buildfile by the
filter
task.
Since this can potentially be a very harmful behavior, the tokens in the files must be of the form @
token@
, where token is the token name that is set in the <filter>
task. This token syntax matches the syntax of other build systems that perform such filtering and remains sufficiently orthogonal to most programming and scripting languages, as well as with documentation systems.
Note: If a token with the format @
token@
is found in a file, but no filter is associated with that token, no changes take place; therefore, no escaping method is available - but as long as you choose appropriate names for your tokens, this should not cause problems.
Warning: If you copy binary files with filtering turned on, you can corrupt the files. This feature should be used with text files only.
You can specify PATH
- and CLASSPATH
-type references using both ":
" and ";
" as separator characters. Ant will convert the separator to the correct character of the current operating system.
Wherever path-like values need to be specified, a nested element can be used. This takes the general form of:
<classpath>
<pathelement path="${classpath}"/>
<pathelement location="lib/helper.jar"/>
</classpath>
The location
attribute specifies a single file or directory relative to the project's base directory (or an absolute filename), while the path
attribute accepts colon- or semicolon-separated lists of locations. The path
attribute is intended to be used with predefined paths - in any other case, multiple elements with location
attributes should be preferred.
As a shortcut, the <classpath>
tag supports path
and location
attributes of its own, so:
<classpath>
<pathelement path="${classpath}"/>
</classpath>
can be abbreviated to:
<classpath path="${classpath}"/>
In addition,
DirSet
s,
FileSet
s, and
FileList
s can be specified via nested <dirset>
, <fileset>
, and <filelist>
elements, respectively. Note: The order in which the files building up a FileSet are added to the path-like structure is not defined.
<classpath>
<pathelement path="${classpath}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="classes"/>
<dirset dir="${build.dir}">
<include name="apps/**/classes"/>
<exclude name="apps/**/*Test*"/>
</dirset>
<filelist refid="third-party_jars"/>
</classpath>
This builds a path that holds the value of ${classpath}
, followed by all jar files in the lib
directory, the classes
directory, all directories named classes
under the apps
subdirectory of ${build.dir}
, except those that have the text Test
in their name, and the files specified in the referenced FileList.
If you want to use the same path-like structure for several tasks, you can define them with a <path>
element at the same level as targets, and reference them via their id attribute - see
References
for an example.
A path-like structure can include a reference to another path-like structure via nested <path>
elements:
<path id="base.path">
<pathelement path="${classpath}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="classes"/>
</path>
<path id="tests.path">
<path refid="base.path"/>
<pathelement location="testclasses"/>
</path>
The shortcuts previously mentioned for <classpath>
are also valid for <path>
.For example:
<path id="base.path">
<pathelement path="${classpath}"/>
</path>
can be written as:
<path id="base.path" path="${classpath}"/>
generally, you need not to write your builder.xml file started from scratch. you can just modify the following
part to meet your demand.
<project name="javastep" default="deploy" basedir=".">
<!-- ===================== Property Definitions =========================== -->
??? <!--
???????? All properties should be defined in this section.
???????? Any host-specific properties should be defined
???????? in the build.properties file.
? In this app, the following properties are defined in build.properties:
?? o? tomcat.home???? - the home directory of your Tomcat installation
??????? o? webapps.home??? - the place to copy the war file to deploy it
??? -->
? <property file="build.properties" />
?
? <property name="app.home"????????? value="." />
? <property name="app.name"????????? value="javastep" />
? <property name="javadoc.pkg.top"?? value="hello" />
? <property name="src.home"????????? value="${app.home}/src"/>
? <property name="lib.home"????????? value="${app.home}/WebRoot/WEB-INF/lib"/>
?
? <property name="classes.home"?????? value="${app.home}/WebRoot/WEB-INF/classes/"/>
? <property name="deploy.home"?????? value="${app.home}/deploy"/>
? <property name="doc.home"????????? value="${app.home}/doc"/>
? <property name="web.home"????????? value="${app.home}/WebRoot"/>
? <property name="build.home"??????? value="${app.home}/build"/>
? <property name="build.classes"???? value="${build.home}/WEB-INF/classes"/>
? <property name="build.lib"???????? value="${build.home}/WEB-INF/lib"/>
<!-- ==================== Compilation Classpath =========================== -->
??? <!--
???????? This section creates the classpath for compilation.
??? -->
? <path id="compile.classpath">
??? <!-- The object files for this application -->
??? <pathelement location="${classes.home}"/>
??? <!-- The lib files for this application -->
??? <fileset dir="${lib.home}">
????? <include name="*.jar"/>
????? <include name="*.zip"/>
??? </fileset>
??? <!-- All files/jars that Tomcat makes available -->
? </path>
<!-- ==================== Build Targets below here========================= -->
<!-- ==================== "help" Target =================================== -->
??? <!--
???????? This is the default ant target executed if no target is specified.
???????? This helps avoid users just typing 'ant' and running a
???????? default target that may not do what they are anticipating...
??? -->
?<target name="help" >
?? <echo message="Please specify a target! [usage: ant <targetname>]" />
?? <echo message="Here is a list of possible targets: "/>
?? <echo message="? clean-all.....Delete build dir, all .class and war files"/>
?? <echo message="? prepare.......Creates directories if required" />
?? <echo message="? compile.......Compiles source files" />
?? <echo message="? build.........Build war file from .class and other files"/>
?? <echo message="? deploy........Copy war file to the webapps directory" />
?? <echo message="? javadoc.......Generates javadoc for this application" />
?</target>
<!-- ==================== "clean-all" Target ============================== -->
?? <!--
????????? This target should clean up any traces of the application
????????? so that if you run a new build directly after cleaning, all
????????? files will be replaced with what's current in source control
?? -->
?<target name="clean-all" >
??? <delete dir="${build.home}"/>
??? <delete dir="${classes.home}"/>
??? <delete dir="${deploy.home}"/>
??? <!-- can't delete directory if Tomcat is running -->
??? <delete dir="${webapps.home}/${app.name}" failonerror="false"/>
??? <!-- deleting the deployed .war file is fine even if Tomcat is running -->
??? <delete dir="${webapps.home}/${app.name}.war" />
??? <!-- delete the javadoc -->
??? <delete dir="${doc.home}"/>
?</target>
<!-- ==================== "prepare" Target ================================ -->
??? <!--
????????? This target is executed prior to any of the later targets
????????? to make sure the directories exist. It only creates them
????????? if they need to be created....
????????? Other, similar, preparation steps can be placed here.
??? -->
? <target name="prepare">
??? <echo message="Tomcat Home = ${tomcat.home}" />
??? <echo message="webapps Home = ${webapps.home}" />
??? <mkdir dir="${classes.home}"/>
??? <mkdir dir="${deploy.home}"/>
??? <mkdir dir="${doc.home}"/>
??? <mkdir dir="${doc.home}/api"/>
??? <mkdir dir="${build.home}"/>
??? <mkdir dir="${build.home}/WEB-INF" />
??? <mkdir dir="${build.home}/WEB-INF/classes" />
??? <mkdir dir="${build.home}/WEB-INF/lib" />
? </target>
<!-- ==================== "compile" Target ================================ -->
??? <!--
????????? This only compiles java files that are newer
????????? than their corresponding .class files.
???? -->
? <target name="compile" depends="prepare" >
??? <javac srcdir="${src.home}" destdir="${classes.home}" debug="yes" >
??????? <classpath refid="compile.classpath"/>
??? </javac>
? </target>
<!-- ==================== "build" Target ================================== -->
??? <!--
????????? This target builds the war file for the application
????????? by first building the directory structure of the
????????? application in ${build.home} and then creating the
????????? war file using the ant <war> task
???? -->
? <target name="build" >
??? <!-- Copy all the webapp content (jsp's, html, tld's, xml, etc. -->
??? <!-- Note that this also copies the META-INF directory -->
??? <copy??? todir="${build.home}">
????? <fileset dir="${web.home}"/>
??? </copy>
??? <!-- Now, copy all the Java class files -->
??? <copy??? todir="${build.home}/WEB-INF/classes">
????? <fileset dir="${classes.home}"/>
??? </copy>
??? <!-- Now, copy all the properties files, etc that go on the classpath -->
??? <copy??? todir="${build.home}/WEB-INF/classes">
????? <fileset dir="${src.home}">
???????? <include name="**/*.properties" />
???????? <include name="**/*.prop" />
????? </fileset>
??? </copy>
??? <!-- Now, copy all the jar files we need -->
??? <copy??? todir="${build.home}/WEB-INF/lib">
????? <fileset dir="${lib.home}" />
??? </copy>
??? <!-- Create the <war> file -->
??? <jar jarfile="${deploy.home}/${app.name}.war"
???????? basedir="${build.home}"/>
? </target>
<!-- ==================== "deploy" Target ================================= -->
??? <!--
???????? This target simply copies the war file from the deploy
???????? directory into the Tomcat webapp directory.
???? -->
? <target name="deploy" depends="build" >
??? <!-- Copy the contents of the build directory -->
??? <copy todir="${webapps.home}"? file="${deploy.home}/${app.name}.war" />
? </target>
<!-- ==================== "doc" Target ==================================== -->
??? <!--
???????? This task creates javadoc. It is dependent upon only the
???????? 'compile' target so it is not executed in a normal build.
???????? As a result, the target needs to be run on its own.
??? -->
? <target name="javadoc" depends="compile">
????? <javadoc sourcepath = "${src.home}"
????????????????? destdir = "${doc.home}/api"
???????????? packagenames = "${javadoc.pkg.top}.*"/>
? </target>
?
<!-- ==================== "test" Target ================================== -->
??? <!--
??????? This task runs all test cases. It invokes each test case individually.
??????? The "test-all" target is tied back to the "struts-test" target which
??????? actually runs the tests. This allows other test targets to be created
??????? in this section while maintaining the ability to run each test target
??????? individually. All individual test targets should be added to the
??????? "depends" attribute of the "test-all" target to provide a single
??????? target that runs all tests.
-->
? <target name="test-all" depends="struts-tests" />
? <target name="struts-tests" depends="build" >
????? <junit printsummary="yes" >
????????? <classpath >
????????????? <pathelement location="${classes.home}"/>
????????????? <pathelement location="${build.home}"/>
????????????? <pathelement location="${build.home}/WEB-INF/classes"/>
????????????? <path refid="compile.classpath"/>
????????? </classpath>
????????? <formatter type="plain" />
????????? <test name="hello.mocktest.TestHelloAction" />
????????? <test name="hello.mocktest.TestHelloActionMultiple" />
????? </junit>
???
? </target>
</project>
?