8장 방어적 프로그래밍
목차
- 8.1 잘못된 입력으로부터 프로그램 보호
- 8.2 어설션
- 8.3 오류 처리 기법
- 8.4 예외
- 8.5 오류로 인한 손상을 막기 위한 방책
- 8.6 디버깅 보조 도구
- 8.7 얼마나 방어적으로 프로그래밍할 것인지 정하기
- 8.8 방어적 프로그래밍에 대해서 한 번 더 고민하기
8.1 잘못된 입력으로부터 프로그램 보호
'쓰레기를 넣으면 쓰레기가 나온다'라는 말은 개발자에게 어울리지 않는다. '쓰레기를 넣으면 아무것도 나오지 않는다' 또는 '쓰레기를 넣으면 오류 메시지를 출력한다', '쓰레기를 허용하지 않는다'가 되도록 프로그램을 제작하라.
쓰레기 입력을 처리하기 위한 방법으로는
- 외부로부터 들어오는 모든 데이터의 값을 검사하라.
- 루틴의 모든 입력 매개변수 값을 검사하라.
- 잘못된 입력을 어떻게 처리할 것인지를 결정하라.
겉으로 보기에 아주 작은 문제를 예방하면 큰 차이를 만들 수 있다.
8.2 어설션
어설션(Assertion)은 대개 루틴이나 매크로 실행 시 프로그램이 스스로 검사할 수 있도록 사용하는 코드다. 어설션이 참이면 모든 것이 예상대로 작동하고 있다는 것을 의미한다. 어설션이 거짓일 때는 코드에서 예상치 못한 오류가 감지되었다는 뜻이다.
// 어설션 사용법
assertion <조건> : <거짓일 경우 수행문>
어설션은 절대로 발생해서는 안 되는 조건에 대해 사용해야한다. 이는 오류 처리와는 조금 다른데, 루틴의 결과로 나온 리턴값을 검사하는데 사용하는 것이 좋다. 사용자로부터 받거나 외부로부터 전달된 값은 오류 처리 코드를 통해 유효성을 검사하는 것이 어설셜보다 좋다.
8.3 오류 처리 기법
발생할 것이 예상되는 오류를 처리하는 부분이다. 오류가 발생하면 오류 코드를 반환하거나, 오류 메시지를 출력하거나 프로그램을 종료할 수도 있다.
프로그램의 성격에 따라 오류 처리는 다르게 적용되어야 한다. 정확성이 중요시되는 방사능 치료기 같은 경우 잘못된 입력이 들어올 경우 프로그램을 종료하는 것이 가장 좋은 선택일 것이다. 하지만 게임, 텍스트 에디터와 같은 대부분의 프로그램에서는 잘못된 입력이 들어올 경우 이를 다른 값으로 대체하거나, 중립적인 값으로 대체해 프로그램을 계속 진행시키는 것이 좋은 선택이 될 가능성이 높다.
정확성은 프로그램이 정확한 값을 유지하거나 처리해야하는 것을 뜻하고, 견고함은 프로그램이 죽지 않는 것을 뜻한다. 자신의 프로그램이 정확성과 견고함 중 무엇이 더 중요한지를 먼저 결정한 후 오류 처리 방법에 대해 고민하는 것을 추천한다.
8.4 예외
예외는 코드가 오류나 예외적인 이벤트 루틴을 호출한 코드에 전달할 수 있는 특수한 방법이다.
8.5 오류로 인한 손해를 막기 위한 방책
바리게이트는 오류로 인한 손해를 막기 위한 방책 중 하나다. 외부로 부터 들어오는 데이터들은 신뢰할 수 없는 데이터다. 신뢰할 수 없는 데이터를 입력으로 받을 때, 오류 처리를 통해 유효성을 검사한다. 이후 신뢰할 수 있는 데이터들을 내부로 들여보낸다. 유효성을 검사해 신뢰할 수 있는 데이터로 들여보내는 것이 바리게이트다. 외부에서 오는 값들은 충분히 오류가 발생할 수 있으므로 오류 처리 기법을 사용한다. 이후 내부에 들어온 데이터들은 오류가 발생하면 안되는 신뢰할 수 있는 데이터들이다. 이들을 검사하기 위해서는 어설션을 사용하는 것이 일반적이고 이 책에서 추천하는 방법이다.
8.6 디버깅 보조 도구
방어적 프로그래밍의 또 다른 핵심은 오류를 빠르게 발견하는 데 도움이 되는 디버깅 보조 도구를 사용하는 것이다.
8.7 제품 코드를 얼마나 방어적으로 프로그래밍 할 것인지 정하기
방어적 프로그래밍 도구를 제품 코드에 남겨 놓아야 할지, 제거해야 할지를 결정하는데 필요한 지침
- 중요한 오류를 검사하는 코드는 남겨두라.
- 사소한 오류를 검사하는 코드를 제거하라.
- 심각한 충돌을 발생시키는 코드를 제거하라.
- 프로그램이 우아하게 충돌하도록 돕는 코드를 남겨두라.
- 기술 지원을 위해서 오류를 기록한다.
- 오류 메시지가 친절한지 확인한다.
8.8 방어적 프로그래밍에 대해서 한 번 더 고민하기
방어적 프로그래밍이 지나치면 그 자체로 문제를 발생시킨다. 소스코드의 양이 많아지고, 프로그램이 필요 이상으로 비대해진다. 모든 입력에 대해 이를 검사하는 바리게이트를 설정한다면 불필요한 자원을 사용하게 될 가능성이 높다. 방어적일 필요가 있는 부분을 찾고, 그 부분에 대해 방어적 프로그래밍을 적용할 수 있는 실력을 키워야한다.