본문 바로가기

JAVA/JAVA 기초

자바 코딩의 기술 - #1 코드 정리

반응형

1.1 쓸모없는 비교 피하기

if(microscope.isInorganic(sample) ==  true)

변경

if(microscope.isInorganic(sample)
  • 불 표현식은 불 원시값과 비교하지 않아도 된다.

1.2 부정피하기

if(!microscope.isHumanoid(sample)) {
    retrun Result.ALIEN;
} else {
    retrun Result.HUMANOID;
}

변경

if(microscope.isHumanoid(sample)) {
    retrun Result.HUMANOID;
} else {
    retrun Result.ALIEN;
}
  • 코드를 읽을때 일반적으로 긍정 표현을 이해하기가 더 쉽다.

1.3 boolean 표현식을 직접 반환

boolean isValid() {
    if (missions < 0 || name == null || name.trim().isEmpty()) {
        retrun false;
    } else {
        retrun true;
    }
}

변경

boolean isValid() {
    retrun missions > 0 && name != null && !name.trim().isEmpty()
}
  • if문으로 감쌀필요없이 값을 바로 반환할 수 있다.

드 모르간 법칙

!A && !B == !(A || B) // true
!A || !B == !(A && B) // true

변경

boolean isValid() {
    boolean isValidMission = missions >= 0;
    boolean isValidName = name != null && !name.trim().isEmpty();
    retrun isValidMission && isValidMission;
}

조건문 복잡할 경우 작은 덩어리로 분할한다.

1.4 boolean 표현식 간소화

class SpaceShip {

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

    boolean willCrewSurvive() {
        retrun hull.holes == 0 &&
            fuelTank.fuel >= navigator.requiredFuelToEarth() &&
            oxygenTank.lastsFor(crew.size) > navigator.timeToEarth();
    }
}

변경

class SpaceShip {

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

    boolean willCrewSurvive() {
        boolean hasEnoughResources = hansEnoughFuel() && hasEnoughOxygen();
        retrun hull.isIntact() && hasEnoughResources;
    }

    private boolean hansEnoughFuel() {
        retrun fuelTank.fuel >= navigator.requiredFuelToEarth();
    }

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

1.5 조건문에서 NullPointerException 피하기

class Logbook {

    void writeMessage(String message, Path location) throws IOException {
        if (Files.isDirectory(location)) {
            throw new IllegalArgumentExceptioin("The path is invalid");
        }

        if (message.trim().equals("") || message == null) {
            throw new IllegalArgumentExceptioin("The message is invalid");
        }

        String entry = LocalDate.now() + ": " + message;
        Files.write(location, Collections.singletoneList(entry),
            StandardCharsets.UTF_8, StandardOpenOption.CREATE,
            StandardOpenOption.APPEND);

    }
}

변경

class Logbook {

    void writeMessage(String message, Path location) throws IOException {
        if (location == null || Files.isDirectory(location)) {
            throw new IllegalArgumentExceptioin("The path is invalid");
        }

        if (message == null || message.trim().equals("")) {
            throw new IllegalArgumentExceptioin("The message is invalid");
        }

        String entry = LocalDate.now() + ": " + message;
        Files.write(location, Collections.singletoneList(entry),
            StandardCharsets.UTF_8, StandardOpenOption.CREATE,
            StandardOpenOption.APPEND);

    }
}
  • 먼저 모든 인수에 대해 null값을 확인한다.
  • 이후에 도메인에 따른 제한을 확인한다.
Objects.requireNonNull()
  • API 활용하자.

1.6 스위치 실패 피하기

switch(user.getRank()) {
    case UNKNOWN:
        cruiseControl.logUnauthorizedAccessAttpemt();
    case ASTRONAUT:
        cruiseControl.grantAccess(user);
        break;
    case COMMANDER:
        cruiseControl.grantAccess(user);
        cruiseControl.grantAdminAccess(user);
        break;        
}

변경

switch(user.getRank()) {
    case UNKNOWN:
        cruiseControl.logUnauthorizedAccessAttpemt();
        break;
    case ASTRONAUT:
        cruiseControl.grantAccess(user);
        break;
    case COMMANDER:
        cruiseControl.grantAccess(user);
        cruiseControl.grantAdminAccess(user);
        break;
}
  • switch문 사용시 break 확인!

1.7 항상 괄호 사용하기

if (user.isUnknown())
    cruiseControl.logUnauthorizedAccessAttpemt();
if (user.isAstronaut())
    cruiseControl.grantAccess(user);
if (user.isCommander())
    cruiseControl.grantAccess(user);
    cruiseControl.grantAdminAccess(user);
  • grantAdminAccess() 메서드 실행된다.

변경

if (user.isUnknown()) {
    cruiseControl.logUnauthorizedAccessAttpemt();
}    
if (user.isAstronaut()) {
    cruiseControl.grantAccess(user);
}
if (user.isCommander()) {
    cruiseControl.grantAccess(user);
    cruiseControl.grantAdminAccess(user);
}
  • 안전하게 괄호를 사용하여 범위를 확인한다.

1.8 코드 대칭 이루기

if (user.isUnknown()) {
    cruiseControl.logUnauthorizedAccessAttpemt();
}    else if (user.isAstronaut()) {
    cruiseControl.grantAccess(user);
} else if (user.isCommander()) {
    cruiseControl.grantAccess(user);
    cruiseControl.grantAdminAccess(user);
}
  • 코드 대치성의 부재
  • 세가지 분기가 비슷한 관심사를 표현? 병렬구조? 모두 대칭인가?

변경

if (user.isUnknown()) {
    cruiseControl.logUnauthorizedAccessAttpemt();
    retrun;
}

if (user.isAstronaut()) {
    cruiseControl.grantAccess(user);
} else if (user.isCommander()) {
    cruiseControl.grantAccess(user);
    cruiseControl.grantAdminAccess(user);
}
  • 권한을 부여하는 코드와 권한을 부여하지 않는 코드로 비대칭성이 생성.
  • 서로 다른 코드 블록으로 분리하면 코드 대치성을 향상시킬수 있다.

 

자바의 코딩의 기술

사이먼 하러, 요르기 레너드, 심누스 디에츠 지음

심지현 옮김

반응형

'JAVA > JAVA 기초' 카테고리의 다른 글

병렬 프로그래밍  (0) 2021.08.18
자바 코딩의 기술 - #2 코딩 스타일  (0) 2020.11.26
자바 코딩 규약  (0) 2019.11.26
Object의 clone() 복사  (0) 2019.03.12
객체의 라이프 사이클  (0) 2018.10.25