經歷了三次oo做業的洗禮,讓我對java語言的強大以及面向對象編程有了初步的理解(固然,我是小白)。本文接下來就將對本身這三次做業的代碼進行分析以及分享本身的心路歷程。java
針對前三次做業,我列出了這其中涉及到的主要的知識點:正則表達式
固然,還有最重要的仍是閱讀和理解指導書的能力,可以在較短的時間內準確無誤的理解指導書的意圖也是必需的能力之一。編程
程序類圖以下:數組
這是我第一個認真寫的java程序。因爲第一次做業比較簡單,因此用到的類也只有三個,類圖也很簡單。儘管並非純翻譯的c代碼,但自從看了不少大佬的代碼就愈發開始嫌棄起來。尤爲是輸入的檢測部分,多是腦抽了吧寫了個字符狀態機,這樣的後果是一個明明很是簡潔的程序看上去很是的臃腫,好處是它能夠遍歷幾乎全部的狀況。而後是主體部分,類的設計是源自老師的PPT,並且主體方法和其餘同窗的幾乎都差很少,因爲第一次做業較爲簡單,具體細節就再也不贅述。但此次做業也讓我對java有了較爲基礎的認識,對比c代碼和java代碼就能夠看出來,不少功能用c實現起來或許很難,但用java卻能夠在很短的代碼內寫出較爲高效的程序(也多是我對c的理解不夠吧);至於對面向對象的理解,此時還停留在朦朧的階段,認爲面向對象編程就是構造一些對象,而後經過對象來調用它們內部的方法。好比我第一次做業的main函數的內容是這樣的:數據結構
public static void main(String[] args) { Scanner scn = new Scanner(System.in); if (!scn.hasNextLine()) {System.out.println("ERROR"); System.out.print("#輸入不能爲空,請從新輸入"); scn.close(); return;} String str = scn.nextLine(); if (str.length() != 0) { str = str.replace(" ", ""); new ComputePoly(str); } else { System.out.println("ERROR"); System.out.println("#輸入不能爲空,請從新輸入"); } scn.close(); }
而ComputePoly()類是這樣構造的:框架
1 ComputePoly(String str) { 2 u = v = L = state = 0; 3 poly = new Poly[51]; 4 for (int i = 0; i < 51; i ++) poly[i] = new Poly(); 5 err = 0; cnt = 0; err1 = 0; 6 parseString(str); 7 compute(); 8 }
其實就是一層一層調用其餘對象。這是我對面向對象編程的一開始的理解。ide
程序類圖:函數
第二次做業要難一些,由於我花在指導書上的時間就差很少有接近一天,並且仍是在室友以及助教的幫助下才勉強看懂此次做業的需求。個人思路是在主類中新建一個Ctrol對象,而後在Ctrol的構造函數中調用其餘對象的方法(如上類圖所示)。此次做業和上次做業不同,由於合法的輸入很短,因此能夠直接使用正則表達式匹配而不用考慮爆棧問題。在程序的設計中,比較難或者比較模糊的一點是同質指令的判斷,我本身寫版本是這樣的(雖然是對的但很冗餘):測試
1 for (int i = 1; i < req.get_size(); i ++) { 2 r2 = req.get(i); 3 if (r1.issame(r2)) { 4 if (r1.get_kind() == 0) { 5 if (r2.get_tim() - r1.get_tim() <= 1 ||r2.get_tim() <= lift.get_all_tim() ) r2.set_ok(false); 6 } 7 else { 8 if (r1.get_tim() == r2.get_tim() || r2.get_tim() <= lift.get_all_tim()) r2.set_ok(false);// 9 } 10 11 } 12 }
後來在室友的提點下(暴露智商了),第三次做業改爲了這樣:spa
1 for (int i = 0; i < req.get_size(); i ++) 2 if (!solve[i] && re.issame(req.get(i)) && req.get(i).get_tim() <= lift.get_all_tim()) 3 {System.out.println("#SAME[" + toReq(req.get(i)) + "]"); solve[i] = true;}
即只須要一個判斷條件就足夠;
程序的主體框架和第一次做業相似(大概我對面向對象的理解還停留在原地吧),main函數內容以下:
1 public class Main { 2 3 public static void main(String[] args) { 4 new Ctrol(); 5 } 6 }
另外與第一次做業不一樣的是,這次做業的屬性都爲private類型(不考慮繼承),此外我還對全部屬性專門設置了set()方法和get()方法,可是後來又以爲此舉不妥:爲每一個屬性都設置了訪問方法,這樣和將這個屬性設置爲public有什麼區別呢?因此在矛盾的驅使下,我在第三次做業進行了稍微的改動:只留部分屬性與外界交換,其餘的屬性則保持其基本特徵不變。
程序類圖:
關於這次做業的設計的話和第二次沒什麼區別,再也不贅述。本次做業的難點應該在於指導書的理解,而好在評論區有不少同窗提出的疑問以及助教的回答(在這裏感謝一下各位提問題的同窗和回答問題的助教筒子們先),因此看完指導書一頭霧水的我在這些問題的幫助下順利的理解的做業要求,因而高興的認爲此次做業應該是沒問題了。可到了真正實現的時候卻發現沒那麼簡單,後來更換了數據結構(我一開始使用的是queue),改爲了ArrayList,這纔算勉強解決了這一問題。固然,這次做業也有很大的不足,就是單純的爲了實現功能和完成任務而犧牲了不少代碼的可讀性和可維護性——不少功能都寫在了一個方法裏面,不方便往後理清邏輯,此處我正在想辦法改進。
對於前三次做業,幸運的是個人公測都沒有出錯,互測在第三次做業時被扣了一個點。
第一次我拿到的是一份面向過程的代碼,除了用的是java的語法罷了,代碼只有一個類只有一個方法。這份代碼公測錯了一個點,緣由是在匹配輸入格式的時候採用了正則表達式可是沒有考慮爆棧的問題。我測出了他的兩個bug,一是由於該同窗沒有考慮第一個多項式前面符號爲負的狀況,而是直接默認爲正;還有一個是由於他在處理「-00」這種狀況的時候考慮不是很周全,只考慮了一個0。
有了第一次給別人debug(找bug)的經驗,此次我拿到代碼的時候首先就看了他的readme。可是看了半天卻沒有什麼收穫,大概是由於這才第二次因此做業坑點很少吧,而後我就看了他的代碼,感受這是一位代碼風格很好可是設計可能不是很周全的同窗的做品。雖然我找了他四個錯誤(報的兩個ERROR,兩個incomplete),但他的代碼格式卻給我很清爽的感受——各個類井井有條,變量名簡單易懂,因此很輕鬆的,我就找到了他的bug(^_^)。儘管找了他的bug,可是我仍是感受那位同窗應該是因爲設計上的問題才致使了這些bug,他的bug依次爲:
因此,我測試的這位同窗若是當初花在指導書上的時間再多一點的話那這些bug應該是能夠避免的。
和第二次做業同樣,拿到代碼我首先看的是他的readme,看完readme我就知道此次應該是找不出代碼的——這份代碼設計很嚴密,不少輸入輸出的限制我連想都沒想過(在這裏先感謝一下測我代碼的那位同窗吧),接下來我用了本身的、舍友的、同窗的測試數據「輪番轟炸」,但都沒有找出bug,索性放棄了。這一次我本身的代碼卻犯了一個錯誤——第一條指令匹配的時候忘記加‘+’,因此若是第一條指令的時間前有正號的話就會報錯。互測結束後我也反思了一下爲何會犯這種錯誤,結論仍是設計上的問題,由於不少問題若是在設計的時候都沒想到的話,寫出的代碼錯誤的機率是很大的。
寫到這裏,我來總結一下如何測試別人的程序。
首先確定是看一下對方的readme,看一下對方的實現方式以及看對方在重要的一些點上有沒有考慮周全並做記錄;
其次呢是將對方的程序在本身用本身的測試數據跑一下看有沒有錯誤的地方;
最後再看一遍對方的readme,看他所提到的功能是否是都實現了以及實現方式是否是有錯誤,構造專門的測試數據進行測試。
首先感慨一下各位助教姐姐真的都好好吖,感受咱們寫oo花了多長時間她們就陪了咱們多長時間。
而後是設計真的很重要!!!有了好的設計,真正來完成代碼的時候可能只須要一兩個小時就搞定了。
最後,好的代碼風格也是優質程序的關鍵,因此,千萬不能以節約時間爲理由而犧牲代碼的可讀性,由於你永遠不會知道爲節約這點時間你會
付出怎樣的代價。