本文主要基於高級軟件工程課程所學內容,結合我的工程實踐題目——12306系統設計,進行用例建模、業務領域建模以及數據建模,最終形成概念原型。目的在於從中體會軟件工程中需求分析和概念原型設計的過程。
題目簡介
題目基本要求
-
參考12306站點進行售票系統建模設計,盡可能接近覆蓋真實線上系統,實現的功能有但不限於:
- 用戶信息注冊
- 查詢余票: 根據時間,車次,站點區間,座次(一等座,二等座,硬卧,硬座…)查詢余票
- 售票: 支持一次購買同一車次的多張車票(多人),支持訂單30分鍾內鎖定,超時釋放。支付接口可以mock。
- 退票: 支持一個用戶賬戶下的批量退票
- 改簽: 同一用戶一張車票只能改簽一次
-
所有讀寫接口延遲要求 <= 500ms
-
單機支持到500qps的並發請求
本項目只包含針對客戶端app的部分,不包含后台管理系統。
用例分析
什么是用例?
用例的核心概念中首先它是一個業務過程,用例的實質是經過邏輯整理抽象出來的一個業務過程。業務過程就是在待開發軟件所處的業務領域內完成特定業務任務的一系列活動。對於一個用例,一定要滿足以下幾個條件:
- 由業務領域內的某個參與者所觸發。
- 能為特定的參與者完成一個特定的業務任務。
- 終止於某個特定參與者,也就是特定參與者明確地或者隱含地得到了業務任務完成的結果。
這里的參與者是指業務領域內的參與者或者業務實體。參與者可以是一個人,也可以是一個組件或外部設備。
如何獲取用例?
用例包含三個抽象層級:抽象用例,高層用例和擴展用例。抽象用例只需要說明要完成什么樣的任務,高層用例需要說明用例的開始和結束,給用例划定邊界。擴展用例要詳細描述參與者和用例交互的具體過程。所以,獲取用例的過程應該是從簡單到復雜逐步進行的。
首先從需求中找到抽象用例。再用TUCBW和TUCEW來描述的用例的邊界,得到高層用例。對用例進行分類,畫出用例圖。最后詳細分析參與者和用例的交互步驟,得到擴展用例。
購票系統用例分析
因為本系統不包含后台管理的部分,所以系統的主要參與者是12306系統客戶端用戶。對於用戶,系統的主要功能包括:注冊/登錄,查詢車次信息,購票,改簽,退票。用戶可以分為已注冊用戶和游客。從宏觀上看,主要用例如下。

上面的用例圖展示了購票系統和用戶系統兩大模塊為用戶提供的功能。用例圖可以繼續細化,加入用例之間的關聯關系。

業務領域建模
業務領域建模是開發團隊用於獲取業務領域知識的過程。因為軟件工程師往往需要工作在不同的業務領域或者不同項目中,他們需要業務領域知識來開發軟件系統。軟件工程師往往來自不同的專業背景,這可能會影響他們對業務領域的認知。因此業務領域建模有助於開發團隊獲取業務領域知識形成統一的業務認知。
開發團隊獲取業務領域知識的過程一般包括收集業務領域相關信息、執行團隊頭腦風暴、對業務領域相關的知識概念進行分類,最后用UML類圖將業務領域知識圖形化展示。
根據課上所學內容,我理解的業務領域建模步驟如下:
- 收集信息
- 列出業務領域概念及其屬性,分析出概念之間的關系
- 將業務領域概念定義成類,通過類的屬性和關系描述概念的屬性和關系
- 繪制UML類圖
購票系統業務領域建模
由於12306系統較為復雜,這里只針對我所負責的用戶與購票模塊進行分析。
業務領域概念分析
根據業務領域建模步驟,首先需要分析購票系統中有哪些業務概念。
- 未注冊用戶需要注冊,注冊時需要提供姓名、證件號碼、手機號碼等信息。
- 用戶可以登錄,登錄后可以通過購票系統購買車票。
- 用戶可以添加或修改常用聯系人信息,可以為聯系人購買車票。
- 每個車次經過若干個站點。
- 車票包含車次信息、起點和終點等信息。
從上面的分析中可以提出一些名詞如用戶,車次,車票,聯系人以及用戶和聯系人信息。接下來將這些信息歸類為類、屬性以及類之間的關系。
- 用戶是一個名詞,可以獨立存在,因此用戶是一個類。
- 用戶注冊時提供的姓名、證件號碼等信息是名詞,但不可以獨立存在,因此不是類,而是作為用戶的屬性。
- 與用戶類似,聯系人是一個類。聯系人的信息是聯系人的屬性。
- 車次是一個名詞,可以獨立存在,因此車次是一個類。
- 站點是一個名詞,可以獨立存在,因此站點是一個類。
- 同理,車票也是一個類。
- 經過是一個及物動詞,表示車次和站點之間的關系。
- 購買是一個及物動詞,表示用戶和車票之間的關系。
以上就是分析出的類及類之間的關系。接下來根據這些信息繪制UML類圖。
UML 類圖

數據模型設計
考慮到性能因素,車票相關的具有高並發量的數據都采用NoSQL內存數據庫進行存儲。在傳統關系型數據庫中,主要存儲:用戶信息,靜態的車次、站點信息,訂單信息和出票信息。部分會頻繁讀取且很少更新的信息進行了反范式化處理,對這些字段冗余存儲。
用戶
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 用戶ID |
| username | varchar | 用戶名 |
| password | varchar | 密碼 |
| name | varchar | 姓名 |
| id_type | int | 證件類型 |
| id_number | int | 證件號碼 |
| sex | int | 性別 |
| varchar | ||
| passenger_type | int | 乘客類型(成人/學生) |
| register_time | datetime | 注冊時間 |
聯系人
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 聯系人信息ID |
| user_id | int | 用戶ID |
| contact_name | int | 聯系人姓名 |
| contact_number | varchar | 聯系人電話 |
| contact_id_type | int | 聯系人證件類型 |
| contact_id_number | varchar | 聯系人證件號碼 |
| contact_passenger_type | int | 聯系人乘客類型 |
車次
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 車次ID |
| name | varchar | 車次名稱 |
| train_type | int | 車次類型(K/D/G) |
| starting_station_id | int | 起點站ID |
| terminal_station_id | int | 終點站ID |
| starting_station_name | int | 起點站名稱 |
| terminal_station_name | int | 終點站名稱 |
| starting_time | datetime | 車次出發時間 |
| terminal_time | datetime | 車次到達時間 |
站點
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 站點ID |
| name | varchar | 站點名稱 |
| city | varchar | 城市名稱 |
車次區間
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 區間ID |
| train_id | int | 車次ID |
| station_id | int | 站點ID |
| order | int | 站點順序 |
訂單
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 訂單ID |
| user_id | int | 訂單創建者ID |
| train_id | int | 車次ID |
| train_date | date | 車次出發日期 |
| starting_station_id | int | 出發站ID |
| terminal_station_id | int | 到達站ID |
| price | int | 總金額(分) |
| is_paid | int | 是否已支付 |
| paid_time | datetime | 支付時間 |
| created_at | datetime | 創建時間 |
訂單詳情
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 訂單詳情ID |
| order_id | int | 訂單ID |
| passenger_name | int | 乘客姓名 |
| passenger_id_type | int | 乘客證件類型 |
| passenger_id_number | varchar | 乘客身份證號 |
| passenger_type | int | 乘客類型 |
| seat_type | int | 座位類型 |
| carriage_number | int | 車廂號 |
| seat_number | int | 座位號(排) |
| seat_location | char | 座位位置(ABCDEF) |
車票信息
| 屬性名 | 類型 | 注釋 |
|---|---|---|
| id | int | 車票ID |
| train_id | int | 車次ID |
| starting_station_name | varchar | 出發站名稱 |
| terminal_station_name | varchar | 到達站名稱 |
| starting_time | datetime | 出發日期時間 |
| seat_type | int | 座位類型 |
| carriage_number | int | 車廂號 |
| seat_number | int | 座位號(排) |
概念原型
概念是人對能代表某種事物或發展過程的特點及意義所形成的思維結論。概念原型是一種虛擬的、理想化的軟件產品形式。一般來說,概念原型=用例+數據模型。
本例中的用例主要包括了針對未注冊用戶的用例和注冊用戶的用例。用例包括與用戶信息相關的用例如注冊、登錄。和與車票相關的如購買車票。未注冊用戶在注冊后成為已注冊用戶,已注冊用戶在登錄后可以使用購票系統,查詢並購買車票。購買成功后產生訂單,生成車票。數據模型上文已經定義。
總結
本文結合一個類似12306的購票系統軟件,對其部分功能模塊,按用例分析、業務領域建模、數據模型設計等步驟進行分析設計,體會了一個軟件從需求分析到概念原型的整體流程。
