Categories

  • uuuuujin

7장 - 컴파일러와의 협업

7.1 컴파일러에 대해 알아보기

  • 정지문제 (halting problem)
    • 런타임 동안 어떤 일이 일어날지 정확히 말할 수 없는 이유
  • 보수적 분석 (conservative analysis)
    • 프로그램이 안전하다고 보장할 수 없는 경우 컴파일러는 프로그램을 허용하지 않음
    • 프로그램에 특정한 실패 가능성이 없다는 것을 보증
    • 장점1) 메서드가 모든 경우에서 return 하는지 확인
    • 장점2) 확정 할당으로 초기화되지 않은 변수에 대한 접근 막음
    • 장점3) 접근 제어로 데이터 캡슐화 지원
      class Class {
          private sensitiveMethod() { }
      }
          
      let c = new Class();
      c.sensitiveMethod();    // 컴파일러 오류 발생
      
    • 장점4) 타입(형) 검사기는 속성을 보증함
    • 약점1) null 참조 <- strict null 검사 웬만하면 해제하지 말 것
    • 약점2) 산술오류
    • 약점3) out of bounds 오류
    • 약점4) 무한루프 체크 못하니까 while대신 for나 forEach 사용하기
    • 약점5) 교착상태, 경쟁상태, 기아상태


7.2 컴파일러 사용

  • 컴파일러 활용
    • 무언가 수정할 때 TODO 리스트로 사용하는 것 -> 컴파일러가 오류 뱉는거 활용
    • 순서 강제화를 이용한 안전성 확보 -> p.201 참고
    • 캡슐화 강제를 통한 안전성 확보 -> 컴파일러의 접근 제어를 사용해서 불변속성 지역화
    • 컴파일러로 사용하지 않는 코드 감지
      • 확정 값을 통한 안전성 확보
        interface NonEmptyList<T> {
            head: T;
        }
            
        class Last<T> implements NonEmptyList<T> {
            constructor(public readonly head: T) {}
        }
            
        class Cons<T> implements NonEmptyList<T> {
          constructor(
            public readonly head: T,
            public readonly tail: NonEmptyList<T>) {}
        }
        
  • 컴파일러 잘못 쓰는 방법 3가지
    1. 타입 잘못 사용하기
      • 형 변환
      • any 사용
      • 컴파일 시간에서 런타임으로 판단에 필요한 정보 옮기기
    2. 게으름
      • 기본값 사용하지 말기
      • 인터페이스에서만 상속받기
      • 처리를 강제한 에외 -> try, catch 사용해서 명시적으로 사용하기
    3. 아키텍처에 대한 이해 부족

7.3 컴파일러 신뢰하기

📌 정상적인 경고의 개수는 0이어야 한다!!! -> 매달 조금씩 줄여보기


7.4 컴파일러만 신뢰할 것

컴파일러는 코드가 우리가 예상하는 문제를 해결할지 여부는 알 수 없지만, 우리가 생각하지 못한 이유로 프로그램이 손상될 수 있는지 여부는 알려줄 수 있음.