앱 충돌 방지를 위해 try / catch 사용


79

필자는 try/catch필요가없는 곳에서도 충돌을 방지하기 위해 자주 사용하는 Android 앱을 개발 하고 있습니다. 예를 들면

의보기는 다음 xml layoutid = toolbar같이 참조됩니다.

// see new example below, this one is just confusing
// it seems like I am asking about empty try/catch
try {
    View view = findViewById(R.id.toolbar);
}
catch(Exception e) {
}

이 접근 방식은 앱 전체에서 사용됩니다. 스택 추적은 인쇄되지 않으며 무엇이 잘못되었는지 찾기가 정말 어렵습니다. 스택 추적을 인쇄하지 않고 앱이 갑자기 종료됩니다.

나는 선배에게 설명 해달라고했고 그는 말했다.

이는 프로덕션에서 충돌을 방지하기위한 것입니다.

나는 그것에 완전히 동의하지 않는다 . 나에게 이것은 앱이 충돌하는 것을 방지하는 방법이 아닙니다. 개발자 자신이 무엇을하는지 모르고 의심 스러움을 보여줍니다 .

이것이 엔터프라이즈 앱이 충돌하는 것을 방지하기 위해 업계에서 사용되는 접근 방식입니까?

경우는 try/catch정말 우리의 필요 다음, 정말이 UI 스레드 또는 다른 스레드 거기 캐치 모든 것에 예외 핸들러를 첨부 할 수 있습니까? 가능하다면 더 나은 접근 방식이 될 것입니다.

예, 비어있는 try/catch것은 좋지 않으며 서버에 스택 추적 또는 로그 예외를 인쇄하더라도 try/catch모든 앱 에서 코드 블록을 무작위로 래핑 하는 것은 나에게 의미가 없습니다 (예 : 모든 함수가 try/catch.

최신 정보

이 질문은 많은 관심을 받고 일부 사람들은 질문을 잘못 해석했기 때문에 (아마도 명확하게 표현하지 않았기 때문에) 나는 그것을 다시 표현할 것입니다.

개발자들이 여기서하는 일입니다.

  • 함수가 작성되고 테스트 되며, 테스트 후 try/catch블록을 감싸는 뷰를 초기화하는 작은 함수이거나 복잡한 함수일 수 있습니다 . 예외를 던지지 않는 함수도 마찬가지입니다.

  • 이 방법은 응용 프로그램 전체에서 사용됩니다. 때로는 스택 추적이 인쇄되고 때로는 debug log임의의 오류 메시지가 표시됩니다. 이 오류 메시지는 개발자마다 다릅니다.

  • 이 접근 방식을 사용하면 앱이 충돌하지 않지만 앱의 동작이 결정되지 않습니다. 가끔은 무엇이 잘못되었는지 따라 가기가 어렵습니다.

  • 내가 물어 본 진짜 질문은 다음과 같습니다. 엔터프라이즈 애플리케이션이 충돌하는 것을 방지하기 위해 업계에서 따르는 관행입니까? 빈 try / catch 에 대해 묻지 않습니다 . 사용자는 예기치 않게 작동하는 응용 프로그램보다 충돌하지 않는 응용 프로그램을 좋아합니까? 그것은 실제로 충돌하거나 사용자에게 빈 화면을 표시하거나 사용자가 인식하지 못하는 동작을 표시하는 것으로 귀결되기 때문입니다.

  • 여기에 실제 코드에서 몇 가지 스 니펫을 게시하고 있습니다.

      private void makeRequestForForgetPassword() {
        try {
            HashMap<String, Object> params = new HashMap<>();
    
            String email= CurrentUserData.msisdn;
            params.put("email", "blabla");
            params.put("new_password", password);
    
            NetworkProcess networkProcessForgetStep = new NetworkProcess(
                serviceCallListenerForgotPasswordStep, ForgotPassword.this);
            networkProcessForgetStep.serviceProcessing(params, 
                Constants.API_FORGOT_PASSWORD);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
     private void languagePopUpDialog(View view) {
        try {
            PopupWindow popupwindow_obj = popupDisplay();
            popupwindow_obj.showAsDropDown(view, -50, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    void reloadActivity() {
        try {
            onCreateProcess();
        } catch (Exception e) {
        }
    }
    

Android 예외 처리 모범 사례의 중복 이 아니며 OP 가이 질문 과 다른 목적으로 예외를 포착하려고합니다 .


11
귀하의 질문에 대답하지,하지만 sliently 예외를 삼키는 결코 catch(Exception e){}- 질문에 대한 편집하기 전에 감각을 만들어이 댓글
무서운 웜뱃


29
아, 악명 높은ON ERROR RESUME NEXT
Deduplicator

의견은 확장 된 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
Bhargav Rao

1
이 질문은 나는 또한 시도 {} 캐치 (예외 e)를 사용하기 때문에 저를 생각했다 {} 많은 시간을 내가 시간이 부족하고 때
라우트 Darpan

답변:


81

물론 규칙에는 항상 예외가 있지만 경험 규칙이 필요하면 맞습니다. 빈 캐치 블록은 "절대적으로"나쁜 습관입니다.

먼저 구체적인 예부터 자세히 살펴 보겠습니다.

try {
  View view = findViewById(R.id.toolbar);
}
catch(Exception e) { }

그래서 무언가에 대한 참조가 생성됩니다. 그리고 그것이 실패 할 때 ... 그것은 중요하지 않습니다; 그 참조는 애초에 사용되지 않기 때문입니다! 위의 코드는 전혀 쓸모없는 라인 노이즈 입니다. 아니면 그 코드를 작성한 사람이 처음에 비슷한 두 번째 호출이 더 이상 예외를 던지지 않을 것이라고 가정합니까?!

아마도 이것은 다음과 같이 보일 것입니다.

try {
  View view = findViewById(R.id.toolbar);
  ... and now do something with that view variable ...
}
catch(Exception e) { }

그러나 이것은 무엇을 도와 주는가?! 코드 내에서 각각 오류 상황을 전파 하기 위한 예외가 존재합니다 . 오류를 무시하는 것은 좋은 생각이 아닙니다. 실제로 예외는 다음과 같은 방식으로 처리 될 수 있습니다.

  • 사용자에게 피드백을 제공합니다. (예 : "입력 한 값이 문자열이 아닙니다. 다시 시도하십시오."); 또는 더 복잡한 오류 처리에 참여
  • 아마도 문제가 예상되는 것이며 완화 될 수 있습니다 (예 : 일부 "원격 검색"이 실패 할 때 "기본"응답을 제공함).
  • ...

간단히 말해서 , 예외로 할 수 있는 최소한의 일은 로그 / 추적입니다. 나중에 일부 문제를 디버깅 할 때 "OK,이 시점에서 예외가 발생했습니다"를 이해할 수 있습니다.

그리고 다른 사람과 같이 뾰족한 밖으로있다 : 당신은 또한에 대한 끼지 않도록 예외 계층에 따라 잘 (일반적으로 : 좋은 몇 가지 캐치해야하는 이유가있을 수 있습니다 예외가 있는지 확인하고, 가장 높은 수준의 오류 심지어 어떤 종류의, 아무것도 분실하지, 지금까지 ).

마지막으로 Ward Cunningham을 인용 해 보겠습니다 .

당신이 읽는 각 루틴이 당신이 기대했던 것과 거의 같을 때 당신은 깨끗한 코드로 작업하고 있다는 것을 알고 있습니다. 코드가 문제의 언어로 만들어진 것처럼 보이게 만들 때 아름다운 코드라고 부를 수 있습니다.

그것에 대해 묵상 해보세요. 깨끗한 코드는 당신을 놀라게 하지 않습니다 . 당신이 우리에게 보여주고있는 예는 보고있는 모든 사람들을 놀라게 합니다.

Update , OP에서 요청하는 업데이트 관련

try {
  do something
}
catch(Exception e) { 
  print stacktrace
}

같은 대답 : "모든 곳에서"그렇게하는 것도 나쁜 습관입니다. 이 코드이기 때문에 또한 독자를 놀라게.

위 :

  • 어딘가에 오류 정보를 인쇄합니다. 그것은이다 전혀없는 이 "어딘가"는 유사 보장 적절한 대상을. 반대로. 예 : 내가 작업중인 애플리케이션 내에서 이러한 호출은 추적 버퍼에 마술처럼 나타납니다. 상황에 따라 애플리케이션은 때때로 이러한 버퍼로 수많은 데이터를 펌핑 할 수 있습니다. 버퍼를 몇 초마다 정리합니다. 따라서 "단순한 인쇄 오류"는 종종 "단순히 모든 오류 정보를 잃어버린 것"으로 해석됩니다.
  • 그런 다음 : 당신이 때문에 당신은 시도 / 캐치하지 않을 수 있습니다 . 코드가 무엇을하는지 이해하기 때문에 그렇게합니다. 그리고 알다시피 : 나는 올바른 일을하기 위해 여기에 try / catch를하는 것이 좋습니다 (내 대답의 첫 부분을 다시 참조하십시오).

그래서, 당신이 보여주는 것처럼 try / catch를 "패턴"으로 사용합니다; 아직 좋은 생각이 아닙니다. 그리고 예, 충돌 을 방지합니다 . 그러나 모든 종류의 "정의되지 않은"동작으로 이어집니다. 알다시피, 예외를 제대로 처리하는 대신 그냥 잡을 때 ; 당신은 벌레 캔을 엽니 다. 나중에 이해하지 못하는 수많은 후속 오류가 발생할 수 있기 때문 입니다. 이전에 "근본 원인"이벤트를 사용했기 때문입니다. 어딘가에 인쇄했습니다. 그리고 그 어딘가 는 이제 사라졌습니다.


1
스택 추적을 인쇄하면 어떻게됩니까? 나는 여전히 여기에서 try / catch가 필요하다고 생각하지 않습니다.
mallaudin

3
나는 당신의 편집을받지 못한다는 것을 인정해야합니다. 당신이 그곳에서 무엇을하고 있는지 진짜 생각이 아닙니다. 또는 당신이 이것으로 얻는 곳.
GhostCat

@mallaudin 일반적인 경우 프로그램을 충돌시키는 줄 이후의 모든 것은 실행되지 않으므로 (obvs) 인쇄는 말도 안됩니다. 이 특정 경우 즉, try + except, 적어도 무언가가 표시되고 예외가 침묵하지 않습니다.
피터 Badida

2
@GhostCat OP는 예외 블록에 이미 로깅 호출이 포함되어 있다는 다른 답변의 주석에 대해 말합니다. 이 질문은 실제로 무슨 일이 일어나고 있는지 잘못 설명하고 있으므로 수석 개발자가 무능하다고 비난하는 것이 여기서 도움이 될 것이라고 생각하지 않습니다. OP가 우리에게주는 것보다 더 많은 일이 일어나고 있다고 생각합니다.
jpmc26

1
@GhostCat 그것은 repo에 관한 것이 아니라 내 예가 나쁘다는 것을 깨달았습니다. 모두가 내가 대해 질문하고 생각 비어 시도 / 캐치
mallaudin

15

로부터 안드로이드 문서 :

다음과 같이 자격을 부여합시다.

일반 예외를 포착하지 마십시오

예외를 잡을 때 게으르고 다음과 같이하는 것도 유혹이 될 수 있습니다.

try {
    someComplicatedIOFunction();        // may throw IOException
    someComplicatedParsingFunction();   // may throw ParsingException
    someComplicatedSecurityFunction();  // may throw SecurityException
    // phew, made it all the way
} catch (Exception e) {                 // I'll just catch all exceptions
    handleError();                      // with one generic handler!
}

거의 모든 경우에 일반 Exception또는 Throwable 을 포착하는 것은 부적절합니다 (오류 예외를 포함하므로 Throwable이 바람직하지 않음). 당신이 (를 포함하여 예상 결코 예외 의미하기 때문에 매우 위험하다 RuntimeExceptions처럼이 ClassCastException) 응용 프로그램 수준 오류 처리에 잡힐.

이는 코드의 오류 처리 속성을 모호 Exception하게 만듭니다. 즉, 호출하는 코드에 누군가 새로운 유형을 추가 하면 컴파일러가 오류를 다르게 처리해야한다는 사실을 깨닫는 데 도움이되지 않습니다 .

일반 예외 포착에 대한 대안 :

  • 한 번의 시도 후 각 예외를 개별 catch 블록으로 개별적으로 catch합니다. 이것은 어색 할 수 있지만 모든 예외를 포착하는 것보다 여전히 바람직합니다.
    저자에 의한 편집 : 이것은 내 선택입니다. catch 블록에서 너무 많은 코드를 반복하지 않도록주의하십시오. Java 7 이상을 사용하는 경우 동일한 catch 블록이 반복되지 않도록 multi-catch를 사용하십시오.
  • 다중 try 블록을 사용하여 더 세분화 된 오류 처리를 갖도록 코드를 리팩터링합니다 . 구문 분석에서 IO를 분리하고 각 경우에 개별적으로 오류를 처리합니다.
  • 예외 다시 던지기 시킵니다. 어쨌든이 수준에서 예외를 잡을 필요가없는 경우가 많습니다. 메소드가 예외를 던지도록하십시오.

대부분의 경우 다른 유형의 예외를 동일한 방식으로 처리해서는 안됩니다.

이 답변의 출처에서 서식 / 단락을 약간 수정했습니다.

PS 예외를 두려워하지 마십시오 !! 그 사람들은 친구들이에요!!!


1
당신이 개별적으로 예외를 잡을 경우, 불확실한 상태에서 실행 (같은 피하기 것을 계속 피하기 위해 확인 Object a; try { a = thing(); } catch (Exception e) {...} try { a.action(); } catch (Exception e) {...}))
njzk2

공정하게 말하면, 제네릭을 잡는 Exception것은 "로그-전-크 래싱"시스템의 일부로 유용 할 수 있지만이 경우에는 다시 던져 져야합니다.
저스틴 시간 - 분석 재개 모니카

9

나는 이것을 다른 답변에 대한 주석으로 넣을 것이지만 아직 그 명성이 없습니다.

당신은 그것이 나쁜 관행이라고 말하는 것이 맞습니다. 사실 당신이 게시 한 것은 예외와 관련하여 다른 유형의 나쁜 관행을 보여줍니다.

  1. 오류 처리 부족
  2. 일반 캐치
  3. 의도적 인 예외 없음
  4. 블랭킷 트라이 / 캐치

이 예를 통해 모든 것을 설명하려고합니다.

try {
   User user = loadUserFromWeb();     
   if(user.getCountry().equals("us")) {  
       enableExtraFields();
   }
   fillFields(user);   
} catch (Exception e) { 
}

이는 다르게 처리해야하는 여러 가지 방법으로 실패 할 수 있습니다.

  1. 필드가 채워지지 않으므로 사용자에게 빈 화면이 표시되고 ... 없음-오류 처리 부족.
  2. 인터넷 문제 또는 서버 자체 문제 (정지, 요청 중단, 전송 손상 등)와 같은 다양한 유형의 오류를 구분할 수 없습니다.-일반적인 캐치.
  3. 현재 시스템이이를 방해하기 때문에 자신의 목적으로 예외를 사용할 수 없습니다. -고의적 예외 없음
  4. 불필요한 오류 (예 : null.equals (...))로 인해 필수 코드가 실행되지 않을 수 있습니다. -블랭킷 트라이 / 캐치

솔루션

(1) 우선, 조용히 실패하는 것은 좋은 일이 아닙니다. 실패하면 앱이 작동하지 않습니다. 대신 문제 해결을 시도하거나 "사용자 데이터를로드 할 수 없습니다. 인터넷에 연결되어 있지 않습니까?"와 같은 경고를 표시해야합니다. 앱이 의도 한대로 작동하지 않는 경우 앱이 자동으로 닫히는 것보다 사용자에게 더 실망 스럽습니다.

(4) 사용자가 불완전한 경우, 예를 들어 국가를 알 수없고 null을 반환합니다. equals 메소드는 NullPointerException을 생성합니다. NPE가 위와 같이 그냥 던져지고 잡히면, 문제없이 실행될 수 있어도 fillFields (user) 메서드가 호출되지 않습니다. 널 검사를 포함하거나 실행 순서를 변경하거나 try / catch 범위를 조정하여이를 방지 할 수 있습니다. (또는 "us".equals (user.getCountry ())와 같이 코딩을 저장할 수 있지만 예제를 제공해야했습니다). 물론 다른 예외는 fillFields ()가 실행되는 것을 방지하지만, 사용자가 없다면 어쨌든 실행하는 것을 원하지 않을 것입니다.

(1, 2, 3) 웹에서로드하면 종종 IOException에서 HttpMessageNotReadable 예외, 심지어 그냥 반환까지 다양한 예외가 발생합니다. 사용자가 인터넷에 연결되지 않았거나 백엔드 서버가 변경되었거나 다운되었을 수 있지만 catch (Exception)를 수행하기 때문에 알 수 없습니다. 대신 특정 예외를 잡아야합니다. 이런 식으로 여러 개를 잡을 수도 있습니다

try{
   User user = loadUserFromWeb(); //throws NoInternetException, ServerNotAvailableException or returns null if user does not exist
   if(user == null) { 
       throw new UserDoesNotExistException(); //there might be better options to solve this, but it highlights how exceptions can be used.
   }
   fillFields(user);
   if("us".equals(user.getCountry()) {
       enableExtraFields();
   }
} catch(NoInternetException e){
    displayWarning("Your internet conneciton is down :(");
} catch(ServerNotAvailableException e){
    displayWarning("Seems like our server is having trouble, try again later.");
} catch(UserDoesNotExistException e){
    startCreateUserActivity();
}

나는 그것이 그것을 설명하기를 바랍니다.

최소한 빠른 수정으로 할 수있는 일은 예외를 제외하고 백엔드에 이벤트를 보내는 것입니다. 예를 들어 firebase 또는 crashlytics를 통해. 이렇게하면 최소한 다음과 같은 것을 볼 수 있습니다 (예 : (4)와 같은 문제로 인해 사용자의 80 %가 주요 활동을로드하지 않습니다.


8

확실히 나쁜 프로그래밍 관행입니다.

현재 시나리오에서 수백 개의 try catch 이와 같은 애플리케이션을 디버깅하지 않고 예외가 어디에서 발생하는지조차 알 수 없습니다. 애플리케이션이 프로덕션 환경에 있다면 악몽입니다.

그러나 로거를 포함하여 예외가 발생하는시기와 이유를 알 수 있습니다. 정상적인 작업 흐름은 변경되지 않습니다.

...
try {
    View view = findViewById(R.id.toolbar);
}catch(Exception e){
    logger.log(Level.SEVERE, "an exception was thrown", e);
}
...

7

이것은 나쁜 습관입니다. 다른 답변은 그렇게 말했지만 뒤로 물러서서 그 이유를 이해하는 것이 중요하다고 생각합니다. 애초에 예외가있는 를 .

모든 기능에는 사후 조건이 있습니다. 있습니다. 함수가 실행 된 후에는 모두 참이어야합니다. 예를 들어, 파일에서 읽는 함수에는 파일의 데이터를 디스크에서 읽어서 반환하는 게시 조건이 있습니다. 그러면 함수가 사후 조건 중 하나를 충족 할 수 없을 때 예외가 발생합니다.

함수에서 예외를 무시하면 (또는 단순히 예외를 로깅하여 효과적으로 무시하는 경우), 실제로 동의 한 모든 작업을 수행하지 않고 해당 함수에 대해 괜찮다고 말하는 것입니다. 이것은 가능성이없는 것 같습니다. 함수가 올바르게 실행되지 않으면 다음이 실행된다는 보장이 전혀 없습니다. 그리고 특정 함수가 완료되었는지 여부에 관계없이 나머지 코드가 제대로 실행되면 처음에 해당 함수가있는 이유가 궁금합니다.

[이제 빈 항목이 catch괜찮은 경우가 있습니다. 예를 들어, 로깅은 빈 캐치로 래핑하는 것을 정당화 할 수있는 것입니다. 일부 로깅을 작성할 수없는 경우에도 애플리케이션이 정상적으로 실행될 것입니다. 하지만 일반 앱에서 찾기 위해 정말 열심히 노력해야하는 특별한 경우입니다.]

요점은 실제로 앱을 계속 실행하지 않기 때문에 나쁜 습관입니다 (이 스타일에 대한 정당화). 기술적으로 OS가 그것을 죽이지 않았을 수도 있습니다. 그러나 단순히 예외를 무시한 후에도 앱이 여전히 제대로 실행될 가능성은 낮습니다. 그리고 최악의 경우 실제로 해를 끼칠 수 있습니다 (예 : 사용자 파일 손상 등).


3

이것은 여러 가지 이유로 좋지 않습니다.

  1. 뭐하는거야 findViewById예외가 발생하는 ? 잡는 대신 그것을 고치십시오 (그리고 이것을 본 적이 없기 때문에 말하십시오).
  2. 잡히지 마 Exception특정 유형의 예외를 할 수있을 때 .
  3. 좋은 앱이 충돌하지 않는다는 믿음이 있습니다. 그건 사실이 아니야. 필요한 경우 좋은 앱이 충돌합니다.

앱이 잘못된 상태가되면 사용할 수없는 상태로 이동하는 것보다 충돌하는 것이 훨씬 좋습니다. NPE를 볼 때 null 수표를 고수하고 떠나서는 안됩니다. 더 나은 접근 방식은 무언가가 null 인 이유를 알아 내고 null이되는 것을 막거나 (null이 유효하고 예상되는 상태가되는 경우) null을 확인하는 것입니다. 그러나 처음에 문제가 발생하는 이유를 이해해야합니다.


2

나는 지난 4-5 년 동안 안드로이드 앱을 개발해 왔으며 뷰 초기화를 위해 try catch를 사용한 적이 없습니다.

툴바가 이렇게하면

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

예 :-보기 (단편 / 대화 상자 / 모든 사용자 정의보기)에서 TextView를 얻으려면

TextView textview = (TextView) view.findViewById(R.id.viewId);

TextView textview = (TextView) view.findViewById (R.id.viewId);

이 대신

View view = findViewById(R.id.toolbar);

보기 개체는 실제보기 유형에 비해 최소 도달 범위가 있습니다.

참고 :-보기가로드 되었기 때문에 충돌 할 수 있습니다. 그러나 try catch를 추가하는 것은 나쁜 습관입니다.


대부분의 경우 뷰를 캐스팅 할 필요가 없습니다. 사용되는 클래스를 정확히 지정하지 않고도 View이미 유용 할 수 있는 몇 가지 메서드 (예 setVisibility():)가 있습니다. (예를 들어, 레이아웃이 수시로 변경되기 쉬운 경우)
njzk2

1

예, try / catch는 앱 충돌을 방지하는 데 사용되지만 질문에 설명 된대로 XML에서 뷰를 가져 오기 위해 try / catch가 필요하지 않습니다.

try / catch는 일반적으로 http 요청을 할 때 사용되며, 문자열을 URL로 구문 분석하고, URL 연결을 생성하는 등 스택 추적을 인쇄해야합니다. 인쇄하지 않는 것은 try / catch로 둘러싸는 데 별 의미가 없습니다.


1

앞서 말했듯이 일반적인 예외는 포착해서는 안되며 최소한 중앙 위치 (일반적으로 애플리케이션 코드가 아닌 프레임 워크 / 인프라 코드에 위치) . 일반 예외를 포착하고 로깅하는 경우 나중에 애플리케이션을 종료하거나 최소한 사용자에게 애플리케이션이 잠재적으로 불안정한 상태에 있고 데이터 손상이 발생할 수 있음을 알려야합니다 (사용자가 계속 실행하도록 선택한 경우). 모든 종류의 예외 (메모리 부족)를 포착하고 앱을 정의되지 않은 상태로두면 이런 일이 발생할 수 있기 때문입니다.

IMHO 예외를 삼키고 데이터 무결성, 데이터 손실의 위험을 감수하거나 앱을 중단하고 사용자가 문제가 발생했음을 알고 다시 시도 할 수 있도록하는 것보다 단순히 앱을 정의되지 않은 상태로 두는 것이 더 나쁩니다. 이것은 또한 더 나은 문제 (문제의 근원에서 더 많이)를보고 할 수 있으며, 사용자가 정의되지 않은 애플리케이션 상태에서 발생하는 모든 종류의 문제를보고하기 시작하는 경우보다 다른 증상이 더 적을 수 있습니다.

중앙 예외 처리 / 로깅 /보고 및 제어 된 종료가 설정되면 예외 처리를 다시 작성하여 가능한 한 구체적으로 로컬 예외를 포착합니다. try {} 블록을 가능한 한 짧게 만드십시오.


1

10 년 이상 기업 모바일 개발 업계에서 일하는 사람으로서 제 관점을 추가하겠습니다. 첫째, 예외에 대한 몇 가지 일반적인 팁, 대부분은 위의 답변에 포함되어 있습니다.

  • 예외는 코드 전체에서 정기적이 아니라 예외적이거나 예상치 못한 또는 통제되지 않은 상황에 사용되어야합니다.
  • 프로그래머는 예외가 발생하기 쉬운 코드 부분을 알고 있어야하며, 예외를 잡아 내고 나머지 코드는 가능한 한 깔끔하게 남겨 두어야합니다.
  • 일반적으로 예외 사항을 조용히 두어서는 안됩니다.

이제 자신을 위해 앱을 개발하지 않고 회사 나 기업을 위해이 주제에 대한 추가 요구 사항에 직면하는 것이 일반적입니다.

  • "앱 충돌은 회사의 이미지가 좋지 않기 때문에 허용되지 않습니다." 그런 다음 신중한 개발을 수행해야하며 가능성이없는 예외도 포착하는 것이 옵션이 될 수 있습니다. 그렇다면 선택적으로 수행하고 합리적인 한도 내에서 유지해야합니다. 그리고 개발이 코드 라인에 관한 것이 아니라는 점에 유의하십시오. 예를 들어 집중적 인 테스트 프로세스는 이러한 경우에 중요합니다. 그러나 회사 앱에서 예상치 못한 동작은 충돌보다 더 나쁩니다. 따라서 앱에서 예외를 포착 할 때마다 수행 할 작업, 표시 할 사항 및 다음에 앱이 어떻게 작동하는지 알아야합니다. 제어 할 수 없다면 앱이 중단되도록하는 것이 좋습니다.
  • "로그 및 스택 추적은 민감한 정보를 콘솔에 덤프 할 수 있습니다. 이는 공격자에게 사용될 수 있으므로 보안상의 이유로 프로덕션 환경에서 사용할 수 없습니다." 이 요구 사항은 개발자가 자동 ​​예외를 작성하지 않는 일반적인 규칙과 충돌하므로 이에 대한 방법을 찾아야합니다. 예를 들어 앱은 환경을 제어 할 수 있으므로 프로덕션 환경을 위해 bugsense, crashlitics 등과 같은 클라우드 기반 도구를 사용하는 동안 비 프로덕션 환경에서 로그 및 스택 추적을 사용합니다.

따라서 짧은 대답은 앱의 품질을 개선하지 않고 유지 관리하는 것이 어렵고 비용이 많이 들기 때문에 찾은 코드가 좋은 사례가 아니라는 것입니다.


1

또 다른 관점은, 매일 엔터프라이즈 소프트웨어를 작성하는 사람으로서 앱에 복구 할 수없는 오류가있는 경우 충돌이 발생하기를 원합니다 . 충돌이 바람직합니다. 충돌하면 기록됩니다. 짧은 시간에 몇 번 이상 충돌이 발생하면 앱이 충돌하고 있다는 이메일을 받고 우리가 사용하는 모든 웹 서비스와 앱이 여전히 작동하는지 확인할 수 있습니다.

그래서 질문 :

이다

try{
  someMethod();
}catch(Exception e){}

좋은 연습? 아니! 다음은 몇 가지 사항입니다.

  1. 가장 중요한 것 : 이것은 나쁜 고객 경험입니다. 나쁜 일이 발생하면 어떻게 알 수 있습니까? 내 고객이 내 앱을 사용하려고하는데 아무것도 작동하지 않습니다. 내 앱이하는 일이 무엇이든 은행 계좌를 확인하거나 청구서를 지불 할 수 없습니다. 내 앱은 완전히 쓸모가 없지만 적어도 충돌하지는 않았습니다! (저의 일부는이 "상위"개발자가 낮은 충돌 수에 대해 브라우니 포인트를 얻었 기 때문에 시스템 게임을하고 있다고 생각합니다.)

  2. 개발을 할 때 잘못된 코드를 작성할 때 최상위 레이어에서 모든 예외를 포착하고 삼키는 경우 로깅이 없습니다. 콘솔에 아무것도없고 앱이 자동으로 실패합니다. 내가 알 수 있듯이 모든 것이 잘 작동하는 것 같습니다. 그래서 나는 코드를 커밋합니다. 내 DAO 개체가 항상 null이었고 고객의 지불은 실제로 DB에서 업데이트되지 않았습니다. 이런! 그러나 내 앱이 충돌하지 않았으므로 플러스입니다.

  3. 악마의 옹호자 역할을하면서 모든 예외를 잡고 삼키는 것이 괜찮다고 가정 해 봅시다. 그것은이다 매우 쉽게 안드로이드에서 사용자 지정 예외 핸들러를 작성 할 수 있습니다. 당신은 정말 그냥하면 모든 예외를 잡기 위해, 당신은 한 곳이 아니라 고추에 그것을 할 수있는 try/catch모든 코드베이스를 통해.

이전에 함께 일한 개발자 중 일부는 충돌이 나쁘다고 생각했습니다.

우리 앱이 충돌 하기를 원한다고 확신해야합니다 . 아니요, 불안정한 앱은 괜찮지 않지만 충돌은 우리가 뭔가 잘못했음을 의미하며이를 수정해야합니다. 크래시가 빠를수록 더 빨리 찾을수록 수정하기가 더 쉽습니다. 내가 생각할 수있는 유일한 다른 옵션은 사용자가 중단 된 세션에서 계속할 수 있도록 허용하는 것입니다. 이는 사용자 기반을 화나게하는 것과 같습니다.


0

catch(Exception e){}본질적으로 오류를 무시 하기 때문에 사용하는 것은 좋지 않습니다 . 아마도 당신이 원하는 것은 다음과 같은 것입니다.

try {
    //run code that could crash here
} catch (Exception e) {
    System.out.println(e.getMessage());
}

0

우리는 거의 동일한 논리를 사용합니다. 사용하다try-catch프로덕션 앱이 충돌하지 않도록하는 데 합니다.

예외는 절대 안됩니다. 무시 . 그것은 나쁜 코딩 습관입니다. 코드를 유지 관리하는 사람들은 기록되지 않은 경우 예외를 발생시킨 코드 부분을 지역화하는 데 정말 어려움을 겪을 것입니다.

Crashlytics예외를 기록하는 데 사용 합니다. 코드는 충돌하지 않지만 일부 기능은 중단됩니다. 그러나 대시 보드에 예외 로그가 표시됩니다 Fabric/Crashlytics. 이러한 로그를보고 예외를 수정할 수 있습니다.

try {
    codeThatCouldRaiseError();
} catch (Exception e) {
    e.printStackTrace();
    Crashlytics.logException(e);
}

예. 그것이 사람들이 여기서하는 일이지만 나는 그것에 동의하지 않습니다. 그래서 제가 질문을 올렸습니다. 좀 더 논리적 인 것을 생각해 낼 수 있습니까?
mallaudin

4
@mallaudin 질문하는 코드를 잘못 나타내는 예제 코드를 게시하지 마십시오. 그것은 당신이 얻는 대답을 크게 바꿀 수 있습니다 .
jpmc26

@ jpmc26 네. 나는 대답에서 그것을 보았다.
mallaudin

0

다른 답변에 동의하지만,이 모티브가 약간만 견딜 수있는 상황이 반복적으로 발생했습니다. 누군가 다음과 같이 클래스에 대해 약간의 코드를 작성했다고 가정합니다.

private int foo=0;

    . . .

public int getFoo() throws SomeException { return foo; }

이 상황에서 'getFoo ()'메소드 는 실패 할 수 없습니다. 항상 개인 필드 'foo'의 합법적 인 값이 반환됩니다. 그러나 누군가-아마도 현학적 인 이유로-이 메소드가 잠재적으로 Exception을 던지는 것으로 선언되어야한다고 결정했습니다. 그런 다음 예외가 발생하는 것을 허용하지 않는 컨텍스트 (예 : 이벤트 처리기)에서이 메서드를 호출하려고하면 기본적으로이 구문을 사용해야합니다 (그런데도 예외를 기록해야한다는 데 동의합니다. 경우) . 이 작업을 수행해야 할 때마다 항상 'catch'절 옆에 'THIS CANNOT OCCUR'라는 큰 주석을 추가합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.