태그 보관물: readability

readability

귀찮은 스타일 / 위험한 후 작업을 수행하기 위해 finally 절을 사용합니까? 수있는 간단한 예라는 것을 알고 있지만

Iterator를 작성하는 과정에서 다음 코드를 작성하는 것을 발견했습니다 (오류 처리 중단).

public T next() {
  try {
    return next;
  } finally {
    next = fetcher.fetchNext(next);
  }
}

읽는 것보다 약간 더 읽기 쉽다

public T next() {
  T tmp = next;
  next = fetcher.fetchNext(next);
  return tmp;
}

나는 가독성의 차이가 압도적이지 않을 수있는 간단한 예라는 것을 알고 있지만 예외가없는 경우에 최종 시도를 사용하는 것이 좋지 않은지에 대한 일반적인 견해에 관심이 있습니다. 코드를 단순화 할 때 실제로 선호되는 경우

나쁜 경우 : 왜? 스타일, 성능, 함정, …?

결론
모든 답변에 감사드립니다! 결론은 (적어도 나를 위해) 첫 번째 예제가 일반적인 패턴이라면 더 읽기 쉽지만 그렇지 않다는 결론입니다. 따라서 난독 화 된 예외 흐름과 함께 목적 이외의 구문을 사용하여 도입 된 혼란은 단순화보다 중요합니다.



답변

개인적으로, 나는 명령 쿼리 분리 에 대한 아이디어를 줄 것 입니다. 바로 아래로 가면 next ()에는 두 가지 목적이 있습니다. 다음 요소를 검색하는 광고 목적과 next의 내부 상태를 변경하는 숨겨진 부작용. 그래서, 당신이하고있는 일은 방법의 본문에서 광고 된 목적을 수행 한 다음 finally 절에서 숨겨진 부작용을 시도하는 것입니다. ‘정확하지는 않지만’정확하게 보이지는 않습니다.

이 코드가 실제로 이해하기 쉬운 것은 코드가 얼마나 이해하기 쉬운 지에 대한 것입니다.이 경우 대답은 “meh”입니다. 간단한 return 문을 “시도”한 다음 오류 방지 오류 복구를위한 코드 블록에서 숨겨진 부작용을 실행합니다. 당신이하고있는 일은 ‘영리한’이고, ‘영리한’코드는 종종 관리자들이 “무엇을 … 코드를 읽는 사람들이 “아, 허, 말이 되겠 군.”

그렇다면 상태 돌연변이를 접근 자 호출과 분리하면 어떻게 될까요? 나는 당신이 걱정하는 가독성 문제가 무질서하다고 생각하지만, 그것이 당신의 더 넓은 추상화에 어떤 영향을 미치는지 모르겠습니다. 어쨌든 고려해야 할 것.


답변

순전히 스타일 관점에서, 나는이 세 줄을 생각합니다 :

T current = next;
next = fetcher.getNext();
return current;

… try / finally 블록보다 더 명확하고 짧습니다. 예외가 발생할 것으로 예상하지 않기 때문에 try블록을 사용하면 사람들을 혼란스럽게 할 것입니다.


답변

finally 블록 내부의 코드 목적 에 따라 다릅니다 . 정식 예제는 스트림을 읽거나 쓴 후 스트림을 닫는 것입니다. 항상 “정리”해야합니다. 객체 (이 경우 이터레이터)를 유효한 상태로 복원하면 IMHO도 정리로 계산되므로 여기서 아무런 문제가 없습니다. return반환 값을 찾 자마자 OTOH를 사용 하고 finally 블록에 많은 관련없는 코드를 추가하면 목적이 모호 해지고 이해하기 어려워집니다.

“예외가없는 경우”사용시 아무런 문제가 없습니다. 코드를 던질 수만 있고 처리 할 계획이없는 경우 를 사용 try...finally하지 않고 사용 하는 것이 매우 일반적 입니다. 때때로, 마지막은 단지 보호 책일 뿐이며, 프로그램의 논리에 대해 예외가 발생하지 않는다는 것을 알고 있습니다 (클래식 “이것은 절대로 발생해서는 안됩니다”조건).catchRuntimeException

함정 : try블록 내에서 발생한 예외 는 finally블록을 실행합니다. 일관성이없는 상태가 될 수 있습니다. 따라서 귀하의 반환 진술이 다음과 같은 경우 :

return preProcess(next);

그리고이 코드는 예외 fetchNext가 발생했지만 여전히 실행됩니다. 다음과 같이 코딩하면 OTOH :

T ret = preProcess(next);
next = fetcher.fetchNext(next);
return ret;

그런 다음 실행되지 않습니다. try 코드가 예외를 제기 할 수 없다고 가정하고 있지만 이보다 복잡한 경우 어떻게 확신 할 수 있습니까? 반복자가 오래 지속되는 개체 인 경우 현재 스레드에서 복구 할 수없는 오류가 발생하더라도 항상 유효한 상태로 유지하는 것보다 기존 개체가 계속 유지됩니다. 그렇지 않으면 실제로별로 중요하지 않습니다 …

성능 : 그러한 코드가 어떻게 작동하는지보기 위해 그러한 코드를 디 컴파일하는 것은 흥미로울 것입니다. 그러나 JVM을 충분히 추측하지 못해서 추측 할 수도 있습니다 … 예외는 일반적으로 “예외적”이므로 처리하는 코드는 그것들은 속도에 대해 최적화 될 필요는 없습니다 (따라서 프로그램의 정상적인 제어 흐름에서 예외를 사용하지 않는 충고) finally.


답변

제목 : “… 반환 후 작업을 수행하기위한 마지막 절 …”은 거짓입니다. finally 블록은 함수가 반환되기 전에 발생합니다. 그것이 사실의 요점입니다.

여기서 남용하는 것은 평가 순서이며, 다음 값은 변경하기 전에 반환하기 위해 저장됩니다. 비 연속적으로 코드를 작성하기 때문에 따르기가 훨씬 어렵 기 때문에 일반적인 관행은 아니며 제 생각에는 잘못된 것입니다.

finally 블록의 의도 된 사용은 예외 처리에 관계없이 일부 리소스 정리, DB 연결 종료, 파일 / 소켓 닫기 등과 같은 결과가 발생해야하는 예외 처리에 사용됩니다.


답변

try의 (일반적으로, 귀하의 예제가 아닌) 부분은 예외를 던질 수 있기 때문에 매우 조심스럽게 생각할 것입니다. 원하지 않을 때 실행하십시오.

그리고 다른 웜 캔은 일반적으로 일부 유용한 조치가 마침내 예외를 던질 수 있으므로 실제로는 지저분한 방법으로 끝날 수 있습니다.

이 때문에, 읽는 사람은 이러한 문제에 대해 생각해야하므로 이해하기가 더 어렵습니다.


답변