본문 바로가기
Java/문법

Java 작성 시 신경쓰면 좋은 Early return, Guard clause

by ssury94 2024. 12. 12.
 
 
 

 

* return false가 먼저 오도록 작업 하기 Why?

Early return이란?

불필요한 코드 실행 방지: return false 이후의 코드는 실행되지 않으므로, 조건이 충족되지 않았을 때 불필요한 작업을 막을 수 있다.
성능 최적화: 조건이 충족되지 않은 경우 즉시 함수를 종료함으로써 리소스를 절약할 수 있다.

 

예제 - 강의 등록, 취소 

import entity.Lecture;
import entity.Student;

public class StudentTest {
    public static void main(String[] args) {

        // 학생 입력
        Student s1=new Student("김나나","32번");
        Student s2=new Student("홍길동","1번");

        // 강의 입력
        Lecture l1= new Lecture("CRM개발과정",1);
        Lecture l2= new Lecture("세무2급과정",20);


        s1.registerLecture(l1);
        l1.printInfo();
        s1.printInfo();

        s2.registerLecture(l1);
        l1.printInfo();

        s1.cancelLecture(l1);
        s1.printInfo();

        s2.cancelLecture(l1);




    }
}

 

 

package entity;

public class Student {
    private String name;
    private String studentId;
    private Lecture registeredLecture;

    public Student() {
    }

    // 생성자
    public Student(String name, String studentId) {
        // 학생의 이름과 학번을 초기화합니다.
        this.name=name;
        this.studentId=studentId;

    }

    public boolean registerLecture(Lecture lecture) {
        // 1. 이미 수강 중인 강의가 있는지 확인합니다.
        // 2. 수강 중인 강의가 없다면, 주어진 강의에 학생을 등록합니다.
        // 3. 강의 등록이 성공하면 registeredLecture를 업데이트하고 true를 반환합니다.
        // 4. 실패하면 (이미 수강 중이거나 강의가 가득 찼을 경우) false를 반환합니다.

        if (registeredLecture == null&&lecture.getMaxStudents()>lecture.getCurrentStudents()) {
            lecture.addStudent();
            this.registeredLecture=lecture;
            System.out.println("등록 되었습니다. 학생이름: "+name+" 신청과목: "+registeredLecture);
            return true;
        } else{
            System.out.println("등록되지 않았습니다.");
            return false;}
    }

    public boolean cancelLecture(Lecture lecture) {
        // 1. 현재 수강 중인 강의가 있는지 확인합니다.
        // 2. 수강 중인 강의가 있다면, 해당 강의에서 학생을 제거합니다.
        // 3. registeredLecture를 null로 설정합니다.
        // 4. 취소가 성공하면 true, 실패하면 false를 반환합니다.
        if(registeredLecture!=null){
            this.registeredLecture=null;
            lecture.removeStudent();
            System.out.println(name+" 학생 등록 취소 되었습니다. ");
            return true;
        }else {
            System.out.println(name+" 학생 취소할 강의가 없습니다.");
            return false;
        }

    }

    public void printInfo() {
        // 학생의 이름, 학번을 출력합니다.
        // 수강 중인 강의가 있다면 강의명도 출력합니다.
        // 수강 중인 강의가 없다면 "수강 중인 강의 없음"을 출력합니다.
        if (registeredLecture == null) {
            System.out.println("학생이름: " + name + " 수강 중인 강의 없음");
        } else {
            System.out.println("학생이름: " + name + " 수강강의명: " + registeredLecture);
        }

    }


    //get set
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    public Lecture getRegisteredLecture() {
        return registeredLecture;
    }

    public void setRegisteredLecture(Lecture registeredLecture) {
        this.registeredLecture = registeredLecture;
    }
}

 

 

package entity;

public class Lecture {

    private String lectureName;
    private int maxStudents;
    private int currentStudents;

    @Override
    public String toString() {
        return lectureName;// 강의명을 반환
    }


    // 생성자
    public Lecture(String lectureName, int maxStudents) {
        // 강의명과 최대 수강 인원을 초기화합니다.
        this.lectureName=lectureName;
        this.maxStudents=maxStudents;
    }

    public boolean addStudent() {
        // 1. 현재 수강 인원이 최대 인원보다 적은지 확인합니다.
        // 2. 여유가 있다면 currentStudents를 1 증가시키고 true를 반환합니다.
        // 3. 강의가 이미 가득 찼다면 false를 반환합니다.
        if (maxStudents > currentStudents) {
            currentStudents += 1;
            return true;
        }else {
            return false;
        }
    }

    public boolean removeStudent() {
        // 1. 현재 수강 인원이 0보다 큰지 확인합니다.
        // 2. 수강 중인 학생이 있다면 currentStudents를 1 감소시키고 true를 반환합니다.
        // 3. 수강 중인 학생이 없다면 false를 반환합니다.
        if(currentStudents>0){
            currentStudents-=1;
            return true;
        }else{
            return false;
        }
    }

    public void printInfo() {
        // 강의명, 현재 수강 인원, 최대 수강 인원을 출력합니다.
        System.out.println("강의명 : "+lectureName+" 현재 수강인원: "+currentStudents+" 최대 수강인원: "+maxStudents);
    }

    // get set


    public String getLectureName() {
        return lectureName;
    }

    public void setLectureName(String lectureName) {
        this.lectureName = lectureName;
    }

    public int getMaxStudents() {
        return maxStudents;
    }

    public void setMaxStudents(int maxStudents) {
        this.maxStudents = maxStudents;
    }

    public int getCurrentStudents() {
        return currentStudents;
    }

    public void setCurrentStudents(int currentStudents) {
        this.currentStudents = currentStudents;
    }
}

 


코드 개선해보기

* 실패 사유가 구체적으로 ( 정원 마감 / 이미 수강중인 과목 있음)  뜨도록 추가해보기

* false먼저, true 나중에 반환되게 수정

public boolean registerLecture(Lecture lecture) {
    // 1. 이미 수강 중인 강의가 있는지 확인합니다.
    // 2. 수강 중인 강의가 없다면, 주어진 강의에 학생을 등록합니다.
    // 3. 강의 등록이 성공하면 registeredLecture를 업데이트하고 true를 반환합니다.
    // 4. 실패하면 (이미 수강 중이거나 강의가 가득 찼을 경우) false를 반환합니다.

    //return false 부터 작성하는쪽이 좋다.
    if (registeredLecture != null) {// 수강중인 강의가 null이 아니면 false
        System.out.println(name + " 학생, 이미 수강중인 과목이 있어 등록되지 않았습니다.");
        return false;
    }
    if (lecture.getMaxStudents() <= lecture.getCurrentStudents()) {
        System.out.println(name + " 학생, 정원 마감으로 등록되지 않았습니다.");
        return false;
    }
        lecture.addStudent();
        this.registeredLecture=lecture;
        System.out.println(name + " 학생, "+registeredLecture.getLectureName() +" 등록되었습니다.");
        return true;
}

Guard clause란?

함수나 메서드의 시작 부분에서 특정 조건을 먼저 확인하고, 
그 조건이 만족되지 않으면 즉시 함수를 종료하는 프로그래밍 패턴입니다

주요 특징은 다음과 같습니다:
조기 반환: 조건이 맞지 않으면 함수를 빠르게 종료합니다.
중첩 조건문 감소: 복잡한 if-else 구조를 단순화하여 코드의 가독성을 높입니다.
코드 평탄화: 깊은 들여쓰기를 줄여 코드의 구조를 더 선형적으로 만듭니다.
주요 로직 강조: 예외적인 상황을 먼저 처리함으로써 핵심 로직에 집중할 수 있게 합니다.

Guard clause를 사용하면 코드의 가독성이 향상되고, 유지보수가 더 쉬워집니다. 또한, 조건이 추가되어도 코드의 복잡도가 크게 증가하지 않는 장점이 있습니다.

 

 registeredLecture.getLectureName()

* 이렇게하면 이름뜬다. 

* 이름이 안떠서 퍼플렉시티에 검색해서... 아직 배운적 없는 @Override toString()을 사용했다.

 

toString()

Object 클래스에 정의된 메소드로, 객체를 문자열로 표현하는 데 사용됩니다. 
기본적으로 이 메소드는 클래스 이름과 해시코드를 반환하지만, 
실제 개발에서는 이 기본 동작을 오버라이드하여 객체의 필드 값을 출력하도록 구현하는 것이 일반적입니다.