Code Complete - 8장 [방어적 프로그래밍]

2025. 11. 25. 23:38Book Review

반응형

리뷰 책 링크

 

Code Complete 코드 컴플리트 | 스티브 맥코넬 - 교보문고

Code Complete 코드 컴플리트 | 《Code Complete 2》는 소프트웨어 구현을 둘러싼 다양한 비유부터 기초적인 프로그래밍, 시스템 구축, 소프트웨어 장인정신에 이르기까지 소프트웨어 업계에 종사하는

product.kyobobook.co.kr


요점 및 인상 깊은 문구 정리

  1. 방어적 프로그래밍
    1. 타당하지 않은 데이터와 절대로 발생할 수 없는 이벤트, 다른 개발자의 실수로부터 자신을 보호하기 위한 방법
      1. 프로그램은 언제나 문제가 있고 지속해서 변경할 것이기 때문에 그러한 상황에 대처할 수 있어야 함
  2. 방어적 프로그래밍 기법들
    1. 잘못된 입력으로부터의 프로그램 보호
      1. 쓰레기 입력 시, 출력 결과
        1. 좋은 프로그램
          1. 쓰레기 입력 → 오류 메시지 출력, 쓰레기 허용 불가
        2. 나쁜 프로그램
          1. 쓰레기 입력 → 쓰레기 출력
      2. 쓰레기 입력 처리 방법
        1. 외부로부터 들어오는 모든 데이터 값 검사하기 (허용 가능 범위 측정)
          1. 파일, 사용자, 네트워크, 그 밖의 외부 인터페이스, 문자열
        2. 입력 매개변수 값 검사
        3. 잘못된 입력 어떻게 처리할 지 결정
    2. 어설션 사용
      1. 어설션이란?
        1. 루틴이나 매크로 실행 시 프로그램이 스스로 검사할 수 있도록 하는 코드
          1. 거짓이면 코드에 예상치 못한 오류 감지되었다는 뜻
        2. 코드에서 가정한 것을 문서화하고 예상치 못한 조건을 찾아내기 위해서 어설션을 사용
      2. 어설션 사용 특징
        1. 참이 되어야 하는 조건 표현식과 참이 아닐 경우 표시할 메시지 두 인자를 가짐
        2. 배포되는 코드에서는 어설션 메시지를 사용자에게 보여주지 않음
        3. 제품 코드의 경우 어설션이 컴파일에 포함되지 않으므로 시스템 성능을 떨어뜨리지 않음
      3. 어설션은 언제 사용하는게 좋을까?
        1. 보통 크고 복잡한 프로그램과 높은 신뢰도를 보장해야 하는 프로그램에서 유용
      4. 어설션 사용 지침
        1. 발생이 예상되는 상황은 오류 처리 코드를 사용하고 절대로 발생해서는 안되는 조건에는 어설션 사용
          1. 오류 처리
            1. 잘못된 입력 데이터 검사하는 용도
          2. 어설션
            1. 코드상의 버그를 검사하는 용도
        2. 실행 가능성이 있는 코드를 어설션 내에 입력하지 않기
          1. 어설션 내에 실행해야할 코드를 넣으면 어설션이 컴파일되지 않을 때 사용이 어려워짐
          2. 별도의 줄에 입력해서 사용하도록 하기
        3. 선행 조건, 후행 조건 문서화하고 검증하는 데 어설션 사용하기
          1. 선행 조건
            1. 루틴, 클래스에서 다른 루틴을 호출하거나 객체 생성하기 전에 반드시 참이어야 하는 특성
          2. 후행 조건
            1. 루틴, 클래스를 호출하고 난 후에 반드시 참이어야 하는 조건
    3. 오류 처리 기법
      1. 발생할 것이 예상되는 오류를 처리하는 방법들
        1. 중립적인 값 반환
          1. 잘 알려진 값 반환하기
            1. 수식
              1. 0
            2. 문자열
              1. 빈 문자열
            3. 포인터 연산
              1. 빈 포인터
          2. 예외 경우
            1. 암 환자에게는 부정확한 데이터를 보여주는 것보다 프로그램 종료하는 편이 나음
        2. 다음에 오는 유효한 데이터로 대체
          1. 스트림 혹은 데이터베이스 등에서 간단하게 다음에 오는 유효한 데이터를 반환해도 되는 경우 사용
        3. 이전과 같은 값 반환
          1. 예외
            1. 민감한 데이터에는 사용하지 않기
              1. 은행 거래에서 이전 사용자의 계좌 번호를 사용하고 싶지 않은 것처럼
        4. 가장 가까운 값 반환
        5. 경고 메시지 파일에 기록
          1. 잘못된 데이터 감지 시, 경고 메시지를 파일에 기록한 다음 계속해서 실행하는 방법 선택
        6. 오류 코드 반환
        7. 오류 처리 루틴 혹은 객체 호출
          1. 오류 처리를 전역적인 오류 처리 루틴이나 오류 처리 객체에 집중시키기
      2. 오류 처리 방식
        1. 오류가 발생하는 소프트웨어의 종류에 따라 달라짐
          1. 정확성
            1. 절대로 부정확한 결과를 반환할 수 없음
            2. 부정확한 결과 반환보다는 아무 결과도 반환하지 않는 것이 좋음
            3. 안전성이 중요한 프로그램에 선호됨
          2. 견고함
            1. 부정확한 결과를 만들어 내더라도 소프트웨어가 작동할 수 있도록 애쓰는 것을 의미
            2. 개인용 응용 프로그램에 선호됨
      3. 예외
        1. 오류가 발생한 상황을 인식하지 못하는 코드는 오류 해석하고 도움이 되는 것을 할 수 있는 능력의 시스템에 제어를 넘김
        2. 사용 방법
          1. 정말로 예외적인 경우에만 예외 사용하기
            1. 절대로 일어나서는 안되는 경우에 사용함
          2. 책임 전가를 위해 예외 사용하지 않기
            1. 오류 발생한 코드에서 처리할 수 있다면 직접 처리하는 것이 좋음
          3. 생성자 소멸자에는 예외 던지지 않기
            1. 생성자에서 예외 던지면 소멸자가 호출되지 않기 때문에 리소스 누수가 있을 수 있음
          4. 올바른 추상화 수준에서 오류 던지기
            1. 루틴의 인터페이스에서 일관된 추상화 제공하기
          5. 예외를 발생시킨 모든 정보를 예외 메시지에 포함시키기
          6. 중앙 집중화된 예외 보고 시스템 구축하기
            1. 예외 종류, 예외 처리 방법, 예외 메시지 형식화 등을 해서 중앙 시스템에 예외 모으기
      4. 공격적인 프로그래밍 기법 사용하기
        1. 예의적인 경우는 눈에 띄어야 하고 배포되는 버전의 코드가 실행 중일 때는 복구 가능 방법으로 처리되야 함
        2. 최상의 방어가 좋은 공격임
          1. 개발 중 가혹하게 실패해서 제품에서는 가볍게 실패할 수 있도록 하기
      5. 디버깅 보조 도구 제거하는 계획 세워두기
        1. 버전 관리 도구나 빌드 도구 사용하기
          1. 같은 소스 파일로부터 서로 다른 버전 프로그램 빌드하기
        2. 전처리기 사용하기
          1. c++같은 언어에서는 컴파일러 옵션 변경하여 디버그 코드를 포함하거나 제거 가능
        3. 디버깅 루틴 작성하기
          1. 디버깅 검사를 수행하는 루틴 호출하기

 

느낀점

  • 코드를 작성할 땐 항상 현재의 나만 생각했는데 시간이 지나 다시 보니 과거의 내가 남긴 불친절한 코드에 고생하는 건 결국 미래의 나였음. 방어적 프로그래밍은 단순한 규칙이 아니라, 미래의 나에게 주는 배려인 것을 느낌
  • '설마 이런 값이 들어올까?'라고 생각하지만 그 '설마'가 발생할 수 있음. 방어적 프로그래밍으로 그 '설마'를 미리 대비하여 많은 장애를 예방해야 한다는 것을 느낌
반응형