Java 과제 1~3 요약 및 분석

서론

세 주간의 Java 개발 과정을 통해, 과제는 단순한 문제 설계에서 복잡한 논리로 점진적으로 깊어졌습니다. 이 세 번의 과제는 Java 언어 기본에 대한 이해뿐만 아니라 객체 지향 설계, 예외 처리, 복잡한 자료 구조 사용까지 다루고 있습니다. 세 번의 과제를 마친 후, 이에 대한 요약을 제공합니다. 먼저 과제의 양은 점차 줄어들었지만, 난이도는 분명히 증가했습니다.

첫 번째 과제: 주로 기본 논리 구현에 집중했으며, 간단한 데이터 입력과 출력에 중점을 두었지만 명확한 구조가 부족했습니다.

두 번째 과제: 문제 평가 및 시험지 구성 개념을 도입하기 시작했으며, 이 단계의 도전 과제는 코드의 재사용성과 유지보수성을 보장하기 위해 합리적인 구조를 구축하는 것이었습니다.

세 번째 과제: 복잡성이 크게 증가하여 학생 정보, 답변 논리 처리, 문제 삭제 및 잘못된 입력 판단이 추가되어 코드 설계 능력과 복잡한 요구사항에 유연하게 대처하는 능력을 전면적으로 시험했습니다.

이러한 주간의 누적을 통해 우리는 단순한 절차 중심 프로그래밍에서 더 성숙한 객체 지향 설계로 점진적으로 전환했습니다. 특히 여러 클래스와 데이터 간의 상호 의존 관리를 다룰 때 모듈화 프로그래밍의 본질을 더 깊이 이해하게 되었습니다. 이 과정은 다소 어려울 수 있지만, 우리는 이 방향으로 최선을 다해 노력했습니다.

설계 및 분석

과제 1은 세 개의 클래스로 구성되었습니다: 문제, 시험지, 답안지.

1. Question 클래스

  • 캡슐화: 문제 번호, 내용, 정답을 Question 클래스에 캡슐화하고, 이러한 속성 접근은 private 변수와 public getter 메서드를 통해 제공되도록 했습니다.
  • 생성자: 문제 속성을 초기화하는 생성자를 제공하며, 매개변수를 통해 직접 값을 할당합니다.
  • 기능 메서드: 주어진 답변이 올바른지 판단하는 checkAnswer 메서드를 구현합니다.
  • 문자열 반환: toString 메서드를 재정의하여 문제 내용을 표시할 수 있도록 합니다.

2. TestPaper 클래스

  • 컬렉션 관리: TestPaper 클래스는 List를 사용하여 모든 문제를 관리합니다. 동적으로 문제를 추가할 수 있습니다.
  • 문제 검색: 특정 번호의 문제를 가져오는 메서드를 제공하며, 문제 번호로 검색하여 더 효율적으로 쿼리할 수 있도록 지원합니다.
  • 캡슐화 설계: 문제 목록의 private성을 유지하고 외부 접근을 위한 public 메서드를 제공합니다.

3. AnswerSheet 클래스

  • 답안 관리: AnswerSheet 클래스는 Paper 인스턴스와 사용자 답변 목록을 보유하며, 답변과 해당 문제를 결합합니다.
  • 답안 평가: 모든 답변을 순회하고 해당 문제 객체를 호출하여 검증하는 평가 메서드를 제공합니다.
  • 결과 출력: 평가 결과에 따라 출력을 생성하고 printResults 메서드를 사용하여 결과를 콘솔에 표시합니다.

과제 2에서도 세 개의 클래스를 유지했지만 논리적으로 수정되었으며, List에서 해시 테이블로 변경되었습니다.

1. Question 클래스

  • 시험의 문제를 나타내며, 문제 번호, 내용, 답변을 포함하며 생성자를 통해 초기화됩니다.

2. TestPaper 클래스

  • 시험지를 나타내며, 시험 번호와 관련 문제 목록(문제 번호와 해당 점수를 HashMap에 저장)을 포함합니다.
  • addQuestion 메서드를 제공하여 시험에 문제 점수를 추가합니다.

3. AnswerSheet 클래스

  • 사용자 답변을 나타내며, 시험 번호와 사용자가 제출한 답변 목록을 포함합니다.
  • 생성자를 통해 초기화하고 addAnswer 메서드로 답변을 추가합니다.

과제 3은 과제 2에 비해 Student 클래스가 추가되어 총 4개의 클래스를 포함합니다.

1. Question 클래스

과제 2에 비해 변화가 없습니다.

코드 보기
class QuizItem {
    private int itemNumber;
    private String content;
    private String correctResponse;
    
    public QuizItem(int itemNumber, String content, String correctResponse) {
        this.itemNumber = itemNumber;
        this.content = content;
        this.correctResponse = correctResponse;
    }
    
    public boolean checkResponse(String userResponse) {
        return correctResponse.equals(userResponse);
    }
    
    @Override
    public String toString() {
        return "문제 " + itemNumber + ": " + content;
    }
}

2. TestPaper 클래스

과제 2에 비해 totalScore가 이 클래스로 이동되었습니다.

코드 보기
class Examination {
    private int examId;
    private Map questionBank = new LinkedHashMap<>();
    private int overallScore = 0;

    public Examination(int examId) {
        this.examId = examId;
    }

    public void addQuestion(int questionId, int points) {
        questionBank.put(questionId, points);
        overallScore += points;
    }
    
    public int getOverallScore() {
        return overallScore;
    }
}

3. AnswerSheet 클래스

Student 클래스가 추가되어 과제 2에 비해 StudentID가 추가되었습니다.

코드 보기
class ResponseForm {
    private String examId;
    private String studentId;
    private Map studentResponses = new LinkedHashMap<>();

    public ResponseForm(String examId, String studentId) {
        this.examId = examId;
        this.studentId = studentId;
    }

    public void addResponse(int questionIndex, String response) {
        studentResponses.put(questionIndex, response);
    }
    
    public String getStudentId() {
        return studentId;
    }
}

4. Student 클래스

학생을 나타내며, 학생 ID와 이름을 포함합니다. 이 두 속성을 초기화하는 생성자를 제공합니다.

코드 보기
class Learner {
    private String studentId;
    private String fullName;

    public Learner(String studentId, String fullName) {
        this.studentId = studentId;
        this.fullName = fullName;
    }
    
    public String getFullName() {
        return fullName;
    }
}

구현 과정에서의 문제점

  1. 과제 작성 시 가장 번거로운 부분은 일부 경계 제약 조건입니다. 답변이 틀린 경우라면 적어도 테스트 사례를 통해 어디가 잘못되었는지 볼 수 있지만, 특정 상황에서 비영리 반환(예: 세 번째 과제 작성 시 10개의 테스트 사례 모두 답변 표시(옳든 그르든)되지만, 제출 시 특정 상황에서 비영리 반환 표시)이 발생하는 경우, 다른 상황은 모두 답변의 옳고 그름이 표시되어 혼란스러울 수 있습니다.
  2. 테스트 사례 3, 즉 문제 삭제가 있는 경우

다음 이미지는 삭제를 고려하지 않고 여전히 판단을 추가해야 함을 나타냅니다.

코드 보기
if (removedItems.contains(itemNumber)) {
    resultOutput.append("문제 ").append(itemNumber).append(" 유효하지 않음~0\n");
}
  1. 테스트 사례 10에서, 즉 정보가 뒤섞여 입력될 경우 다음과 같은 상황이 발생했습니다.

정렬되지 않은 입력을 판단하지 않아 답변이 비어있게 될 수 있습니다.

개선 제안

이전 SourceMonitor 분석 데이터에서 볼 수 있듯이, 주석을 작성하지 않는 경향이 있습니다. 당시에는 생각이 비교적 명확했을 수 있지만, 시간이 지나면 이해하기 어려워져 향후 반복 및 읽기에 불리합니다. 또한 일부 중첩 구조가 많이 사용되어 이해는 쉬울 수 있지만, 코드가 지나치게 장황하고 복잡도도 높습니다. 코드를 명확하고 간결하게 작성하여 복잡도를 낮추어야 합니다.

결론

처음의 간단한 논리 구현부터 마지막까지 문제, 시험지, 답안지, 학생, 문제 삭제 등 다양한 입력 유형의 정보 처리를 포함하는 완전한 객체 지향 시스템을 구축하는 세 번의 과제를 통해, 우리는 캡슐화와 모듈화 설계를 통해 복잡한 비즈니스 논리의 변화에 대처하는 방법을 배웠습니다. 동시에 추상화 및 계층화 설계를 통해 프로그램 구조를 더 명확하고 확장 가능하게 만들었습니다. 이 과정은 다소 꾸물거릴 수 있고 점수도 그렇게 높지 않을 수 있지만, 이 일을 완수하기 위해 최선을 다해야 합니다. 또한 과제 제출 전 테스트 커버리지가 때때로 충분하지 않으며, 특히 일부 경계 상황과 형식 오류 처리에서 그렇습니다. 향후 테스트 설계에 중점을 두어 프로그램이 다양한 입력 상황에서 안정적으로 실행될 수 있도록 해야 하며, 진정한 테스트를 수행하고 더 많은 시간을 대과제에 할애해야 합니다.

태그: java 객체지향프로그래밍 자료구조 예외처리 모듈화설계

7월 22일 23:42에 게시됨