? 隨著第四單元UML第二次作業的結束,本學期的OO學習也宣告結束了(但還得寫博客),下面就對本單元和本次作業做一個總結。
第四單元兩次作業的架構設計
? 本單元是對UML的結構進行解析,第一次作業是對UML類圖的解析,主要的難度是UML各種元素之間較為復雜的從屬以及其他關系。我的類圖設計如下:
? 我自己創建了ClassModel類來統領兩個子類ClassClass和InterfaceClass,分別代表類和接口,其中實現了添加、儲存、處理類和接口的各種下設參數的方法和變量,讓類和接口的類繼承同一個父類非常重要,因為類和接口有很多相似的地方,再進行輸入處理時也有很多不易區分也不用區分是類還是接口的情況,所以這樣處理極大地方便了程序對這兩個類地儲存和管理。對于方法我創建了OperationClass來添加儲存和管理方法的各種屬性,然后ClassClass和InterfaceClass就只用儲存和管理OperationClass即可,對于其他的屬性由于沒有更多的層次,所以就直接使用接口提供的UML類來進行儲存和管理即可。
? 在進行輸入處理的過程中,由于其結構的層次性,應該將各種屬性的UML_ELEMENT分批來處理,我首先識別處理了UML_CLASS,UML_INTERFACE,UML_OPERATION, UML_ASSSOCIATION_END, 之后再將剩余的其他屬性進行識別處理,這樣再識別時就可以直接建立起各種元素之間的邏輯結構。在儲存中我主要使用了HashMap結構,進行從id到類,從name到類等的映射。
? 對于各種指令的處理方法,有難度的主要分為兩類,一個是需要考慮關聯關系的指令,對它的處理比較直接,在每個ClassModel類中均有其關聯的類或接口的引用,直接訪問即可得到所需要的信息。更復雜的是需要考慮繼承關系和實現關系的指令,對于繼承關系需要考慮多重的繼承,所以我們使用遞歸來處理,其中Information類就是創建用來在遞歸時在類與類、接口與接口之間傳遞信息的,我們任意從某一個類開始,逐層向上,利用遞歸來實現與繼承和實現有關信息的統計,儲存在information里,再逐層向下傳遞。一次遞歸結束后,再找一個沒有經歷過遞歸的類開始遞歸,直到所有地類和接口都經歷過一次遞歸為止。
? 第二次作業在第一次作業的基礎上增加了狀態圖和順序圖的解析,以及對類圖合法性的判斷。在這里要感謝老師和助教們手下留情,最后一次作業的難度要比我想象中簡單很多,特別是最后加了很多數據限制以后,整個問題變得很簡單。
? 整體架構如上,對于順序圖建立一個Interation類來儲存和管理對應的信息,對于狀態圖類建立一個StateMachine類來儲存和管理對應的信息,相比類圖簡單很多,想法也很自然。
? 那么本次的難點主要在于類圖合法性的檢查,類似對類圖的處理,我們按照層次順序依次識別和建立各元素之間的關系,但不需要用到其他的類,只需要根據要求按照id和name建立關系即可。第一個檢查較為簡單,只需要遍歷查看attribute和Association End有沒有重復即可。對于第二三個檢查,先將類繼承,類實現接口,接口繼承形成一張id為結點的有向圖,那么第二個檢查就是在有向圖中找圈,具體地可以使用強連通分量等算法,但由于這里點比較少,所以我們對每個點跑一遍較為樸素的每個點只可到達一次的dfs即可,若可以回到本點,則將該點加入異常結果中。對于第三個檢查,在第二個檢查檢查已經無圈的情況下,找任意兩點之間有沒有多于一條路經可以到達的情況,若有,那么起始的點就重復繼承,具體地同樣也是對每個點使用較為樸素地dfs,若在dfs中訪問了某個點兩次,那么這個起始點就加入到異常結果中。
四個單元中架構設計及OO方法理解的演進
? 在最開始的第一個單元,明顯地自己仍然是面向過程的思維,當時應用熟練的只是Java的語法,而不是Java面向對象的思想,第一單元的第一次作業好像就只使用了一個類來完成了所有的事情,在第二次作業中讓自己多分出了幾個類,但仍然不夠靈活和自然,更多的是為了劃分而劃分。
? 到了第二個單元,有了前面一個單元三次作業的練習,自己有所進步,開始從面向對象的思路開始思考,自己所處理的問題有哪些對象可以使用,他們之間又有哪些關系,但第二單元的重點我認為是在線程的設計和處理上,根據線程的理論,類的劃分也就比較自然,但也是讓我感受到了面向對象的便利。
? 在第三單元之中,是根據JML來寫代碼,更多地是在助教們設計好的架構下來補充代碼,雖然沒有太多的自己的設計,但這也是一個學習的過程。到了第四單元,對面向對象的理解應該已經有了比較高的進步了,可以從問題涉及的對象入手來分析問題,可以很自然地想到一個比較好的架構,并實現它。
四個單元中測試理解與實踐的演進
? 第一個單元最開始自己測試的方法還是比較原始,主要是自己手動構造一些邊際數據來進行測試,肉眼來看結果的正確性。在后面由于表達式難度的加大,肉眼很難分辨正確與否,所以我和幾位同學一起用python來對拍,答案相同則認為正確。
? 第二個單元是多線程,在第一次作業中我吃了手動輸入的虧,由于自己手動輸入的速度太慢,所以基本上不會造成線程安全問題,所以隱藏了很多問題。所以之后我使用了bash批處理和Python來實現了自動生成輸入,自動按時輸入和檢查輸出的合法性,大大加快了檢查效率,也使得在互測中方便了很多。
? 第三個單元中引入了JML,開始我還是使用自動數據生成和多個程序對拍的方法,之后也嘗試了利用JML自動生成數據并自動測試,但總有一些bug,所以最后嘗試使用了樸素的Junit單元測試,還是比較方便的。
? 第四個單元是UML的解析,由于數據不易生成,所以測試主要是利用starUML來生成一些邊界性的數據進行測試,也由于UML的結構相對比較固定,所以還較為方便。
? 總的來說,測試是程序設計過程中一個非常重要的環節。經過四個單元,我認為測試最好的方法就是使用Junit對沒個小單元進行功能測試,但實踐中由于自己類和方法的設計問題以及時間問題,比較難以實施。同時自動化測試尤其是壓力測試對測試也是一個必須的過程。
課程收獲
? 最大的收獲當然是面向程序的設計思想,面向對象提供給了我們一個程序設計的高效思路,使得我們的程序層次化架構更加清晰,代碼重用更加便利,加快了程序設計速度,提高了程序設計效率。豐富了我之前單一的面向過程的變成思想,展現了編程更多的可能性。
? 在這個過程中自己的代碼能力也有了很大的提升,也是第一次擁有了工程性的想法和思維。還學習到了多線程的程序設計,了解了Java較為底層的實現,對Java有了更深的理解。也學習到了規格化的設計,JML語言,UML建模語言等。
? 另外,在這個過程中,自己分析問題的能力,測試的能力,debug的能力也有很大的提升,也是對自己的抗壓能力,面對較大規模編碼的能力的提升。
課程改進建議
- 希望改進一下課上測試的形式和方法,至少找時間講解一下課上的題目或給出參考性答案,否則我們在課上測試中得到的收獲很少。
- JML部分課程組或許可以再進行一些探索和優化,刪去一些難以實現的部分,增添一些更為實際的要求。
- 希望可以改進一下課堂使用的ppt,個人認為課堂ppt的邏輯普遍有一些混亂,結構不是非常的清晰,常常有一些重復等。另外,截圖也經常看不清楚。