項目實訓心得
在這一個多月的項目實訓過程,我感到是我專業學習中收獲非常大的一個月。在這個月里,我體驗到了團隊合作的經驗,編程過程中的樂趣,以及將學習應用到實際、從實踐中學習的豐收感。
這一個月里,得到了二個最寶貴體驗:一是參與了一個團隊合作的、有很強多同模塊相互性、和一套完整生命周期流程的工程項目。這一套項目按照軟件工程的流程一步步走下來,經歷了需求分析,詳細設計,實際編碼和測試這一系列階段。一步一步慢慢的走下來。雖然對于真實的項目來說,這個項目的復雜度和規模并不是很大,邏輯要求也不是太嚴格。但是對于只參加一些3-4人的項目編程的我來說,已經第一次讓我體真正的體驗到將編程作為一項工程來執行的難得經驗。
第二個體驗是詳細設計中,將軟件架構和分層的思想以及簡單的工程模式等應用到了項目中。使用框架等方式,非常有效的提高了代碼的復用和工程的可維護性,雖然多層結構看似麻煩,但實際上它很大的降低了設計的復雜度,在實際的體驗中感到,使用了框架后的模塊,維護起來清晰了很多,容易了很多,降低了耦合,同時增強了模塊間的交互和重用。
隨著整個工程的流程一步步進行,我們看到了一個工程的一次次成長。項目伊始,我們得到了項目需求文檔(我想這一步在實際中也應該是由項目人員精心設計才完成的),對于工程的不同用例,將工程分為了六個模塊,并對應的將組員分為了六組。我們的第一步是完成對需求文檔的理解,而成果就是對應了各個模塊的實際功能的靜態頁面,因為軟件客戶最后體驗所有需求的功能實現就是通過操作頁面來實現,所以頁面要在客戶需求的角度去考慮,同時要將需求的功能都賦予體現。在這個過程中,大家除了按功能分化出頁面分類外,大部分時間還用來精心設計頁面的風格。頁面布局和菜單中大量用到了JavaScript和CSS。和以我往設計頁面時不同的是,為了讓大家可以公用這些設計,在頁面的布局中不能太復雜,甚至幾乎是不能在需要統一的地面對整體的布置有任何復雜的干預。所有希望統一的部分都要在公共的CSS和JavaScript中做出方便統一使用的類或方法,在頁面本身的代碼中幾乎看不到布局設計,只有功能組件。
在頁面設計通過審核之后就是詳細設計階段了,在這階段的前幾天我們犯了一個順序錯誤,直接從數據庫著手。結果由于項目的功能的復雜性和模塊之間太多需要交互的地方,使得數據庫的設計進行的很緩慢。經過老師的提點我們改為從程序編碼的框架開始著手。聯系各功能的具體實現來設計編碼的層次結構(框架詳細設計在下一節),劃分出公共平臺。這樣再從各模塊的功能及其交互劃分來聯系設計數據庫就變的清晰了很多。在設計過程中我們還使用了E-R圖來設計出關系數據庫,即從參與的對象和對象之間的關系最終設計出數據庫的方法。在這次設計中發現自己在利用一些系統的理論進行整體的數據庫模型設計方面還存在很多不足。數據庫完成后,對框架的設計也基本完成,公共的分頁設計,數據庫連接與關閉,工程的文件結構和工程的環境也在幾次討論后完成統一設計。
由于之前對struts有了一定的了解,所以我在需求分析階段就開始嘗試著著手對幾個簡單模塊的實現編碼,之后在詳細設計階段中,每次討論后新加的內容都需要對已經完成的代碼進行一次大的修改。隨著代碼的增長,嘗試了很多種文件結構。之后引入項目的框架也經歷了很大的修改和許多次的嘗試。此外的修改還包括BaseAction的引入,DispatchAction的引入,使用struts異常處理等,并做好工程備份及將修改記錄在日報中。在這一次次的修改中讓我受益匪淺,對這些設計和修改有了更深刻的體會。這樣在詳細設計階段的過程中,框架設計都已經在編碼中事先進行了實現和測試,一些功能在寫好后被分離出來作為公共平臺。終于在小組開始編碼時確定出了統一并詳細完整的的工程的全部環境,項目的框架結構和整體編碼方式。我的編碼實現和單元測試也基本完成。
在兩周的編碼過程中,我主要是和吉利一起協助各模塊編碼,增加各模塊間交流,在這期間也解決問題的過程中學到知識。經過全體組員兩周的努力工作,終于進入了測試階段。我和吉利負責整體測試,測試聯結了所有模塊之后,可以順利的完成全套的流程。讓整個設計可以在6個流程中一步步的走下去,同時保證數據庫中所有數據和狀態的正確性。隨著測試一次次的進行,問題漸漸被全部排除,經過3次測試之后,基本可以完全順利的走完全套流程。
我們這次工程中使用的是四層結構的框架,即將MVC三層結構的同時,將model模型層分成了model模型層和DAO持久層。其中又根據工廠模式分出DAO接口,bean,factory,service(manager)提供DAO實現。
結構實現:首先我們根據框架,設計出相應的文件結構。視圖層即所有JSP文件,和配置文件一起由eclipse的自動生成單獨分在WebRoot下,六模塊的頁面分別分于六個子目錄下。所有的公共頁面和js,css目錄也放入WebRoot下。由于這次項目中模塊間的功能頁面基本是完全相互獨立的,這為在實現視圖層和控制層之間的頁面跳轉控制帶來很大的方便。代碼目錄(src)下為六個模塊的六個目錄,公共代碼目錄(platform),以及后加入的驗證模塊的目錄(validate)。除公共目錄外,各模塊下代碼分為5個目錄:Action,model,Form,manager和dao。(這里有兩個命名的失誤,根據實際的使用,model的名字應該叫bean更合適,而這里manager一般在框架中稱為service。但我們已經有了稱為service的模塊名稱。)這里的Action和Form對應了struts中的組件,DAO層和model-bean一起完成了操作的具體實現,
視圖層view:總體框架上,我們使用的是frameset來實現,不過聽老師說現在流行的使用jap的include結合div等來實現頁面框架。在之后編碼中,因為frameset出現了一個問題,就是用來驗證攔截的過濾器無法刷新整個框架,使得攔截后的頁面只能顯示在被操作的frame中。但是frameset的好處是框架分離的很好,在實現jsp編碼中幾乎完全不用去考慮框架。我不知道用include是否能做到。以前雖然都使用的include,但是是在每個頁面中都要加入include。有時還會影響布局。在編碼過程中,我們用JavaScript實現了很多很好用的效果,比如選擇時間的窗口,表單的正則表達式驗證,表格的變色效果等,封裝到公共的js文件中,調用起來很方便。在這次jap編程中,我終于由最初的在頁面中堆滿java代碼,轉變為只使用一些JSTL,EL語句和struts標簽處理邏輯,美觀了頁面編碼,同時讓頁面更專注于顯示層。但這里我對EL語句和純標簽語句又有些難以取舍。EL語句在頁面代碼中雖然不如單用標簽顯得純粹美觀,但是EL表達式簡約的表現風格讓實現和維護變得容易了很多。
控制層Action的設計一是使用了DispatchAction,將多個Action類合并,方便了管理。二在公共部分中定義了BaseAction,由這個類去繼承struts的DispatchAction。之后我們的所有Action都去繼承這個BaseAction。這樣在需要對Action進行統一處理,以及定義一些供Action公共使用的方法時就可以在這個BaseAction中修改。雖然在這次項目中,BaseAction只定義了個用于處理字符亂碼的方法公共使用,但由此即可瞥見對于更復雜的Action統一處理這種設計也能從容應對。由于是分模塊進行,于是我們將struts的xml配置文件也分為對應各個模塊,使用多xml的配置方式,而這也需要對命名規則等很多方面有更好的協調和統一。在這次控制層的實現中,我起初還是像以前一樣對很多不同的驗證,模型層返回的異常都在Action中處理并跳轉。在之后的修改中,逐漸將這些處理都改至模型層Manager中,由Manager取用持久層的操作方法,實現所有業務邏輯處理。
具體實現功能的模型層中,我們為每個DAO定義了接口和實現類,這也是我第一次將接口真正應用到程序中。同時我們在每個模塊的DAO中應用了工廠模式,由一個factory類實現所有DAO的單例生成。之后在Manager中調用這個實例實現操作。而這個Manager同時本身也是單例實現的,由Action進行靜態調用。可見其中實現Action控制層和DAO持久層交互的就是Manager模型層,并將兩者嚴格的分離開來。同時在Manager中還集合處理了所有來至業務功能邏輯和底部數據庫的所有異常。因為數據庫的連接也是在Manager中創建的,但這不影響持久層的獨立性,因為這是考慮到有時一次業務操作會進行多個數據庫操作、調用多個數據庫方法,將連接在模型層中創建更便于數據庫的高效使用。模型層中對異常的集中處理,更簡化了上下控制層和模型層的實現,使其更專注于各自的業務實現。在異常處理上,使用了struts的一種異常處理機制,在xml配置文件中進行異常配置。這樣在Manager中將異常拋出,由struts實現異常跳轉和提示。同時我們還將自定義的異常處理類也作為公共類公用,這樣就可以在需要的時候對異常進行統一的處理。
在持久層的實現上,我們使用了tomcat數據庫連接池,在編碼中將數據庫連接等方法封裝到公共類中,并且將連接數據源作靜態單例實現,以提高數據庫調用的效率。在DAO的設計方面,我們主要針對實際的操作對象和對應的數據庫進行DAO層方法的封裝。每個方法盡量實現一些簡單的操作。這樣在不同模塊直接有數據和操作交互的時候,只在模型層只要去各個模塊的DAO中取得需要的方法加以組合,實現自己的業務處理。很好的提高了代碼的復用性和可維護性,降低了各個模塊間數據交互處理的設計復雜度。
//文采太爛, 結尾的感慨段就不發了