가장 큰 실수는 여전히 더 절차적인 용어로 생각하고 있다는 것입니다. 이것은 사람으로서 당신을 비판하는 것이 아니라 단지 관찰 일뿐입니다. 보다 기능적인 용어로 생각하는 것은 시간과 연습이 필요하기 때문에 메소드가 현재 존재하고 가장 분명한 것처럼 보일 것입니다. 이차적 인 사소한 실수는 메소드 내부에서 Optional을 생성하는 것입니다. 선택 사항은 어떤 것이 값을 반환하거나 반환하지 않을 수 있음을 문서화하는 데 도움이됩니다. 아무것도 얻지 못할 수도 있습니다.
이것은 당신이 완벽하게 합리적으로 보이는 완벽하게 읽을 수있는 코드를 작성하도록 이끌었지만, 당신은 get and isPresent 인 사악한 쌍둥이 유혹에 유혹을 받았습니다.
물론 문제는 빨리 "현재 존재하는 이유는 무엇입니까?"
많은 사람들이 여기서 놓친 것은 isPresent ()는 gosh-darn 유용한 람다가 얼마나 기능적이며 기능적인 것을 좋아하는 사람들이 완전히 탑승 한 사람들이 작성한 새로운 코드를 위해 만들어진 것이 아니라는 것입니다.
그러나 그것은 우리에게 몇 가지 좋은, 위대하고 매력적인 (?) 이점을 제공합니다.
- 새로운 기능을 사용하기 위해 레거시 코드를 쉽게 전환 할 수 있습니다.
- Optional의 학습 곡선을 완화합니다.
첫 번째는 다소 간단합니다.
다음과 같은 API가 있다고 상상해보십시오.
public interface SnickersCounter {
/**
* Provides a proper count of how many snickers have been consumed in total.
*/
public SnickersCount howManySnickersHaveBeenEaten();
/**
* returns the last snickers eaten.<br>
* If no snickers have been eaten null is returned for contrived reasons.
*/
public Snickers lastConsumedSnickers();
}
그리고 당신은 이것을 빈칸으로 채우는 레거시 클래스를 가졌습니다.
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
확실한 예. 그러나 여기서 나와 함께하십시오.
이제 Java 8이 출시되었으며 우리는 탑승을 시작했습니다. 따라서 우리가하는 일 중 하나는 이전 인터페이스를 Optional을 반환하는 것으로 교체하고 싶다는 것입니다. 왜? 다른 사람이 이미 은혜롭게 언급 한 것처럼 : 이것은 무언가가 null 일 수 있는지의 여부를 추측합니다 .
이것은
이미 다른 사람들에 의해 지적되었습니다. 그러나 지금 우리는 문제가 있습니다. 우리가 (무고한 방법으로 alt + F7을 치는 동안 실례합니다), 그렇지 않으면 훌륭한 일을하는 잘 테스트 된 레거시 코드 에서이 방법이 호출되는 곳을 상상해보십시오. 이제이 모든 것을 업데이트해야합니다.
이 곳은 isPresent가 빛나는 곳입니다.
지금 : Snickers lastSnickers = snickersCounter.lastConsumedSnickers (); if (null == lastSnickers) {throw new NoSuchSnickersException (); } else {consumer.giveDiabetes (lastSnickers); }
된다 :
Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers.get());
}
그리고 이것은 당신이 새로운 후배에게 줄 수있는 간단한 변화입니다 : 그는 유용한 무언가를 할 수 있고, 동시에 코드베이스를 탐험하게 될 것입니다. 상생. 결국이 패턴과 비슷한 것이 널리 퍼져 있습니다. 그리고 이제 람다 등을 사용하기 위해 코드를 다시 작성할 필요가 없습니다. (이 특별한 경우에는 사소한 일이지만 독자에게 연습하기가 어려운 예를 생각해 봅니다.)
이는 사용자가 수행 한 방식이 본질적으로 값 비싼 재 작성없이 레거시 코드를 처리하는 방법이라는 것을 의미합니다. 새 코드는 어떻습니까?
글쎄, 당신의 경우에, 당신이 무언가를 인쇄하고 싶을 때, 당신은 간단하게 할 것입니다 :
snickersCounter.lastConsumedSnickers (). ifPresent (System.out :: println);
아주 간단하고 완벽합니다. 그러면 표면까지 천천히 버블 링되는 지점은 get () 및 isPresent ()에 대한 사용 사례가 있다는 것입니다. 새로운 코드를 너무 많이 생각하지 않고도 기존 코드를 기계적으로 수정하여 최신 유형을 사용할 수 있습니다. 따라서 수행중인 작업은 다음과 같은 방식으로 잘못 안내됩니다.
- null을 반환 할 수있는 메서드를 호출하고 있습니다. 올바른 아이디어는 메소드가 널을 리턴한다는 것입니다.
- 람다 환상을 포함하는 맛있는 새로운 방법을 사용하는 대신 레거시 반창고 방법을 사용하여이 옵션을 처리합니다.
Optional을 간단한 null 안전 검사로 사용하려면 다음을 수행해야합니다.
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
물론 이것의 좋은 버전은 다음과 같습니다.
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
그건 그렇고, 꼭 필요한 것은 아니지만 작업마다 새로운 줄을 사용하는 것이 더 쉽기 때문에 읽기 쉽습니다. 읽기 쉽고 이해하기 쉬운 요일 간결함.
이것은 물론 우리가하려는 모든 것을 이해하기 쉬운 매우 간단한 예입니다. 실생활에서 항상 간단한 것은 아닙니다. 그러나이 예에서 우리가 표현하고있는 것이 우리의 의도라는 점을 주목하십시오. 우리는 직원에게 GID와 ID를 부여하고 가능하면 인쇄하고 싶습니다. 이것은 Optional의 두 번째 큰 승리입니다. 보다 명확한 코드를 만들 수 있습니다. 또한 맵에 피드를 제공 할 수 있도록 많은 것들을 수행하는 메소드를 만드는 것과 같은 일을하는 것이 일반적으로 좋은 생각이라고 생각합니다.