본문 바로가기

공부/JAVA 클린코드

Chapter 1 - 우선 정리부터

728x90

Chapter1

1.1 쓸모없는 비교 피하기

  • 불 원시 타입 true, false 를 없애준다.
if(microscope.isInorganic(sample)){ // true,false 없음
    return Result.INORGANIC;
}
else{
    return analyzeOrganic(sample);
}

if(!microscope.isHumanoid(sample)){ // true,false 없음
    return Result.ALIEN;
}
else{
    return Result.HUMAN;
}

1.2 부정 피하기

  • 긍정 표현식이 부정표현식 보다 낫다.
if(microscope.isOrganic(sample)){ //isInOrganic -> isOrganic
    return analyzeOrganic(sample);
}
else{
    return Result.INORGANIC;
}

if(microscope.isHumanoid(sample)){ //! 없앰
    return Result.HUMAN;
}
else{
    return Result.ALIEN;
}

1.3 불 표현식을 직접 반환

 boolean isValid(){
     return missions>=0 && name!=null && !name.trim().isEmpty();
 }
  • 조건문 3개 이상일 때는 변수에 의미있는 이름을 지어 조건 덩어리로 표현
 boolean isValid(){
     boolean isValidMissions = missions >=0; 
     boolean isValidName = name != null && !name.trim().isEmpty(); // 두개의 조건문을 하나로 묶음
     return isValidMissions && isValidName;
 }

1.4 불 표현식 간소화

  • 한 메서드 안에서 추상화 수준이 비슷하도록 명령문을 합쳐야함.

  • 높은 수준의 메서드가 다음으로 낮은 수준의 메서드를 호출하는 것이 이상적.

  • 문제 코드

    class SpaceShip {
    
      Crew crew;
      FuelTank fuelTank;
      Hull hull;
      Navigator navigator;
      OxygenTank oxygenTank;
    
      boolean willCrewSurvive() {
          return hull.holes == 0 &&
                  fuelTank.fuel >= navigator.requiredFuelToEarth() &&
                  oxygenTank.lastsFor(crew.size) > navigator.timeToEarth();
      }
    
    
```
- 개선코드
```java
 class SpaceShip {

    Crew crew;
    FuelTank fuelTank;
    Hull hull;
    Navigator navigator;
    OxygenTank oxygenTank;

    boolean willCrewSurvive() {
        boolean hasEnoughResources = hasEnoughFuel() && hasEnoughOxygen(); //소모성 자원이라는 주제로 묶고 의미 있는 이름으로 지음
        return hull.isIntact() && hasEnoughResources;
    }

    private boolean hasEnoughOxygen() {
        return oxygenTank.lastsFor(crew.size) > navigator.timeToEarth();
    }

    private boolean hasEnoughFuel() {
        return fuelTank.fuel >= navigator.requiredFuelToEarth();
    }
}

1.5 조건문에서 NullPointerException 피하기

  • 문제 코드
   void writeMessage(String message, Path location) throws IOException {
        if (Files.isDirectory(location)) { //location null 이면 nullPointerException 발생
            throw new IllegalArgumentException("The path is invalid!");
        }
        if (message.trim().equals("") || message == null) { //유효성 검사 먼저 하면 nullPointerException 발생
            throw new IllegalArgumentException("The message is invalid!");
        }
              ...
    }
  • 개선 코드

        void writeMessage(String message, Path location) throws IOException {
            if (message == null || message.trim().isEmpty()) {  // null을 먼저 확인 한 후에 유효하지 않은지 검사
                throw new IllegalArgumentException("The message is invalid!");
            }
            if (location == null || Files.isDirectory(location)) { // location도 null검사 먼저
                throw new IllegalArgumentException("The path is invalid!");
            }
    
  • 위에 처럼 항상 매개변수를 검사할 필요 x

  • public, protected, default 메서드에만 하면됨. private 메서드에서는 필요 x

1.6 스위치 실패 피하기 && 1.7 항상 괄호 사용하기

  • 각 case 끝에 꼭 break문 붙여주기
  • 의도적으로 break 누락시에는 반드시 주석을 남김.
  • Switch가 항상 옳은 것은 아님. 서로 다른 관심사는 서로 다른 코드블록에 넣어야함. 따라서 이때는 if문 사용
  • if문 사용할 때는 (),{} 와 같은 괄호를 사용.
  • 문제코드
void authorize(User user) {
        Objects.requireNonNull(user);
        switch (user.getRank()) {
            case UNKNOWN:
                cruiseControl.logUnauthorizedAccessAttempt();  // break 없음 , 허가받지 않은 접근 
            case ASTRONAUT:
                cruiseControl.grantAccess(user);  // 허가받은 접근
                break;
            case COMMANDER:
                cruiseControl.grantAccess(user); // 허가받은 접근
                cruiseControl.grantAdminAccess(user);
                break;
        }
    }
  • 개선코드

      // 허가받은 접근과 허가받지 않은 접근을 서로 다른 코드블럭에 넣음.
      void authorize(User user) {
          Objects.requireNonNull(user);
          if (user.isUnknown()) {
              cruiseControl.logUnauthorizedAccessAttempt(); 
          }
          if (user.isAstronaut()) {
              cruiseControl.grantAccess(user);
          }
          if (user.isCommander()) {
              cruiseControl.grantAccess(user);
          }
          cruiseControl.grantAdminAccess(user); // SECURITY THREAT
      }

    1.8 코드 대칭 이루기

  • 비슷한 관심사끼리 묶어준다

  • 개선 코드

    void authorize(User user) {
        Objects.requireNonNull(user);

        // 권한 부여 안하는 코드 혼자 if문 
        if (user.isUnknown()) {
            cruiseControl.logUnauthorizedAccessAttempt();
            return;
        }

        // 권한을 부여하는 코드끼리 if/else if로 묶어줌
        if (user.isAstronaut()) {
            cruiseControl.grantAccess(user); 
        } else if (user.isCommander()) {
            cruiseControl.grantAccess(user);
            cruiseControl.grantAdminAccess(user);
        }
    }

출처: 자바 코딩의 기술/사이먼 하러, 요르그 레너드, 리누스 디에츠 저/심지현 역

'공부 > JAVA 클린코드' 카테고리의 다른 글

Chapter2-코드스타일 레벨업  (0) 2021.04.29