체스를 구현하던중 Optional 에 대해서 알게 되었다.
Optional 의 등장배경
Optional 은 null 로 인해 발생하는 문제 때문에 등장하게 되었다.
메서드의 반환값으로 null 이 반환될 수 있고, 때문에 에러가 발생될 가능성이 높은 상황이라면 사용하자는 취지이다.
백문이 불여일견
코드로 살펴보자.
Optional 적용 전
체스의 메소드 중 체스판의 좌표(Position)에 해당하는 체스말(Piece)을 찾는 메소드가 있었다.
1 2 3 4 5 6 | public Piece findPieceByPosition(Position position) { return pieces.stream() .filter(x -> x.isEqualPosition(position)) .findAny() .orElse(null); } |
그리고 아래의 코드는 체스말을 이동시킬 때 목적지점에 같은팀 체스말이 있는지 확인하는 코드이다.
1 2 3 4 5 6 7 8 9 10 11 | private void validateTargetTeam(Position sourcePosition, Position targetPosition) { Piece sourcePiece = findPieceByPosition(sourcePosition); Piece targetPiece = findPieceByPosition(targetPosition); if (targetPiece != null){ return; } if (sourcePice.isSameTeam(targetPiece) { throw new IllegalArgumentException("해당 칸에 같은 팀의 말이 존재 합니다"); } } |
위의 코드를 살펴보면 sourcePiece 가 null 일때 NullPointException이 발생된다.
실수로 sourcePiece가 null 일 때의 처리를 누락한것이다.
그리고 누구나 이런 실수를 범한적이 있을 것이다.
또한 매번 null 체크를 해주다보면 코드가 지저분해지는 경우도 있다.
이런 상황에서 Optional 을 사용할 수 있다.
Optional 적용 후
먼저 좌표로 체스말을 찾는 메소드는 다음과 같다.
1 2 3 4 5 | public Optional<Piece> findPieceByPosition(Position position) { return pieces.stream() .filter(x -> x.isEqualPosition(position)) .findAny(); } |
반환형은 Optional<Piece>이다.
만약 입력한 좌표에 체스말이 있다면 체스말이 값으로 들어있는 Optional 객체가 반환된다.
반대로 입력한 좌표에 체스말이 없다면 값이 없는 텅빈 Optional 객체가 반환된다.
그렇다면 이를 이용한 메소드들은 어떻게 리펙토링 될 수 있을까?
다음은 목적지점에 있는 체스말의 팀을 체크하는 메소드를 리펙토링한 것이다.
1 2 3 4 5 6 7 8 9 10 | private void validateTargetTeam(Position sourcePosition, Position targetPosition) { Piece sourcePiece = findPieceByPosition(sourcePosition) .orElseThorw(() -> new IllegalArgumentException("해당 칸에 움직일 말이 없습니다")); findPieceByPosition(targetPosition) .filter(target -> sourcePiece.isSameTeam(target)) .ifPresent(piece -> { throw new IllegalArgumentException("해당 칸에 같은 팀의 말이 존재 합니다") }); } |
위 코드의 특징으로는 먼저 null 체크를 하는 조건문이 없다.
그리고 Optional 사용 전에는 실수로 sourcePiece의 null 체크를 놓쳤지만 여기에서는 NullPointException 이 발생할 일이 없다.
코드도 깔끔해져 가독성이 높아진것 같다.
정리
이처럼 null 이 발생할 가능성이 있는 부분에서 Optional 을 사용해주니 여러가지고 장점이 많은 것 같다.
귀찮은 null 체크도 안해도 되고,
그러다 보니 실수가 줄고,
코드도 깔끔해지니 여러가지로 유용하다.
'Java' 카테고리의 다른 글
람다 표현식을 활용한 디자인패턴 - 템플릿 메서드 (0) | 2020.04.08 |
---|---|
람다 표현식을 활용한 디자인패턴 - 전략 패턴 (0) | 2020.04.08 |
스트림 활용 정리 (0) | 2020.04.04 |
스트림 기본 정리 (0) | 2020.04.04 |
인터페이스, Interface (0) | 2020.02.17 |