17장. 냄새와 휴리스틱

Overview

  • 휴리스틱

    • Heutiskein → '찾아내다', '발견하다’

🌱 발견법 - 간편 추론, 경험을 기반으로 **그때그때 상황과 직관에 따라 행동**하여 결론을 도출하는 것

  • 휴리스틱 알고리즘

    • 최적 해를 보장하지 않는다.

    • Greedy

    • Travelling Salesman Problem


저자의 휴리스틱

주석

🌱 주석은 코드만으로 다하지 못하는 설명을 부언한다.

  1. 부적절한 정보

    • 코드만으로 충분한데 구구절절 설명하는 주석은 없어야 한다.

    i++ // i 증가
    • function signature만 달랑 기술하는 Javadoc은 사용하지 않아야한다.

    /** 
     * @param sellRequest
     * @return
     * @throws ManagedComponentException
     */
    public SellResponse beginSellItem(SellRequest sellRequest)
    throws ManagedComponentException
  2. 주석 처리된 코드

    • 주석 처리된 코드를 발견하면 즉각 지워버려야 한다.

함수

  1. 너무 많은 parameter

    • parameter 개수는 작을수록 좋다. 아예 없는게 가장 좋다!

    • 넷 이상은 최대한 피해야한다.

  2. flag parameter ✨

    • boolean, int, enum 등 플래그 파라미터는 함수가 내부적으로 여러 기능을 수행한다는 뜻

    • 플래그를 넘겨 제어하는 대신, 새로운 함수를 만들자.

  3. 죽은 함수

    • 아무도 호출하지 않는 함수는 삭제해야 한다.


일반

  1. 한 소스 파일에 여러 언어를 사용하는 것

    • 이상적으로는 소스 파일 하나 당, 하나의 언어만 사용해야 한다.

    • 불가피한 경우에 최대한 언어 범위를 줄여야 한다.

  2. 당연한 기능을 구현해라

    • 함수나 클래스는 프로그래머가 당연히 받아들일 수 있는 기능을 제공해야 한다.

  3. 중복✨

    • DRY (Don’t Repeat Yourself)

    • 코드에서 중복을 발견하면, 추상화의 기회이다!

    • 중복 코드 → 하위 루틴이나 클래스로 분리 가능

  4. 올바른 추상화 수준을 설정하기 ✨

    • high level - 집의 형태, 외관, 공간, 방의 배치 (정책)

    • low level - 콘센트, 전등의 위치, 지붕의 크기 등의 기초공사 수준 (세부사항)

    • 의존성 역전 법칙 (DIP) → 집의 형태가 전등의 위치나 색깔에 의해 바뀌어선 안된다. low level이 high level에 의존

    • 기초 클래스 (interface, abstract) 에서 파생 클래스에 의존해서는 안된다.

  5. 기능 욕심

    • 클래스 메서드는 자기 클래스의 상태에 관심을 가져야지, 다른 객체를 조작해서는 안된다.

  6. 부적절한 static 함수

    • Math.max(double a, double b) 는 좋은 static 함수. 모든 정보를 parameter를 통해 가져온다.

    • 재정의 할 가능성이 있는 함수를 static으로 만들어선 안된다. ✨

    • 시급을 계산하는 방법은 언제든 바뀔 수 있다.

  7. 서술적 변수 (Descriptive Variable)

    • 서술적 변수 이름을 사용해서 가독성을 높이자.

    • 변수 이름을 지어보자

      • The total cost of a purchase (totalCost)

      • The total cost of a purchase, including tax (totalCostWithTax)

      • The number of columns in a grid (colNum)

      • The number of rows in a grid (rowNum)

      • The width of a rectangle (rectWidth)

    • 플래그 변수

      • isRaining , isTooHot , hasPassedExam → is , has 또는 contains 와 같은 동사로 시작

      • 변수 이름을 positive 하게 → isNotFull 대신 isEmpty (부정 조건을 피하자)

  8. 명명된 상수로 교체해라! ✨

    • 코드에서 숫자를 사용하지 마라 (숫자는 명명된 상수 뒤로 숨기자)

    • ex) 책의 한 페이지당, 55줄을 인쇄한다 → LINES_PER_PAGE

  9. 조건을 캡슐화 하라

  1. 함수는 한 가지 일만 한다.

  • 세개로 나눌 수 있다.

  1. 시간적인 결합을 드러내라

    • 함수 파라미터를 통해 함수가 호출되는 순서를 드러낼 수 있다.

    • 파라미터를 사용!

  2. 경계 조건은 캡슐화 하라 ✨

    • 경계 조건은 한 곳에서 설정해두고 사용한다.

    • 변수로 캡슐화


Java

  1. 긴 import 목록을 피해라

    • 패키지에서 클래스 둘 이상을 사용한다면 와일드 카드를 사용한다.

  2. 상수는 상속하지 않는다.

    • TENTHS_PER_WEEK, OVERTIME_RATE 상수의 출처는?

    • 부모 클래스?

    • 인터페이스?

      • 계층의 가장 상위에 선언되어 있다.

    • static import 사용 ✨

  3. 상수 vs Enum

    • 주석으로 상수의 의미를 전달,,?

  • 상수들이 많아진다면? 집합을 만들고 싶다.

  • Enum을 활용, 서로 연관된 상수들의 집합

  • 추가 속성 부여 가능


이름

  1. 서술적인 이름을 사용하라

    • 이렇게는 쓰지마라,,

    • 명명법에 신경쓰기

  2. 적절한 추상화 수준에서 이름을 선택하라

    • detail한 구현을 드러내는 이름을 피하라

  3. 이름과 범위는 비례한다

    • 짧은 범위에는 짧은 이름을 사용해도 괜찮다.

  4. 이름에 부수효과를 설명하라

    • 함수, 변수, 클래스가 하는 모든 일을 기술해야 한다.


테스트

  1. 잠재적으로 불안정한 모든 부분을 테스트 해야한다.

  2. 사소한 테스트를 건너뛰지 마라

  3. @Ignore 를 붙여 불분명한 요구사항을 표시하라

  4. 경계 조건을 테스트 하라

  5. 버그 주변은 철저히 테스트하라


  • 주소 값 비교

    • Int

    • Int?

    • ~128 - 127 사이만 캐싱

    • String

  • Marker Interface

    • Serializable

    Untitled
    • 익셉션!

    Untitled
    • Serializable 인터페이스를 구현함으로써 해결

    • writeObject()를 살펴보자

Last updated