1. 程式人生 > 其它 >面向物件程式設計-第四單元部落格

面向物件程式設計-第四單元部落格

OO第四單元作業總結

本單元架構設計

本單元的作業架構,是基於課程組提供的需要實現的介面進行構建的。

第一次作業的架構,比較簡單,但是奠定了基礎。主幹就是實現UmlInterfaceMyUmlIntreface,完成分析輸入資料構建模型以及頂層應答查詢的功能。而執行應答部分則是由各個“包裝類”組成,即以官方包中的元素UmlClassUmlInterface等元素為屬性而非直接繼承,這樣可以新添很多功能,又可以避免繼承帶來的難以察覺的錯誤。在呼叫這些元素的基本資訊時,則可以通過多加一層簡單的轉發中介來實現。具體實現可參考如下:

public class MyUmlClass {
    UmlClass myClass;
    
    public MyUmlClass(/*...*/) {
        //...
    }//initialize myClass
    
    public String getId() {
        return myClass.getId();
    }
    
    //...
}

而在這些包裝類中,我將如了很多新的方法和容器,用來處理圖的儲存分析,比如xxxNamtToId,用來在輸入時儲存名字到Id列表的對映關係,從而方便對重名的判斷,對重名元素的尋找,等等。又如AssociatedClass,拋棄Association而直接連結到對端的類或介面,簡化判斷流程,增加可讀性。在這些設計下,第一次作業架構大概如此。

第二次作業的架構,相較於第一次實質沒有變化,仍然是以一個類為主幹(只不過改名了),但是由於UML邏輯上要求三種圖分開,加上官方包總介面UmlGeneralInterface其實是繼承了三個邏輯上分好類的介面UmlClassModelInteractionUmlCollaborationInteraction

UmlStateChartInteraction。參照這個思路,我也選擇將MyUmlGeneralInterface含有為三個類MyUmlClassModelInteractionMyUmlCollaborationInteractionMyUmlStateChartInteraction的例項(此處可以採用單例模式,但我沒有),然後由MyUmlGeneralInterface呼叫MyUmlClassModelInteractionMyUmlCollaborationInteractionMyUmlStateChartInteraction的方法來進行分析。如圖

這樣既使得結構清晰,分工明確,同時還能避免程式碼聚集,類程式碼超過500行而引發Checkstyle錯誤。而原來的MyUmlInterface

對各個元素的管理則分別交給三者來管理。

第三次作業的架構,則只是在第二次的基礎上添加了一個UmlStandardPreCheck介面用來提前檢測一些Uml錯誤。同樣,類似於第二次,我只需新增一個MyUmlStandardPreCheck類來實現它的功能即可。但是考慮到效能,我選擇讓第二次作業的三個新增類與它互相交流,由MyUmlStandardPreCheck來呼叫他們,而具體分析查詢由那三個類來完成,在交流的同時也減輕耦合程度。

四個單元中架構設計及OO方法理解的演進

在本學期的四個單元——求導,多執行緒電梯,JML,UML中,架構設計的重要性始終被強調。的確,如果架構沒設計好,最直觀的影響就是很容易重構,在一次又一次重構中痛苦掙扎。因此好的架構是必要的。

在第一單元作業中,我進行了一次比較徹底的重構,也就是從第一次作業到第二次作業,由於突然多出了可能的巢狀和三角函式,求導瞬間變得複雜,因而不得不改變之前較大規模的正則解析,而是改成遞迴和小正則解析結合的方式,按照多項式的邏輯分層分別歸屬功能。本想著第三次作業應該不用重構了,也對可能到來的錯誤檢查有了一定的心理準備,但是直到第三次作業真正開始分析的時候,才發現改動仍然不小,需要穿插在結構各處修修補補改改,而沒有任何的預留空位,這就導致寫完後我自己也不想看我自己的程式碼,最終還導致了互測bug(強測沒錯導致進錯互測屋,被狠狠地捅了)。本單元最大的教訓便是紙上談兵終不如敲上三兩行逼迫理解。但是怎麼樣讓真正的理論設計分析和寫程式碼逼迫推演理解結合,可能仍然需要考慮。

在第二單元作業中,由於第一單元作業吃虧不少,吃一塹長一智,我果斷選擇自己先思考一個合理的可以用三次作業的架構。查詢前輩架構介紹,與他人不斷討論細節,無所不用其極。最終我選擇的是分散式排程,並沿用了三次作業。但老實說,越往後仍然還是越暴露出架構設計的另一方面問題,一開始應對單、同類型多電梯還可以比較好地解決,而且簡單地往上相容不同型別的電梯迭代起來也很快,只需要改集中排程器分配原則和增加電梯的開關門判斷即可,但是一旦牽扯到效能,排程就變得非常難以協調,容易顧此失彼。一方面,排程器需要儘量動態排程,但是動態排程本身就很難設計,需要有所捨棄,而選擇一個可以量化的目標函式來衡量效率,和多執行緒攪在一起非常的麻煩;另一方面,電梯上下人需要處理多個快取區的問題,非常的麻煩。因而這是典型的架構沒能很好地適配效能要求,儘管在迭代擴充套件方面還是有可為的。這算是我第二單元的教訓。

第三單元作業,應該是最簡單的一個單元作業,按照JML規格走,小心不出錯,鑽研一下幾個複雜的演算法就差不多了。因此架構設計大概沒什麼可說的。但是這個單元啟示我們不侷限於OO的一個特點,就是形式化描述的功用。相較於虛擬碼,形式化語言並不那麼涉及細節,而是更概括,更具指導性;相較於自然語言它又更加精確,更數學化,但是對使用者從表意方面要求也更高,一旦表意有些許差池就會引發很大的誤解。因而對OO這種動不動程式碼量就比較大的程式設計方面,形式化語言算是一個很有力的工具,具有一定的概括性,又能具體到方法屬性層面,但是要小心使用,符合規範。

第四單元作業其實類似於第三次作業,介紹了另一種規範語言——UML。在該單元作業中,我對架構設計其實已經有一定的經驗了,能夠做到拿到指導書先想一想怎麼構造,減少改動,雖然有些時候還是會出現一些比較細節方面的,比如突然需要將幾個屬性整合出一個類單獨管理,才臨時想起新增。其他的不多說,上面也說過了,總之在這個單元,我對我的架構設計大概比較滿意,算是付諸實現了一次自己想的架構設計的一般方法。

總結自己在四個單元中測試理解與實踐的演進

對我來說,在四個單元中,測試的重要性都不小,對於發現潛在的bug十分有效,特別是剛完成程式碼時完全不知道程式碼能夠正常工作到什麼程度。但是具體而言,我對測試的理解的確逐步演進了,對於如何進行測試也有了一定的心得。

在第一單元求導關,剛跨入OO大門,我完全沒有寫測評機,靠的是一些人為編造的有特點的算式來進行評測。缺點顯而易見,覆蓋面較為狹窄,綜合多項特點測試比較薄弱。但是,在這個單元,我認為體現的最多的還不是自動化測試尋找bug方面的能力,而是在效能分析方面的能力。因為如果想不到某種情況的資料,那麼大概率寫測評機也覆蓋不到,僅僅可能是能夠隨機碰出一些幸運資料罷了。但是自動化測試能夠產生大量資料的優點,卻可以彌補人造資料規模小的問題,可以通過大量資料測評比較結果(本單元是結果字串長度),綜合評分(效能分),從而幫助尋找一些拉低效能的資料特點,對症下藥。(當然,很多是我從研討課那感覺到的,因為說到底我並沒有進行自動化測試)。

開始第二單元作業後,由於有了第一單元測試的誘惑,以及第二單元確實需要一定的手段來代替肉眼判斷答案正確性。因此我動手寫了一份自動測評機,完全由C和bat指令碼完成,資料互動採用重定向利用檔案進行,通過C分析輸入檔案來判斷電梯動作是否合法,乘客是否到達目的地等。其實怎麼說,自己寫了才發現,自動測評機其實就是一個按照一定規律自動產生資料,然後對結果字串進行比對的程式,只不過也需要一定的設計來儘量通用化,比如結果比對程式我一直用到第四單元乃至os,只是略加修改。本單元的自動生成資料也有一點麻煩,需要定時投喂,因此我“擅自”挪用了討論區某位dl的定時投喂程式,利用管道來投喂。總的來說,這一單元大大增進了我對測試的認識,測試程式本身也需要一定的架構,最好是介面式的呼叫,定時投喂程式和字串比較就是最好的例子。此外,利用指令碼來控制作業系統輔助測試,感覺比python調庫要簡單。

第三單元作業,測試的壓力反而沒有第二次大。但是第三次完全引入了對拍的概念。第二單元其實也有對拍,但主要是對時間,但第三單元則難以得到標準答案,因而決定與他人合作,利用隨機自動生成資料,將結果進行字串比對,從而找到容易出問題的地方,再檢查為何出現分歧。其他方面倒也沒有很大的改變。

第四單元作業,和架構設計一樣,大概也算是對測試能力的一次收官檢驗。然而我在第四單元錯的也不少,儘管也進行了測試,但是測試力度明顯不如前幾次,可能是因為臨近烤漆,沒有太大的動力,而且資料相對更難造出。但是如果真的要做測試,本單元應該對拍和時間相結合,自動測試與手動構造相結合,因為既有對UML的理解不知是否正確的疑惑,又有圖計算對複雜度的壓力,因而相對覆蓋較為全面。

總結自己的課程收穫

經過一個學期的OO課程的鍛鍊(霧),我覺得OO對於設計這一門博大精深的藝術還是沒有完全弄明白,只是開了一個頭,畢竟靠精湛的設計建模吃飯的人不在多數,絕不可能這麼簡單。反覆的區域性重構,錯綜複雜的交錯關係,讓人糾結不已的加介面加類,都是沒有提前設計的真實後效,也是我常常遇到的問題。不該還好,現在我還是通過OO意識到了這個問題,提前設計這一提醒是OO課給我帶來的一大收穫,寫程式碼絕不是直接莽就可以了。

此外,我也學到一些Java的知識,雖然不算很多。其中之一就是多執行緒的使用,算是完整學到的一個大塊的知識點了,也結合了作業系統學到的知識,對計算機的工作原理進行了瞭解。

還有一點可能不完全相關的感想,那就是由OO而對一些前後端工程設計也有了一點興趣。無論是OO評測網站的搭建,還是後端測評機的執行,抑或是gitlab的協調使用,大概讓我感受到什麼是一項系統工程,怎樣將可能用到的東西都用技術化歸下來,這一點算是讓我對黑框框以外的程式設計設計有了興趣,但將會是什麼可能還需要我進一步去發現。

立足於自己的體會給課程提三個具體改進建議

1.希望課程組能夠參考一下大部分同學們的課表,不要讓主要寫oo的時間與太多同學的課程時間重疊,導致時間比較緊張。

2.希望測評形式更加開放,在功能上滿足要求,實現方式更多樣化,畢竟同學們總是與課程組爭論某些細節上的正確性比較麻煩(當然只是建議,畢竟這樣測評將會變得不方便精確賦分,具體形式完全還需要商討)

3.研討課可以與實驗課結合更緊密,而不是作為同一時間交替的互不相干的課程,比如研討課也可以介紹實驗課的相關細節,特別是實驗課是拓展環節時。

4.雖然知道OO不是Java課,但是許多Java相關的知識還是非常有必要的,感覺還是讓同學們在大二多學一點知識比較好