面向對象先導課感想

下來我將分點講述下收穫和感想以及相關意見和建議。

收穫和感想

作爲一個雖然沒有專門學過java但是早已經熟悉OOP程序設計方式,並使用 C# 有過大概幾千行開發經驗的學員,我的感想可能和大部分人有些不同。

java語言

說到javaC#,其實這是強類型語言裏面兩個最適合OOP設計的語言,而且兩者之前有着相當高的語法相似度(畢竟都是滿滿的C系語言風格)。而且都是在整個項目中指定一個入口點類,然後從 static void main 函數入口,就像這樣(簡單的A+B問題的實現):

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace APlusB {
    class Program {
        static void Main(string[] args) {
            string[] numbers = Console.ReadLine().Split(new char[] { ' ' });
            int a = int.Parse(numbers[0]);
            int b = int.Parse(numbers[1]);
            Console.WriteLine(a + b);
        }
    }
}

Java

package aplusb;
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        System.out.println(a + b);
    }
}

有一個之前遇到過的坑,就是java的異常處理機制。在java中,如果一個函數(方法)需要拋出異常的話,是必須在當前函數(方法)處進行聲明的。同時外部調用這個函數(方法)的部分也必須使用異常處理語句包裝起來(即必須放進 try { } 中)。
這樣做的一個很大的好處是強迫開發者完全將所有的異常保持在一個可控的狀態,即每一層對於內層的異常都會做好完全的處理。不過缺點也很明顯——語法太煩了,尤其是當異常狀態很多很雜時候,外部調用可以變得非常繁瑣。
C#中則完全不需要這些,拋出異常無需聲明,也可以隨意的使用可能有異常的函數(方法)(不過由於亂拋異常導致的程序報錯結果也得自己處理。)

基於java的OOP

還記得在第一次正式講OOP時,java OOP很重要的一個原則就是不允許任何變量直接暴露給用戶。
這一點的確沒有錯,變量直接暴露給用戶會導致部分數據失去控制,從而導致整個對象模型內部紊亂。可是很多時候還是需要這樣子的變量的,尤其是頻繁訪問的數據,不停地 get, set總讓人感到非常的不舒服,語法也會變得很臃腫。
對於java而言,這的確是無解的,對於頻繁直接改動的值總還是不得不get, set
而在C#中,則有個叫做屬性的東西,可以很好的解決這一問題,就像這樣

protected int p_val;
public int val {
    get { 
        return this.p_val;
    }
    set {
        this.p_val = value;
    }
}

程序調用時,就可以像調用一個變量一樣的調用val了,無需括號,無需get, set,語法十分優雅。
不僅如此,屬性還可以完美支持很多更加強大的功能

  • 只讀屬性
protected int p_val;
public int val {
    get { 
        return this.p_val;
    }
}

這樣一來val就只可以讀出不可以更改了

  • 將複雜的數據維護動作簡單封裝起來
    其實,屬性也是基於getset的模式的,只不過將其按照賦值和取值的兩種動作分別進行了封裝。get, set內部本質還是一個函數,可以執行復雜任務的函數。

同時,java和c#都作爲嚴格的強類型OOP語言,很多機制(例如:強類型的繼承、接口、反射、函數的重載等)也都是完全具備的(相比之下,弱類型則不需要接口和函數重載之類的東西,像php這樣的語言連反射也都是完全內置化的,而且弱類型語言普遍有個叫做eval的函數,可以基本上取代掉傳統的反射類)。就語法舒適程度而言,個人還是更支持c#一些。不過java有個至今無可替代的優勢——完美的跨平臺支持java的虛擬機遍佈各個平臺,即涉及到各個平臺底層的東西java早已替編程者實現好了),且java的部分特性決定了java更適合作爲OOP初學者語言。

總之這兩個語言,各有各的好處,還有很多的東西值得我去進一步研究和學習。以及,作爲一個合格的 IT learner,而不是廉價的勞動力碼農,眼光也絕對不可以侷限於語言本身,而應該是語言之上更深層次的東西

對於課程設計的建議

相比於之前的數據結構與程序設計課程,面向對象課程存在一個比較明顯的問題——由於很多時候只有大致的需求而沒有很明確的輸入輸出或交互要求,所以很難做成類似OJ那樣的自動化評測,所以很多時候還是只能依賴於人手工評測,這樣非常的費時費力。
其實個人感覺,做出來OJ模式的測評本身並不是難事。但是帶來的問題是,如果完全採用黑盒測試,則沒有辦法保證學生採用了所需的面向對象設計模式。
我個人的建議是:將人工查看代碼和黑盒測試相結合
人工查看可以一定程度上保證設計模式按照要求。同時黑盒測試也可以真正更加方便可感地衡量一個程序的真實性能和不足,同時大大提高測試效率

關於課程本身,我想說的就是如何平衡一下Java語言的教學和真正面向對象知識的教學,讓無java基礎的人不至於完全掉隊,也讓有一定基礎的人不被太多拖慢進度。

關於互測

由於有些東西可能真的還是難以全面採用黑盒測試,所以不得已只能採用互測的方式。就目前來看,當前的互測方式有明顯不公平不合理之處

  • 由於採用的是每個人隨機分配一名被hack者的原因,所以這直接導致每個人能hack的空間非常有限。說的更直接點,如果你很幸運抽到了一個代碼滿是bug的程序,那你的分數可以非常高;如果你hack的人程序結構相當嚴密,設計優化程度相當可以,那這一點上你基本沒法指望。
  • 同時也是由於上面一點,從被hack者的角度而言,也存在極大的漏網空間,很大程度上也取決於運氣。同一份程序,如果你的hacker是個技術了得,你大概會很慘;如果他敷衍了事或者水平欠佳,那你得分也一樣不會低,甚至完全不低於那些真正把程序寫的很棒的人

這樣的模式,有很多的弊病

  • 由於存在如此巨大的不公平空間,所以很難真正激發同學之間互相糾正錯誤的慾望,根本無法達到類似 Codeforces 那樣的互相糾正的作用。相反,這樣的措施一旦限制稍有失誤,便可能導致嚴重的惡性競爭甚至是一些不正當線下交易)。
  • 從學生的未來發展來看,這樣的措施會導致很多該糾正的bug和系統設計錯誤無法被及時糾正。一旦少數當時作爲漏網之魚的學生帶着這種錯誤的設計方式進入了其他單位,那麼對學生本人和那個單位而言都是極爲不利的。

我的建議:

  • CodeforcesCodeforces 網站鏈接) 中,一旦有人成功hack了別人的一份程序,那麼終測的時候,所有之前獲得 Accepted 狀態的程序都會被所有這些成功hack別人的數據重新測試一下。也就是說實際上即便你直接hack的人只有一個或者幾個,但實際上作用到的人是所有人很多時候,很多錯誤,都是非常具有共性的,一個hack點常常可以卡掉非常多份的程序)。建議這樣的廣泛測試機制可以納入考覈,有助於大幅度提高公平性和教學的質量。
  • Codeforces 中, 每一份程序都是被掛出來讓大家一起來hack的。這樣當看得人多了,缺陷自然會很快全部曝光出來。建議更多的程序讓大家開放hack,也可以讓真正有足夠能力hack的人能發揮應有的作用。(不過這樣一來就必須做好嚴密的反作弊反抄襲系統,爲了杜絕由於代碼公開而導致的抄襲現象。不過也有一種辦法就是等到ddl之後,所有人停止提交,這時候再開放hack。

總之,個人覺得,互測機制本身是個初衷很好的機制。但是裏面的相關制度和模式還是應該有進一步完善的空間。最後期待半年後我們的OO課程更加科學合理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章