結合 uml 所學和 Javafx 從建模到實現一個子功能模組 —— 日程管理。新手上路,類圖到程式碼實現的過程還是很曲折但所幸收穫頗豐,記錄一下學習心得。
日程功能模組
最後成果
JAVAFX裡面沒有封裝日曆控制元件,找了些專案原始碼做參照肝了一個,不過為了簡化分析的過程,不會詳細寫其中業務邏輯。
總的來說,從建模帶程式碼實現的功能完成了90%,日程列表和日曆的通訊沒寫,預期效果是如果有新增的日程,日曆上相應的日曆塊會有 marked 的標記。這一塊按照我的想法寫程式碼會變得很亂,也是建模過程中沒有認真考慮的點。
建模過程
需求
日程主要是幫助使用者檢視和管理日常事務,使用者可以記錄待辦事件並且設定提醒時間,有助於管理時間和提高工作效率。
而作為成績管理系統學生介面的一個子功能模組,除了幫助學生管理課程和學習任務,它還需要能自動匯入課程考試資訊,便於學生規劃學習進度。
用例圖及主要用例描述
- 用例圖
從需求分離出物件為學生。把所有有意義的動賓短語先列出來【檢視日常事務】,【管理日常事務】,【記錄待辦事件】,【設定提醒時間】,【自動匯入課程考試資訊】。這裡是因為需求比較直觀簡單,一般還需要根據語義找隱藏的功能需求。
進一步分析用例之間的關係,【管理日程事務】即對日程做刪改,應該是在選定具體的事務後。【記錄待辦事件】即新建日程,包括【設定提醒時間】等資訊設定。【自動匯入課程資訊】應該不是由學生完成的,學生只能檢視,所以還有參與者 —— 考試管理系統。
畫出用例圖如下
心得:在畫用例圖時並沒有花太多時間打磨,構建的快也修改的快。從需求快速提取用例,在寫用例描述的時候還會再倒回來修改的
參考老師發的資料,從用例圖如何到類圖,觀點不一。有從活動圖 ——> 類圖以及從詳細的用例描述中抽象出類圖,兩種都參考嘗試了一下。
- 用例描述
用例編號 | S1.1 |
用例名稱 | 檢視日程詳細資訊 |
參與者 | 學生 |
觸發條件 | 點選列表中具體的一項日程 |
前置條件 | 學生已經登入,並且在日程介面 |
後置條件 | 顯示目標日程的詳細資訊 |
正常流程 | 1. 點選列表中目標日程,顯示日程資訊 |
擴充套件流程 | 1. 編輯目標日程,修改事件資訊 2. 刪除目標日程 |
特殊要求 | 無 |
用例編號 | S1.2 |
用例名稱 | 新增日程 |
參與者 | 學生 |
觸發條件 | 點選“新增日程”按鈕 |
前置條件 | 學生已經登入,並且在日程介面 |
後置條件 | 新增了新的日程到日曆,對應日期格顯示 marked |
正常流程 | 1. 點選“新增日程”按鈕,開啟日程建立皮膚 2. 填寫事件,設定時間段 3. 選擇是否設定提醒時間 4. 點選“提交”按鈕 |
擴充套件流程 | 1. 取消建立日程 |
特殊要求 | 無 |
用例編號 | S1.3 |
用例名稱 | 檢視考試安排 |
參與者 | 學生 |
觸發條件 | 點選“檢視考試安排”按鈕 |
前置條件 | 學生已經登入,並且在日程介面 |
後置條件 | 顯示顯示本學期所有考試安排 |
正常流程 | 1. 點選“檢視考試安排”按鈕,顯示考試安排皮膚 |
擴充套件流程 | 1. 新增提醒 |
特殊要求 | 無 |
活動圖
較為傾向於從用例描述中抽象出類,老師發的資料中也寫到,用例描述佔據著皇后的位置,而三王一後中沒有出現活動圖。我在寫完用例描述後對程式也已經有了輪廓。
類圖 <重中之重>
學習部落格【深入淺出UML類圖】
從用例描述中,抽象出所有的類。我們先提取實體類,有日程類,以及填充日曆的日期格類。邊界類這裡就是介面類,有日程主介面類,新增日程的介面類,兩個介面類分別都有控制類實現相關的業務邏輯。介面類裡面的部件主要是日曆類,日程列表類,考試列表類。
先把實體類的屬性寫好,日程類我們很容易可以知道,有日程名稱,開始和截止時間,提醒時間。使用者在填寫事件時,可能還有一些額外的資訊需要提醒自己,那麼就新增一個事件備註屬性。
日期格類應該包含的是當前格子表示的日期,因為我們還可以直接看到這個格子是否有日程,應該是抽象為一個狀態。這裡我預備用布林型 isMarked 來表示。(當時寫的時候還加了Mark屬性,作為如果存在日程的標記,多餘了。
然後進一步思考類之間的關係,先看聚合關係,ScheduleList 和 ExamList 都是由 Schedule 聚合而來,但 ExamList 屬於特殊的日程,它在這裡只能檢視不能修改。日期格和日曆Calendar也是聚合關係,我的想法是按月顯示,那關係就是一個日曆中由35個日期格。
考試列表,日程列表和日曆都屬於主介面的部件,包括主介面在內的業務邏輯都由 ScheduleController 來處理。最後得到類圖如下
程式碼實現
用starUML的正向工程工具根據上面畫好的類圖匯出所有的程式碼。然後用 sceneBuilder 開始頁面佈局。
主介面我直接用的做平時成績管理系統的介面稍加改動,已經有基本佈局和css渲染。新增新日程介面根據用例描述,就是有對日程基本資訊的編輯,然後確認取消按鍵。
下面是靜態初始介面,還沒有實現任何功能只是個UI。
編寫介面類,主介面繼承 Application 類。新增日程是由主介面按鈕觸發彈出的,暫時不寫。
開始編寫程式碼,正向工程匯入後已經有了屬性,實體類只需要編寫setter和getter方法以及構造器
日曆是用GirdPane寫的,每一個日期格都繼承AnchorPane,便於在內部進行佈局
兩個 List 部件類
ScheduleList 有 Schedule 的聚合,初始化我們從資料庫匯入資料(因為用到資料庫的地方較少,就不分離出來的(絕不是懶:/,刪除和修改的方法這裡暫時不寫。
ExamList 直接從資料庫初始化資料之後不再會變化,所以它包含的應該是 final static 的 Schedule 陣列,與上面類似就已經完成了。
日曆類 Calendar 和兩個控制元件按鈕的行為
日曆類其中涉及細節較多,這裡把它當作已經封裝好的日曆控制元件FXCalendar。根據類圖,我們要完成的時在按上月和下月的按鈕時,日曆要做出變化。
兩個按鈕觸發的行為實現程式碼
可以看到上面呼叫了 changeCalendar() 方法來實現日曆的變化,下面是 changeCalendar() 程式碼實現
兩個介面的互動和新增日程介面完善
在主介面按下新增日程按鍵是觸發新增日程介面資訊,每次都會產生一個新的介面,一個主介面可以有多個新增日程介面。
我們從類圖中得知,主要有填入事件資訊,是否需要提醒,確認新增和取消操作。(這裡在編寫的時候就發現,類圖的不足之處,開啟提醒應該是由控制類來完成。
填入事件資訊是在介面中完成的
確認新增事件 getNewScheduleButton()
確認和取消都會觸發視窗的關閉,而視窗是在主介面控制類生成的,在這裡需要獲取當前按鈕所在視窗來關閉
是否提醒
到這裡,新增日程介面和控制類都完成了
最後要做的是刪除選中日程和檢視選中日程deleteSchedule(in schedule:Schedule)
,showScheduleDetail(schedule:Schedule)
這裡有個十分迷惑的小bug,雖然處理了。但還是不知道為什麼,希望有大佬解惑
ClickedID
是在監聽日程列表中被滑鼠選中的事件編號。
檢視選中日程時,生成對話方塊來提示選中日程的所有細節。
list 做出的相應操作
總結心得
從類圖到程式碼仍舊花了不少時間在不斷思考如何組織和實現,一度想不管結構全部累在一起,這裡類圖起了一個很大的規範作用。它在設計階段,規範好整個框架,讓我先對業務流程有了大致的輪廓。如果感覺有錯誤,可以在類圖階段就修改,而不是等到實現時修改程式碼,減小犯錯成本。
其實程式碼實現後,我還返回去修改了類圖
一個是命名規範,當時設計類圖命名比較草率,導致在程式碼累積下來後不能見名知意,所以重構了程式碼並且修改類圖中類和方法的命名;
第二個是方法的引數和返回值,類圖設計時我對每個方法都寫了形參和返回值,但具體實現時大概率會發生變化,比如刪除日程那隻需要傳遞日程ID,而不是把Schedule傳過去;
類圖上的時間安排
其出現兩個問題,其一是在根據類圖實現程式碼時發現有些細節沒有考慮到,需要在實現時再花時間來設計。其二是根據類圖的設計無從下手,有我Java功底尚淺的原因,但也可能是因為設計的不合理。
類圖設計的快,可能會有細節被忽略;類圖設計的慢,不斷打磨精細,如果後續要修改,可能因為投入了較多的時間成本不想修改。
這次從建模到實現,收穫很大,真的感受到一個好的建模可以讓整個功能實現更加高效。我的建模可能還很不規範,之後還是多實踐和總結!