雖然對OO這門課的大名早有耳聞,也作好了心理準備,但通過開學來這四周的磨練,不由讓我懷念起了去年計組的快樂時光(誤)。即便是P7這種公認的玄學領域指導書,與目前OO的任何一份指導書相比也難分伯仲;即便是課上測試前一天開強測,也不會讓我像這幾周的週一週二那樣熬到凌晨兩三點。做爲一位非酋玩家,分到三次大佬做業,直到如今分數還基本處於零和狀態,懷着這樣的心情寫下這篇博客。python
能夠看到總體來看第一次做業的設計還算合理,可是部分方法複雜度較高,具體分析上面標紅的方法發現這些這些方法都在經過正則表達式處理輸入,因爲該程序自己計算難度不大,主要的工做在處理輸入上,再加上正則表達式處理輸入自己須要不少行,致使了這些方法複雜性較高,但整體上講此次做業基本實現了高內聚低耦合的目標,層次結構比較清晰。linux
在第一次做業中,讓我印象最深的BUG就屬正則表達式溢出了。因爲是臨時學習的正則表達式,對正則表達式內部的處理機制並不熟悉,再加上自行構造過長的數據難度較大,前期寫代碼的時候沒有注意這個問題,直到提交前一天晚上睡覺前,用本身寫的python腳本生成了一個合格的(20x50)多項式把本身程序炸了才意識到問題的嚴峻性。接下來就是一夜的極限操做,通過在網上搜索解決方案,發現是由於本身在正則表達式中使用了太多的嵌套,我本來使用了一個超長的正則表達式,把多項式匹配單項式匹配數字格式等這些一次性解決。這樣的正則表達式在讀到過長的輸入,甚至是符合指導書要求的20x50的多項式時就會發生正則表達式溢出錯誤。最終我經過把匹配工做分爲兩部分,先匹配多項式兩邊的大括號,提取出每一個多項式再匹配多項式中的單項式,從而解決了緩衝區溢出問題,也成功達成了OO第一次做業就熬到半夜兩點的成就。正則表達式
本覺得改完這個bug就萬事大吉了,就沒再管這個de過bug的代碼,次日也用了所有的公測,可是事情並不像我想象的這麼簡單。分配測試任務後幾個小時一個紅方塊就出如今了個人分支樹上,一看測試樣例發現是沒有處理多項式前面的負號。回頭看本身寫的代碼,原來是在半夜debug的過程當中分部處理了多項式,因爲第一個多項式的格式與其餘多項式不一樣(第一個多項式前面能夠沒有符號),就把第一個多項式單獨提出來處理。恰恰就在這個地方偷了個懶直接把處理後面多項式部分的代碼拷貝了過來,又恰恰沒有拷貝處理符號的部分,直接致使第一個多項式的符號默認爲正。這也給我提了個醒,在debug的過程當中可能會產生更多的bug。編程
第一次互評,就收到了某巨佬的做業(windows下pdf右鍵刪除信息有漏洞,雖然在windows下沒法看到信息,可是在linux下原形畢露,後兩次做業你們注意到後就沒有再出現相似問題),因爲這份做業使用有限狀態機來匹配格式,用哈希表來記錄,在諮詢了一樣使用有限狀態機和哈希表的室友後成功虎口拔牙發現了一個小bug。若是輸入的某一個單項式係數爲0,在哈希表上不會有顯式的變化。能夠在後面再輸入一個指數相同的多項式也不會報格式錯誤。這也是使用哈希表的同窗們都要面對的問題,能夠經過對每個指數增長訪問位來解決該問題。windows
這個程序也是我使用Java寫的第一個算得上規模的程序,在此次做業中使用到了Java正則表達式以及try/catch語句塊,經過啃《Thinking in JAVA》我在這兩個方面收穫頗豐。經過使用catch(Throwable t)實現了寫出永遠也不會crash的程序,也基本掌握了使用簡短的正則表達式來檢查輸入格式並從輸入中提取須要的信息,相比那個狀態極多的有限狀態機節省了很多時間精力。設計模式
本次做業在設計過程當中,我但願可以徹底模擬真實電梯的運行狀態,但同時又受到課件上提供的設計模式的影響,最終綜合起來就獲得了上面UML圖所示的這個龐然大物,從我設計的角度來看,各個類的分佈基本均衡,每一個類各司其職,可是其中有至關多的冗餘部分,並無起到實際做用,並且我爲了讓每一個類管理好本身的屬性,把對象處處傳遞,在UML圖像上就展示出了十分複雜的關係網絡,總體耦合度較高,可是每一個類的內聚性還算合理,體現出我對面向對象的理解還不透徹,刻板地認爲模擬真實狀況就算是面向對象,並且過多的冗餘代碼致使這個不怎麼複雜的程序被我寫得看起來很複雜。網絡
在此次做業因爲實現的功能較爲簡單,在我編寫的過程當中實際上並無遇到多少bug,更多的時間是在應對頻繁變化的指導書(再次吐槽指導書...)。此次做業我寫的代碼很是臃腫,有不少冗餘的部分,雖然說表面上又臭又長,但功能上講我我的認爲是沒有問題的。以後的公測以及互測階段的結果也證實了這一點。多線程
而此次互測我估計又是拿到一位大佬的代碼,用我構造的各類刁鑽數據測試也沒有出現任何問題,代碼寫的也很簡潔明瞭,不像我寫的那麼臃腫,我認真學習了這位大佬的代碼,發現從邏輯上確實是無懈可擊,我也把其中一些思想用到了我下一次的做業中。可是估計是偷懶這個程序對於無效請求沒有任何輸出,錯誤輸入只輸出ERROR也不輸出提示,報了個incomplete,算是實現了0的突破/(ㄒoㄒ)/~~。學習
此次做業涉及到的類衆多,我也是通過了長時間的構思纔開始寫這個程序,可是並無將構思過程當中的想法記錄下來,分析整理。最終因爲自身的邏輯條理確實不是很清晰,對面向對象編程也不是很熟練,把多個想法混合實如今了一塊兒,寫了一堆臃腫醜陋的代碼,其中有面向過程的、面向對象的、還有四不像的,好比在樓層類裏增長了電梯間,但願經過樓層類的電梯間來調用電梯,也就是經過調度器調度樓層再調度電梯,後來發現太麻煩又改爲了直接調用電梯,形成了電梯間這一引用實際上沒什麼用,此次的代碼中還有至關多相似的問題,從上面UML圖的複雜度以及程序的複雜度分析結果也能夠看出這一點。這也讓我下定決心在下次做業中大刀闊斧刪掉那些沒有用的東西,同時也讓我注意到了提早作好規劃的重要性。測試
因爲此次做業須要繼承上一次做業的部分類,因此看上去UML圖變得更加複雜了,但實際上並不是如此。本次做業在上次做業的基礎上進行了大幅度的簡化,可是因爲調度類須要實現的功能太多有一些不均衡。但這些改進也帶來了另外一些問題,好比我把做業2中樓層和電梯中的按鈕所有轉移到了新的調度器內部,雖然減小了運行過程當中調度器與樓層和電梯的交互,下降了耦合度,可是這也形成了類的內聚性的下降。同時在此次做業中出現了一個god類ALS_Scheduler,這個類無所不知無所不曉,能夠隨意改變其餘類對象的屬性,這應該是在面向對象編程中極力避免的。
此次做業相比前兩次難度和複雜度明顯提高,直觀的表現就是如何捎帶這個問題指導書本身都說不清楚(第三次吐槽指導書...但願不會有第四次)。在最終經過Git上的問答基本解答了心中的疑惑以後,吸收上次做業經驗作了個規劃,並學習了互測階段拿到的那份做業,在第二次做業的結構上作了大規模的簡化。經過實現電梯和樓層按鈕,每次運行一層,並在調度器中實現主請求,等待請求隊列和捎帶請求隊列,獲得了一個較爲令我滿意的版本。然而問題來了,使用主請求以及隊列有一個不可避免的問題,就是一層多個捎帶指令的輸出順序混亂。看似是一個小bug但實際改起來卻傷筋動骨,若是單獨執行主請求勢必會致使主請求與捎帶請求的順序難以嚴格按照輸入順序,可是若是拋棄主請求模式,又會致使當下整個調度機制的徹底癱瘓。因此最終只得將主請求降級爲捎帶請求加入捎帶隊列,但保留住請求的引用,並在給每一個請求增長序號在捎帶隊列中進行排序後執行。可是這個補丁打得彷彿是在拆東牆補西牆,de一個bug出一堆bug。究其緣由是結構的改變致使了不少以前規劃中並無考慮到的問題,再加上代碼自己已經至關複雜,修改過程很容易出現紕漏。總而言之,仍是前期工做不足。只能用時間來彌補設計上的缺陷,最終經過熬夜爆肝,de完了全部bug,總體感受就像是在補丁上打補丁。我還吸收第一次做業的經驗,經行了完整的各項測試,確保沒有新的BUG出現。不過這個代碼改到最後可讀性已經變的很是差,我本身幾乎都看不懂(心疼一下互測階段拿到我程序的同窗)。
或許是不少同窗都遇到了我上面的這種問題,也或許是因爲個人運氣太背(面向運氣的編程對我不友好),在互測階段我拿到的這份代碼,雖然寫的比我簡潔一些,但一樣可讀性極差,幾乎是不知所云,在各個類之間跳來跳去,跳的我眼花繚亂。想從readme入手理個頭緒,發現readme中並無有關程序具體實現方法的描述,無奈只得用我收集的和自行構造的近60個通過精挑細選的幾乎是覆蓋的測試樣例轟炸了一輪,沒有出現任何問題,而後又經歷了讀代碼從入門到放棄的過程,最終第三次做業又以零和收場。
第三次做業能夠說是真正體現出了面向對象編程優點所在。前幾回做業也許能夠用面向過程的方法寫出來,可是此次真的很難想象不用面向對象的方法如何編寫。可是因爲我我的對面向對象的理解和掌握還存在不少問題,致使寫出來的代碼複雜度很高,維護困難,bug頻出。這也是在未來的做業中須要重點改進的。
從前三次做業結果來看,我本身的做業公測全過,三次被測人的公測也是全過,互測總共被找了一個bug,找到別人一個bug,找到別人一個輸出不完整,總分+1。我也意識到了我在發現程序bug的能力上確實存在缺陷。大部分狀況下都只能經過本身構造或是從同窗們那裏蒐集測試數據進行測試,在測試中發現bug,而後再打補丁式地修改,這種現象隨着做業難度的上升變得愈來愈廣泛,同時修改的難度也在不斷增大,debug帶來的新bug也愈來愈多。
在互測階段尋找對方的bug時,我也基本遵循着這一套路,用大量的測試數據進行狂轟濫炸,若是炸完沒有出現問題基本就表明這個代碼是真的沒有問題了,以後我也會抱着僥倖心理去看看readme,看能不能找出一些自相矛盾的地方(好比像第二次做業的互評),若是上面兩步都沒有問題(好比第一次和第三次),就基本能夠認定是大佬的做業無疑,就只能讀代碼,學習一下對方是怎麼寫的,同時看看有沒有邏輯上的漏洞,(好比第一次做業就發現了這樣的漏洞)。可是對於可讀性差的代碼,只能說讀懂對方的代碼比本身寫代碼還難,我表示直接棄坑(好比第三次做業),這也算是OO互評的一個bug吧,畢竟若是寫出來的代碼沒有可讀性,會使評測者無處下手,只能經過原始的狂轟濫炸來發現bug,大大增長了測試者的測試難度。
具體分析我前幾回的代碼,能夠發現最主要的問題在於把各個類之間的關係編制得過於複雜,這從第二次和第三次做業的UML圖上就能夠看出來,如何實現高內聚低耦合一直是個人一個老大難問題,須要對我目前程序的結構進行完全重構才能實現。在第四次課上我也進一步瞭解了什麼是面向對象以及怎樣才能寫出面向對象的程序,我也已經作好了構思,在寫多線程以前大刀闊斧整改我以前的程序。
最後盜一張圖做爲結語(逃...)