下來我将分點講述下收獲和感想以及相關意見和建議。
作為一個雖然沒有專門學過java但是早已經熟悉OOP程式設計方式,并使用 <code>C#</code> 有過大概幾千行開發經驗的學員,我的感想可能和大部分人有些不同。
說到<code>java</code>和<code>C#</code>,其實這是強類型語言裡面兩個最适合OOP設計的語言,而且兩者之前有着相當高的文法相似度(畢竟都是滿滿的C系語言風格)。而且都是在整個項目中指定一個入口點類,然後從 <code>static void main</code> 函數入口,就像這樣(簡單的A+B問題的實作):
C#
Java
有一個之前遇到過的坑,就是java的異常處理機制。在java中,如果一個函數(方法)需要抛出異常的話,是必須在目前函數(方法)處進行聲明的。同時外部調用這個函數(方法)的部分也必須使用異常處理語句包裝起來(即必須放進 <code>try { }</code>中)。
這樣做的一個很大的好處是強迫開發者完全将所有的異常保持在一個可控的狀态,即每一層對于内層的異常都會做好完全的處理。不過缺點也很明顯——文法太煩了,尤其是當異常狀态很多很雜時候,外部調用可以變得非常繁瑣。
而<code>C#</code>中則完全不需要這些,抛出異常無需聲明,也可以随意的使用可能有異常的函數(方法)(不過由于亂抛異常導緻的程式報錯結果也得自己處理。)
還記得在第一次正式講OOP時,java OOP很重要的一個原則就是不允許任何變量直接暴露給使用者。
這一點的确沒有錯,變量直接暴露給使用者會導緻部分資料失去控制,進而導緻整個對象模型内部紊亂。可是很多時候還是需要這樣子的變量的,尤其是頻繁通路的資料,不停地 <code>get</code>, <code>set</code>總讓人感到非常的不舒服,文法也會變得很臃腫。
對于java而言,這的确是無解的,對于頻繁直接改動的值總還是不得不<code>get</code>, <code>set</code>。
而在C#中,則有個叫做屬性的東西,可以很好的解決這一問題,就像這樣
程式調用時,就可以像調用一個變量一樣的調用<code>val</code>了,無需括号,無需<code>get</code>, <code>set</code>,文法十分優雅。
不僅如此,屬性還可以完美支援很多更加強大的功能
隻讀屬性
這樣一來<code>val</code>就隻可以讀出不可以更改了
将複雜的資料維護動作簡單封裝起來
其實,屬性也是基于<code>get</code>和<code>set</code>的模式的,隻不過将其按照指派和取值的兩種動作分别進行了封裝。<code>get</code>, <code>set</code>内部本質還是一個函數,可以執行複雜任務的函數。
同時,java和c#都作為嚴格的強類型OOP語言,很多機制(例如:強類型的繼承、接口、反射、函數的重載等)也都是完全具備的(相比之下,弱類型則不需要接口和函數重載之類的東西,像php這樣的語言連反射也都是完全内置化的,而且弱類型語言普遍有個叫做eval的函數,可以基本上取代掉傳統的反射類)。就文法舒适程度而言,個人還是更支援c#一些。不過java有個至今無可替代的優勢——完美的跨平台支援(java的虛拟機遍布各個平台,即涉及到各個平台底層的東西java早已替程式設計者實作好了),且java的部分特性決定了java更适合作為OOP初學者語言。
總之這兩個語言,各有各的好處,還有很多的東西值得我去進一步研究和學習。以及,作為一個合格的 IT learner,而不是廉價的勞動力碼農,眼光也絕對不可以局限于語言本身,而應該是語言之上更深層次的東西。
相比于之前的資料結構與程式設計課程,面向對象課程存在一個比較明顯的問題——由于很多時候隻有大緻的需求而沒有很明确的輸入輸出或互動要求,是以很難做成類似OJ那樣的自動化評測,是以很多時候還是隻能依賴于人手工評測,這樣非常的費時費力。
其實個人感覺,做出來OJ模式的測評本身并不是難事。但是帶來的問題是,如果完全采用黑盒測試,則沒有辦法保證學生采用了所需的面向對象設計模式。
我個人的建議是:将人工檢視代碼和黑盒測試相結合
人工檢視可以一定程度上保證設計模式按照要求。同時黑盒測試也可以真正更加友善和可感地衡量一個程式的真實性能和不足,同時大大提高測試效率。
關于課程本身,我想說的就是如何平衡一下Java語言的教學和真正面向對象知識的教學,讓無java基礎的人不至于完全掉隊,也讓有一定基礎的人不被太多拖慢進度。
由于有些東西可能真的還是難以全面采用黑盒測試,是以不得已隻能采用互測的方式。就目前來看,目前的互測方式有明顯不公平不合理之處。
由于采用的是每個人随機配置設定一名被hack者的原因,是以這直接導緻每個人能hack的空間非常有限。說的更直接點,如果你很幸運抽到了一個代碼滿是bug的程式,那你的分數可以非常高;如果你hack的人程式結構相當嚴密,設計優化程度相當可以,那這一點上你基本沒法指望。
同時也是由于上面一點,從被hack者的角度而言,也存在極大的漏網空間,很大程度上也取決于運氣。同一份程式,如果你的hacker是個技術了得,你大概會很慘;如果他敷衍了事或者水準欠佳,那你得分也一樣不會低,甚至完全不低于那些真正把程式寫的很棒的人。
這樣的模式,有很多的弊病:
由于存在如此巨大的不公平空間,是以很難真正激發同學之間互相糾正錯誤的欲望,根本無法達到類似 <code>Codeforces</code> 那樣的互相糾正的作用。相反,這樣的措施一旦限制稍有失誤,便可能導緻嚴重的惡性競争(甚至是一些不正當線下交易)。
從學生的未來發展來看,這樣的措施會導緻很多該糾正的bug和系統設計錯誤無法被及時糾正。一旦少數當時作為漏網之魚的學生帶着這種錯誤的設計方式進入了其他機關,那麼對學生本人和那個機關而言都是極為不利的。
我的建議:
在 <code>Codeforces</code> (Codeforces 網站連結) 中,一旦有人成功hack了别人的一份程式,那麼終測的時候,所有之前獲得 <code>Accepted</code> 狀态的程式都會被所有這些成功hack别人的資料重新測試一下。也就是說實際上即便你直接hack的人隻有一個或者幾個,但實際上作用到的人是所有人(很多時候,很多錯誤,都是非常具有共性的,一個hack點常常可以卡掉非常多份的程式)。建議這樣的廣泛測試機制可以納入考核,有助于大幅度提高公平性和教學的品質。
在 <code>Codeforces</code> 中, 每一份程式都是被挂出來讓大家一起來hack的。這樣當看得人多了,缺陷自然會很快全部曝光出來。建議更多的程式讓大家開放hack,也可以讓真正有足夠能力hack的人能發揮應有的作用。(不過這樣一來就必須做好嚴密的反作弊反抄襲系統,為了杜絕由于代碼公開而導緻的抄襲現象。不過也有一種辦法就是<b>等到ddl之後,所有人停止送出,這時候再開放hack。</b>)
總之,個人覺得,互測機制本身是個初衷很好的機制。但是裡面的相關制度和模式還是應該有進一步完善的空間。最後期待半年後我們的OO課程更加科學合理。