Java vs Ruby: 성적표 프로그램

Tags:

CS101 과목의 성적표 프로그램의 답안을 전문적으로 보이게 수정하고 이를 루비와 비교해보았습니다. LoC에서의 차이점이나 루프를 돌거나 리스트를 다루는 방법 등에 대한 비교.

(generics 써서 캐스팅 없애는건 제외하고) 자바에서 더 짧게 짤 수 있으시다면, be my guest.

1. Subject.java

public class Subject {

    private String name;
    private int score;
    
    public Subject() { }
    
    public Subject(String name, int score) {
        setName(name);
        setScore(score);
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
}

1′. subject.rb

class Subject
  def initialize(name, score)
    @name = name
    @score = score
  end
  
  attr_accessor :name, :score
end

2. Scorecard.java

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class Scorecard {
    
    private String studentName;
    private Subject[] subjectArray;
    
    public Scorecard(String studentName, Subject[] subjectArray) {
        this.studentName = studentName;
        this.subjectArray = subjectArray;
    }
    
    public double getTotal() {
        double result = 0;
        for (Subject s: subjectArray)
            result += s.getScore();

        return result;
    }
    
    public double getAverage() {
        return getTotal() / subjectArray.length;
    }
    
    public String getStudentName() {
        return studentName;
    }
    
    public Subject findBestSubject() {
        return (Subject) Collections.max(
            Arrays.asList(subjectArray), 
            new Comparator() {
                public int compare(Object o1, Object o2) {
                    return ((Subject)o1).getScore() - ((Subject)o2).getScore();
                }
            }
        );
    }
}

2′. scorecard.rb

class Scorecard
  def initialize(name, subjects)
    @name = name
    @subjects = subjects
  end
  
  def total
    @subjects.inject(0.0) { |total, s| total + s.score }
  end
  
  def average
    total / @subjects.size
  end
  
  def best_subject
    @subjects.max { |a, b| a.score <=> b.score }
  end
  
  attr_reader :name
end

3. ScorecardMain.java

public class ScorecardMain {
    public static void main(String[] args) {
        Subject[] sub = new Subject[] {
                new Subject("Math",90),
                new Subject("English",86),
                new Subject("Physics",88),
                new Subject("Biology",97) 
        };
        
        Scorecard sCard = new Scorecard("철수",sub);
        
        System.out.println(sCard.getStudentName()+" 학생의 총점은 "
            +sCard.getTotal()+" 점 입니다.");
        System.out.println(sCard.getStudentName()+" 학생의 평균점수는 " +
            +sCard.getAverage()+" 점 입니다.");
        System.out.println("제일 잘한 과목은 "
            +sCard.findBestSubject().getName()
            +"로 "+sCard.findBestSubject().getScore()+"점 입니다.");
    }
}

3′. scorecard_main.rb

require "subject"
require "scorecard"

subjects = [Subject.new("Math", 90), 
            Subject.new("English", 86), 
            Subject.new("Physics", 88), 
            Subject.new("Biology", 97)]

card = Scorecard.new("철수", subjects)
puts "#{card.name} 학생의 총점은 #{card.total} 점입니다."
puts "#{card.name} 학생의 평균점수는 #{card.average} 점입니다."
puts "제일 잘한 과목은 #{card.best_subject.name} 로 #{card.best_subject.score} 점입니다."

Comments

6 responses to “Java vs Ruby: 성적표 프로그램”

  1. 공성식 Avatar
    공성식

    워낙에 straight-forward한 코드라 흠잡을 데가 없네요.
    그냥 몇 가지 사소한 지적을 해보겠습니다.
    크고 작은 것 비교하는 연산자(사실은 메소드지만…)를 쓰면 글이 잘리기 때문에 그냥 (비교연산자)라고 썼습니다.

    def best_subject
    @subjects.max { |a, b| a.score (비교연산자) b.score }
    end

    과목 간의 비교 방법은 과목 클래스 내에 정의하는 게 더 좋을 것 같습니다.
    과목 클래스 내에서 처리해야 할 responsibility를 외부 클래스에 전가하는 것은 별로 OO적이지 않을 것 같아서요.

    class Subject
    def (비교연산자) (other)
    @score (비교연산자) other.score
    end
    end

    class Scorecard
    def best_subject
    @subjects.max { |a, b| a b }
    end
    end

    또한 Subject는 가급적 immutable로 하는 게 좋을 것 같아요.
    만약 그렇지 않으면 다음과 같은 cheating이 가능합니다.

    card.best_subject.name = “Test”
    card.best_subject.score = 100

    그러므로 Subject 클래스에 attr_accessor보다는 attr_reader를 이용하는 게 좋겠습니다.

    위의 것들은 자바 코드에도 비슷하게 적용될 것 같구요.

    CS101과목에서 굳이 이런 것까지 고려할 필요야 없겠지만요…

  2. 공성식 Avatar
    공성식

    위의 코드 중 다음 부분은 잘못 됐네요.
    (비교연산자)가 빠졌어요.

    class Scorecard
    def best_subject
    @subjects.max { |a, b| a (비교연산자) b }
    end
    end

  3. MKSeo Avatar
    MKSeo

    음 네… 맞아요. 말씀하신대로 수정하면 더 좋을 듯..
    그냥 자바 코드를 보니 바꿔보고 싶었어요.
    예제도 워낙 전형적인 예제라.. ㅎㅎ

  4. 아즈 Avatar

    아니 형 이런걸 다~ ^^;;

  5. 공성식 Avatar
    공성식

    앗, 다시 생각해 보니 만약 과목 클래스 내에서 비교 메소드를 만들면 최대값 찾을 때 블럭을 넘겨주지 않아도 되겠네요.

    class Scorecard
    def best_subject
    @subjects.max
    end
    end

  6. MKSeo Avatar
    MKSeo

    아 네 맞아요.. 무언가를 알고 있는 클래스가 외부에 getter setter를 제공하게하기보다는 그 클래스가 자신의 일은 알아서 하도록하라는 말이 기억나는군요 ㅎㅎ

Leave a Reply

Your email address will not be published. Required fields are marked *