타당하지 않은 입력으로부터 프로그램의 보호

외부에서 들어오는 모든 데이터의 값을 검사하라 : 문자열이라면 제한된 범위의 값이 맞는지 목적에 맞는 값인지 검사해야 한다

루틴의 모든 입력 매개변수를 검사하라.

잘못된 입력을 어떻게 처리할 것인지 결정하라

 

방어코드 작성의 가장 좋은 형태는 처음부터 오류를 입력하지 않는 것이다. 반복적인 설계, 코드를 작성하기 전에 의사코드 작성, 코드를 작성하기 전에 테스트 케이스 작성, 저수준 설계에 대한 정밀 검사 등은 모 두 결함의 입력을 예방하는 데 도움을 주는 활동들이다.

 

어설션(Assertion)

assertion은 프로그램이 실행될때 스스로를 검사할 수 있도록 개발 도중에 사용되는 코드이며 일반적으로 함수나 매크로로 사용된다.

코드에서 사정한 것들을 문서화하고 예상치 못한 조건을 찾아내기 위해서 assertion을 사용하라

  • 입력(출력) 매개변수의 값이 예상된 범위 안에 들어가는지
  • 파일이나 스트림이 루틴이 시작할때(끝날때) 열려있는지(닫혀있는지)
  • 파일이나 스트림이 루틴이 시작할때(끝날때) 시작(끝)이 있는지.
  • 파일이나 스트림이 읽기전용, 쓰기 전용, 읽기/쓰기 열려있는지
  • 입력만 가능한 변수의 값이 루틴에 의해서 변경되지 않는지
  • 포인터가 널이 아닌지
  • 루틴에 전달되는 배열이나 다른 컨테이너가 적어도 X개의 데이터 요소를 포함할수 있는지
  • 테이블이 실제 값을 포함할수 있도록 초기화되었는지
  • 컨테이너가 루틴이 시작할때(끝날때) 비어있는지(채워)
  • 최적화되어 있고 복잡한 루틴의 결과가 느리지만 분명하게 작성된 루틴과 일치하는지.

 

Assertion사용지침서

절대로 발생해서는 안되는 조건을 위해서 assertion을 써라

실행가능한 코드를 assertion내에 입력하지 않는다.

ex assertion을 위험하게 사용하고 있는 비주얼 베이직 예제

Debug.Assert(PerformAction());

ex. assertion을 안전하게 사용하고 있는 비주얼 베이직 예제

actionPerformed = PerformAction()

Debug.Assert(actionPerformed );

assertion이 실행되지 않아서 작업을 수행하는 코드가 컴파일 되지 않을수 있기때문에 수행하는 함수의 값을 따로 받은 다음에 그것을 assert해야 한다.

선행조건과 후행조건을 문서화하고 검증하기 위하여 assertion을 사용하라

 

오류처리기법

aseertion코드에서 절대로 발생해서는 안되는 오류를 처리하기 위하여 사용된다.

중립적인 값을 리턴해라. : 잘못된 데이터에 대한 가장 좋은 대응은 작업을 계속 수행하고 아무런 문제가 없다고 알려진 값을 리턴하는 것이다. 숙자계산에서는 0을 리턴할 것이고 문자연산에서는 빈 문자열을 리턴할 것이다.

다음에 오는 타당한 데이터로 대체하라

이전과 동일한 값을 리턴하라

가장 가까운 타당한 값으로 대체하라

경고메세지를 파일에 기록하라

오류코드를 리턴하라

오류처리 루틴이나 객체를 호출하라

오류가 발생한 곳에서 오류메세지를 출력하라

지역적으로 가장 잘 작동하는 방법으로 오류를 처리해라

종료하라

 

견고성과 정확성 - 소프트웨어 성격에 따라 달라진다. X레이촬영소프트웨어와 비디오게임이 같을순 없으니 신중하게 생각할 문제.

 

예외

예외는 코드가 오류나 예외적인 이벤트를 루틴을 호출한 코드에 전달할수 있는 특수한 방법이다. 만약에 어떤 루틴에 있는 코드가 어떻게 처리해야 하는지를 모르는 예외적인 상황이 발생하면, 예외를 던진다(throw)

무시되어서는 안되는 오류를 프로그램의 다른 부분에 알리기 위하여 예외를 사용하라.

정말로 예외적인 조건인 경우에만 예외를 던져라

책임을 전가하기 위해서 예외를 사용하지 마라

만약 생성자와 소멸자에서 예외를 잡을수 없다면 생성자와 소멸에서 예외를 던지지 마라

올바른 추상화 수준에서 오류를 던져라

예외를 야기한 모든 정보를 예외 메시지에 포함시켜라 - 비어 있는 catch블록을 피하라

라이브러리 코드가 던지는 예외를 파악하라

집중된 예외 보고자의 구축을 고려하라

 

예외 사용을 규격화해라

  • 프로젝트에서 던지는 모든 예외에 대한 기본 클래스로 사용할수 있도록, 프로젝트에 특화된 예외 클래스의 작성에 대해서 고려해본다. 기록, 오류 보고 등을 집중시키고 규격화할수 있다.
  • 어떤 코드가 지역적으로 오류를 처리하기 위해서 throw-catch문법을 사용할수 있는지에 대하 구체적인 상황을 정의한다
  • 어떤 코드가 지역적으로 처리되지 않는 예외를 던질수 있는지에 대한 구체적인 상황을 정의한ㄷ나
  • 집중된 예외 보고자가 사용될 것인지를 결정한다
  • 예외가 생성자와 소멸자에서 허용되는지 정의한다
  • 예외의 대안들을 고려해보자

 

오류에 의해서 발생하는 손해를 막기 위한 방책

특정한 인터페이스를 '안전한'지역의 경계로써 명시하는 것이다.안전한 지역의 경계를 지나는 데이터의 타당성을 검사하고 만약 데이터가 타당하지 않으면 현명하게 반응한다.

수술실(operating-room)기법이란 것이 있다. 데이터는 수술실에 들어가는 것이 허용되기 전에 살균된다. 수술실에 있는 것은 모두 안전하다고 여겨진다.

 

디버깅.

공격적인 프로그래밍을 사용하라

. 정상적으로 죽은 프로그램이 못쓰게 된 프로그램 보다 낫다.

  • 어설트가 프로그램을 중단하도록 한다. 프로그래머가 알려진 문제를 무시하기 위해서 enter키를 누르는 습관을  갖지 않도록 한다.
  • 할당된 모든 메모리를 완벽하게 채워서 메모리 할당 오류를 발견할수 있도록 한다
  • 파일 형식과 관련된 오류를 발견하기 위해서 할당된 파일이나 스트림을 완벽하게 채운다.
  • case 문의 default절이나 if문의 else 절이 심각한 문제를 일으키거나 (프로그램종료)간과하지 못하도록 한다
  • 객체를 삭제하기 전에 쓰레기 데이터로 채운다
  • 만약 여러분이 개발하고 있는 소프트웨어에 적합하다면, 오류 로그파일을 이메일로 보내도록 프로그램을 설정하여, 배포된 소프트웨어의 어떤 오류가 발생하고 있는지 확인할수 있다.

 

제품 코드 안에 남는 방어적인 프로그래밍 코드 정하기.

중요한 오류를 검사하는 코드는 남겨 놓아라

사소한 오류들을 검사하는 코드를 제거하라.

심각한 충돌을 야기하는 코드를 제거하라.

프로그램이 우아하게 충동하도록 돕는 코드를 남겨두라. - 만약 프로그램의 치명적인 오류를 감지하는 디버깅 코드를 포함하고 있다면, 프로그램이 우아하게 종료할수 있도록 그 코드를 남겨둔다.

기술적인 지원을 위해서 오류를 기록하라. - 제품코드에 디버깅 보조 도구를 남겨놓지만, 작동방식을 변경하지 않는 방법을 고려해본다. 만약 개발시에 프로그램을 중지시키는 aseertion을 코드에 포함시켰다면, 해당 assertion 루틴을 완전히 제거하기보다는 메시지를 파일에 기록할수 있도록 변경하는 것을 고려해볼수 있다.

여러분이 남겨둔 오류메시지가 친절한지 확인한다.

 

요점 정리

  • 제품코드는 쓰레기를 입력하면 쓰레기가 나온다 보다 정교한 방법으로 오류를 처리해야 한다.
  • 방어적인 프로그래밍 기법은 오류를 찾기 쉽고, 수정하기 쉽고, 제품 코드에 덜 손상을 입히도록 만든다
  • assertion은 오류를 초기에 발견하는데 특히, 큰 시스템, 신뢰성이 높은 시스템, 빠르게 코드가 변경되는 경우에 도움을 줄수 있다
  • 잘못도니 입력데이터를 처리하는 방법에 대한 결정은 오류 처리와 고수준 설계에 있어서 핵심적인 결정사항이다
  • 예외는 코드의 정상적인 흐름과 다른 차원에서 오류를 처리하는 방법을 제공한다.
  • 제품 시스템에 적용되는 제약 사항들이 반드시 개발 버전에 적용될 필요는 없다. 여러분은 그러한 사항들을 자신에게 유리하도록 사용할수 있으며, 오류를 빠르게 검출하는데 도움을 주는 코드를 개발 버전에 추가할수 있다.,

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 1. 19. 17:06