나는 그것에 대해 생각했고 예를 내놓을 수 없었습니다. 누군가 예외를 잡아서 아무 일도하지 않는 이유는 무엇입니까? 예를 들어 줄 수 있습니까? 어쩌면 절대로해서는 안되는 것일 수도 있습니다.
나는 그것에 대해 생각했고 예를 내놓을 수 없었습니다. 누군가 예외를 잡아서 아무 일도하지 않는 이유는 무엇입니까? 예를 들어 줄 수 있습니까? 어쩌면 절대로해서는 안되는 것일 수도 있습니다.
답변:
나는 D에서 변환 오류와 같은 것들로 항상 그것을합니다.
import std.conv, std.stdio, std.exception;
void main(string[] args) {
enforce(args.length > 1, "Usage: foo.exe filename");
double[] nums;
// Process a text file with one number per line into an array of doubles,
// ignoring any malformed lines.
foreach(line; File(args[1]).byLine()) {
try {
nums ~= to!double(line);
} catch(ConvError) {
// Ignore malformed lines.
}
}
// Do stuff with nums.
}
즉 , 예외가 무시되는 이유 를 설명하는 주석 일지라도 모든 catch 블록에 무언가 가 있어야한다고 생각합니다 .
편집 : 또한 이와 같은 작업을 수행하려는 경우 무시하려는 특정 예외 만 잡아야한다는 것을 강조하고 싶습니다. 평범한 옛날을하는 catch {}
것은 거의 항상 나쁜 일입니다.
아무것도 기록하지 않고 예외를 삼킬 수 있다고 생각하는 한 가지 예는 예외를 로깅하더라도 로깅 코드 자체입니다.
무언가를 기록하려고 시도했지만 예외가 발생하면 할 수있는 일이 많지 않습니다.
그러면 응용 프로그램이 주요 작업을 계속 수행 할 수 있지만 문제 해결 기능이 손상 될 수있는 "최악의 악의"옵션을 사용하여 조용히 삼킬 수 있습니다.
빈 catch
블록은 대부분의 언어에서 코드 냄새입니다. 주요 아이디어는 예외 상황에 예외를 사용하고 논리 제어에 예외를 사용하지 않는 것입니다. 모든 예외는 어딘가에서 처리해야합니다.
이 방법을 사용하면 하나의 특정 응용 프로그램 계층을 프로그래밍 할 때 몇 가지 선택 사항이 있습니다.
이것은 아무것도하지 않고 빈 catch
블록을 위한 공간을 남기지 않습니다 .
추가 편집 : 예외를 던지는 것이 프로그램 로직을 제어하는 일반적인 방법 인 언어로 프로그래밍한다고 가정합니다 (의 대안 중 하나 goto
). 그런 다음 catch
이 언어로 작성된 프로그램의 빈 else
블록은 전통적인 언어 의 빈 블록 과 매우 비슷 합니다 (또는 전혀 else
블록이 없음 ). 그러나 이것이 C #, Java 또는 C ++ 개발 커뮤니티에서 권장하는 프로그래밍 스타일이 아니라고 생각합니다.
어떤 경우에는 Java가 어떤 상황에서도 절대 발생할 수없는 예외를 처리해야합니다. 이 코드를 고려하십시오.
try {
bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}
다음과 같은 표준 문자 집합을 지원하려면 모든 Java 플랫폼 구현이 필요합니다.
...
UTF-8
Java 플랫폼을 중단하지 않으면이 예외를 발생시킬 수있는 방법이 없습니다. 그래서 왜 처리를 귀찮게합니까? 그러나 try-catch-clause를 생략 할 수는 없습니다.
throw new Error(e)
아무것도 놓치지 않았다는 것을 확신하기 위해 추가하고 싶은 유혹이 있습니다 (또는 실제로 깨진 플랫폼을보고합니다).
일반적으로 아닙니다. 스택에 예외를 던지거나 발생한 일을 기록하려고합니다.
그러나 문자열을 구문 분석하고 숫자로 변환 할 때 (특히 한 번만 사용하고 다양성을 버리는 프로젝트를 매핑 할 때) 종종이 작업을 수행합니다.
boolean isNonZeroNumber = false;
try {
if(StringUtils.isNotBlank(s) && new BigDecimal(s).compareTo(BigDecimal.ZERO) != 0) {
b = true;
}
} catch(NumberFormatException e) {
//swallow this exception; b stays false.
}
return b;
어떤 경우에는 예외가 전혀 예외가 아닙니다. 실제로 예상됩니다. 이 예제를 고려하십시오.
/* Check if the process is still alive; exitValue() throws an exception if it is */
try {
p.exitValue();
processPool.remove(p);
}
catch (IllegalThreadStateException e) { /* expected behaviour */ }
java.lang.Process ()에는 isAlive () 메소드가 없기 때문에 아직 살아 있는지 확인하는 유일한 방법은 exitValue ()를 호출하는 것입니다. 프로세스가 여전히 실행 중이면 IllegalThreadStateException이 발생합니다.
내 겸손한 경험에서이 좋은 일이 거의 없습니다. 마일리지는 다를 수 있습니다.
코드베이스에서 이것을 볼 때마다 거의 예외가 숨겨져있는 버그를 추적했기 때문입니다. 달리 말하면, 코드를 제공하지 않음으로써 애플리케이션은 오류를 표시하거나 다른 조치를 수행 할 방법이 없습니다.
예를 들어 API 계층에서 예외를 지나치게하거나 원하지 않을 수 있으므로이 경우 가장 일반적인 것을 시도한 다음 기록하는 경향이 있습니다. 다시 한번, 적어도 디버그 / 진단 세션에 기회를주기 위해.
일반적으로 비어 있어야하는 경우 최소한 내가 일종의 어설 션을 작성하므로 디버그 세션 중에 최소한 무언가가 발생합니다. 즉, 처리 할 수 없으면 완전히 생략하는 경향이 있습니다.
IMO는 빈 catch 문이 괜찮은 곳입니다. 예외가 예상되는 테스트 사례 :
try
{
DoSomething(); //This should throw exception if everything works well
Assert.Fail('Expected exception was not thrown');
}
catch(<whatever exception>)
{
//Expected to get here
}
예외가 발생했을 때 어느 정도의 경고가 표시되지 않는다고 생각하지 않습니다. 프로그래밍 목표 중 하나가 코드를 개선하지 않아야합니까? 예외가 10 %의 시간에 발생하고이를 알지 못하면 예외는 항상 그렇게 나쁘거나 나빠질 수 있습니다.
그러나 코드 처리에서 예외가 실제로 해를 끼치 지 않으면 사용자를 코드에 노출시키는 이유는 다른 쪽입니다. 내가 일반적으로 구현하는 솔루션은 내 로거 클래스 (직장에서 쓰는 모든 단일 클래스에 있음)에 의해 로깅되는 것입니다.
양성 예외 인 경우 Logger의 .Debug () 메서드를 호출합니다. 그렇지 않으면 Logger.Error () (및 (아마도) throw).
try
{
doWork();
}
catch(BenignException x)
{
_log.Debug("Error doing work: " + x.Message);
}
그건 그렇고, 내 로거 구현에서 .Debug () 메서드를 호출하면 App.Config 파일에서 프로그램 실행 로그 수준이 디버그 모드임을 지정하는 경우에만 기록합니다.
존재 확인은 좋은 사용 사례입니다.
// If an exception happens, it doesn't matter. Log the initial value or the new value
function logId(person) {
let id = 'No ID';
try {
id = person.data.id;
} catch {}
console.log(id);
}
또 다른 경우는 finally
절이 사용될 때 입니다.
function getter(obj){}
function objChecker()
{
try
{
/* Check argument length and constructor type */
if (getter.length === 1 && getter.constructor === Function)
{
console.log("Correct implementation");
return true;
}
else
{
console.log("Wrong implementation");
return false;
}
}
catch(e)
{
}
finally
{
console.log(JSON.stringify(getter))
}
}
// Test the override of the getter method
getter = getter;
objChecker();
getter = [];
objChecker();
getter = {};
objChecker();
getter = RegExp;
objChecker();
getter = Function;
objChecker();
ECMAScript에서 이와 유사한 사용 사례와 관련된 catch 바인딩 을 생략 할 수있는 제안 이 있습니다.
참고 문헌
내가 실제로 이와 같은 일을해야 할 유일한 시간은 콘솔 응용 프로그램의 로깅 클래스였습니다. STDOUT에 오류를 발생시키고 파일에 오류를 기록한 다음> 0 오류 코드로 앱을 닫은 최상위 전역 catch 처리기가있었습니다.
여기서 문제는 때때로 파일에 대한 로깅에 실패했다는 것입니다. 디렉토리 권한으로 인해 파일 쓰기가 중단되었으며 파일이 독점적으로 잠겼습니다. 이 경우 예외 세부 정보를 기록하면 로거가 동일한 작업을 수행했기 때문에 다른 곳에서와 같은 방식으로 예외를 처리 할 수 없었습니다 (캐치, 관련 세부 정보 기록, 더 나은 예외 유형으로 랩 등). 이미 실패한 파일에 쓰려고합니다. 그들이 다시 실패하면 ... 내가가는 곳을 봅니다. 무한 루프로 들어갑니다.
try {} 블록 중 일부를 삭제하면 메시지 상자에 예외가 표시 될 수 있습니다 (자동 구성 앱에서는 원하는 것이 아님). 따라서 로그 파일에 쓰는 방법에는 빈 캐치 핸들러가 있습니다. 이것은 여전히 0보다 큰 오류 코드를 얻으므로 오류를 묻지 않으며 무한 루프를 중지하고 앱이 정상적으로 종료되도록합니다.
물론 비어있는 이유를 설명하는 주석이 있습니다.
(이것은 이전에 게시하려고했지만 망각에 타오르는 것을 두려워했습니다. 비록 내가 유일한 사람은 아니기 때문에 ...)
가장 중요한 부분이 무엇이든 끝에 순서에 관계없이 일부 시퀀스를 실행 해야하는 상황에서는 괜찮습니다.
예를 들어. 호스트와 컨트롤러의 모션 제어 통신. 비상 상황에서는 이동을 중단하고, 궤도 생성을 중지하고, 모터를 감속 시키며, 브레이크를 활성화하고, 앰프를 비활성화하기위한 준비 단계가 많이 있습니다.이 후 버스 전원을 차단해야합니다. 모든 단계는 순차적으로 이루어져야하며 단계 중 하나가 실패하면 나머지 단계는 하드웨어 손상의 위험이 허용되는 경우에도 실행되어야합니다. 위의 모든 사항이 실패하더라도 킬 버스 전원은 어쨌든 발생해야합니다.
오류로부터 복구하기 위해 시스템 리소스를 정상적으로 종료
예를 들어. 당신이 사용자에게 피드백을 제공하지 않는 백그라운드에서 서비스를 실행하는 경우 사용자에게 오류의 표시를 밀어 싶지 않을 수도 있지만 않는 우아한 방식으로 사용되는 리소스를 닫아야합니다.
try
{
// execution code here
}
catch(Exception e)
{
// do nothing here
}
finally
{
// close db connection
// close file io resource
// close memory stream
// etc...
}
이상적으로는 디버그 모드에서 catch를 사용하여 오류를 잡아 테스트를 위해 콘솔이나 로그 파일에 인쇄합니다. 프로덕션 환경에서 백그라운드 서비스는 일반적으로 오류가 발생할 때 사용자를 방해하지 않으므로 오류 출력을 억제해야합니다.