Skip to content

Latest commit

 

History

History
329 lines (190 loc) · 10.9 KB

ch17_heuristics.md

File metadata and controls

329 lines (190 loc) · 10.9 KB

💡 주석

부적절한 정보

  • 주석은 코드와 설계에 기술적인 설명을 부연하는 수단이다.
  • 일반적으로 메타 정보만 주석으로 넣는다.
  • 다른 시스템에 저장할 정보는 주석으로 적절하지 못하다.

쓸모 없는 주석

  • 오래된 주석, 엉뚱한 주석, 잘못된 주석은 쓸모 없다.
  • 쓸모 없어진 주석은 재빨리 삭제하는 편이 좋다.

중복된 주석

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

성의 없는 주석

  • 단어를 신중하게 선택한다.
  • 문법과 구두점을 올바로 사용한다.
  • 주절대지 않는다.
  • 당연한 소리를 반복하지 않는다.
  • 간결하고 명료하게 작성한다.

주석 처리된 코드

  • 주석으로 처리된 코드를 발견하면 즉각 지우자.
  • 누군가 정말 필요하다면 이전 버전을 가져오면 된다.

💡 환경

여러 단계로 빌드해야 한다.

  • 빌드는 간단히 한 단계로 끝나야 한다.
  • 소스 코드 관리 시스템에서 이것저것 따로따로 체크아웃할 필요가 없어야 한다.
  • 한 명령으로 전체를 체크아웃해서 한 명령으로 빌드할 수 있어야 한다.

여러 단계로 테스트해야 한다.

  • 모든 단위 테스트는 한 명령으로 돌려야 한다.
  • IDE에서 버튼 하나로 모든 테스트를 돌린다면 가장 이상적이다.
  • 모든 테스트를 한 번에 실행하는 능력은 아주 근본적이고 중요하다.

💡 함수

너무 많은 인수

  • 함수에서 인수 개수는 작을수록 좋다.
  • 아예 없으면 좋다.
  • 넷 이상은 그 가치가 아주 의심스러우므로 최대한 피한다.

출력 인수

  • 출력 인수는 직관을 정면으로 위배한다.
  • 함수에서 뭔가 상태를 변경해야 한다면 함수가 속한 객체의 상태를 변경한다.

플래그 인수

  • 플래그 인수는 혼란을 초래하므로 피해야 마땅하다.

    (boolean 인수는 함수가 여러 기능을 수행한다는 증거)

죽은 함수

  • 아무도 호출하지 않는 함수는 삭제한다.
  • 과감히 삭제하라.

💡 일반

한 소스 파일에 여러 언어를 사용한다

  • 이상적으로는 소스 파일 하나에 언어 하나만 사용하는 방식이 가장 좋다.

당연한 동작을 구현하지 않는다

  • 최소 놀람의 원칙에 의거해 함수나 클래스는 다른 프로그래머가 당연하게 여길 만한 동작과 기능을 제공해야 한다.
  • 당연한 동작을 구현하지 않으면 코드를 읽거나 사용하는 사람이 더 이상 함수 이름만으로 함수 기능을 직관적으로 예상하기 어렵다.

경계를 올바로 처리하지 않는다

  • 코드는 올바로 동작해야 한다.
  • 모든 경계 조건을 찾아내고, 모든 경계 조건을 테스트하는 테스트 케이스를 작성하라.

안전 절차 무시

  • 안전 절차를 무시하면 위험하다.

중복

  • DRY 원칙
  • 코드에서 중복을 발견할 때마다 추상화할 기회로 간주하라.
  • 중복된 코드를 하위 루틴이나 다른 클래스로 분리하라.
  • 어디서든 중복을 발견하면 없애라.

추상화 수준이 올바르지 못하다

  • 추상화는 저차원 상세 개념에서 고차원 일반 개념을 분리한다.
  • 고차원 개념과 저차원 개념을 섞어서는 안된다.

기초 클래스가 파생 클래스에 의존한다

  • 기초 클래스와 파생 클래스로 개념을 나누는 이유
    • 고차원 기초 클래스 개념을 저차원 파생 클래스 개념으로부터 분리해 독립성을 보장하기 위해서
  • 기초 클래스는 파생 클래스를 몰라야 마땅하다.

과도한 정보

  • 잘 정의된 모듈은 인터페이스가 아주 작다.
  • 클래스나 모듈 인터페이스에 노출할 함수를 제한할 줄 알아야 한다.
  • 자료를 숨겨라
  • 유틸리티 함수를 숨겨라
  • 상수와 임시 변수를 숨겨라
  • 메서드나 인스턴스 변수가 넘쳐나는 클래스는 피하라
  • 하위 클래스에서 빌요하다는 이유로 protected변수나 함수를 마구 생성하지 마라
  • 인터페이스를 매우 작게 그리고 매우 깐깐하게 만들어라
  • 정보를 제한해 결합도를 낮춰라

죽은 코드

  • 죽은 코드는 시간이 지나면 악취를 풍기기 시작한다.
  • 죽은 코드는 설계가 변해도 제대로 수정되지 않는다.
  • 죽은 코드는 시스템에서 제거하라.

수직 분리

  • 변수와 함수는 사용되는 위치에 가깝게 정의한다.
  • 지역 변수는 처음으로 사용하기 직전에 선언하며 수직으로 가까운 곳에 위치해야 한다.
  • 비공개 함수는 처음으로 호출한 직후에 정의한다.

일관성 부족

  • 어떤 개념을 특정 방식으로 구현했다면 유사한 개념도 같은 방식으로 구현한다.

잡동사니

  • 비어 있는 기본 생성자는 쓸데없이 코드만 복잡하게 만든다.
  • 소스코드는 언제나 깔끔하게 정리하라! 잡동사니를 없애라! (사용하지 않는 변수, 호출하지 않는 함수, 정보 제공 없는 주석 등)

인위적 결합

  • 서로 무관한 개념을 인위적으로 결합하지 않는다.

기능 욕심

  • 마틴 파울러가 말하는 코드 냄새 중 하나
  • 클래스 메서드는 자기 클래스의 변수와 함수에 관심을 가져야지 다른 클래스의 변수와 함수에 관심을 가져서는 안된다.

선택자 인수

  • 선택자 인수는 목적을 기억하기 어려울 뿐 아니라 각 선택자 인수가 여러 함수를 하나로 조합한다.
  • 함수 동작을 제어하려는 인수는 하나 같이 바람직하지 않다.
  • 인수를 넘겨 동작을 선택하는 대신 새로운 함수를 만드는 편이 좋다.

모호한 의도

  • 코드를 짤 때는 의도를 최대한 분명히 밝힌다.

잘못 지운 책임

부적절한 static 함수

  • static 함수보다 인스턴스 함수가 더 좋다.

서술적 변수

  • 서술적인 변수 이름은 많이 써도 괜찮다.

이름과 기능이 일치하는 함수

  • 더 좋은 이름으로 바꾸거나 아니면 더 좋은 이름을 붙이기 쉽도록 기능을 정리해야 한다.

알고리즘을 이해하라

  • 알고리즘이 올바르다는 사슬을 확인하고 이해하려면 기능이 뻔히 보일 정도로 함수를 깔끔하고 명확하게 재구성하는 방법이 최고다.

논리적 의존성은 물리적으로 드러내라

  • 한 모듈이 다른 모듈에 의존한다면 물리적인 의존성도 있어야 한다.
  • 의존하는 모든 정보를 명시적으로 요청하는 편이 좋다.

if/else 혹은 switch/case 문보다는 다형성을 사용하라

표준 표기법을 따르라

  • 팀이 정한 표준은 팀원들 모두가 따라야 한다.

매직 숫자는 명명된 상수로 교체하라

정확하라

  • 코드에서 뭔가를 결정할 때는 정확히 결정한다.

관례보다 구조를 사용하라

  • 명명 관례도 좋지만 구조 자체도 강제하면 더 좋다.

조건을 캡슐화하라

  • 조건의 의도를 분명히 밝히는 함수로 표현하라.

부정 조건은 피하라

  • 부정 조건은 긍정 조건보다 이해하기 어렵다.
  • 가능하면 긍정 조건으로 표현한다.

함수는 한 가지만 해야 한다

  • 한 가지만 수행하는 더 작은 함수 여러 개로 나눠야 마땅하다.

숨겨진 시간적인 결합

  • 때로는 시간적인 결합이 필요하다. 하지만 시간적인 결합을 숨겨서는 안 된다.

일관성을 유지하라

  • 코드 구조를 잡을 때 이유를 고민하라
  • 그 이유를 코드 구조로 명백히 표현하라
  • 시스템 전반에 걸쳐 구조가 일관성이 있다면 남들도 일관성을 따르고 보존한다.

경계 조건을 캡슐화하라

  • 경계 조건은 변수로 캡슐화하는 편이 좋다.

함수는 추상화 수준을 한 단계만 내려가야 한다

  • 함수 내 모든 문장은 추상화 수준이 동일해야 한다. 그리고 그 추상화 수준은 함수 이름이 의미하는 작업보다 한 단계만 낮아야 한다.
  • 추상화 수준 분리는 리팩터링을 수행하는 가장 중요한 이유 중 하나다.

설정 정보는 최상위 단계에 둬라

  • 추상화 최상위 단계에 둬야 할 기본값 상수나 설정 관련 상수를 저차원 함수에 숨겨서는 안 된다.
  • 대신 고차원 함수에서 저차원 함수를 호출할 때 인수로 넘긴다.

추이적 탐색을 피하라

  • 한 모듈은 주변 모듈을 모를수록 좋다.
  • 디미터의 법칙

💡 자바

긴 import 목록을 피하고 와일드카드 * 를 사용하라

상수는 상속하지 않는다

상수 대 Enum

  • enum은 이름이 부여된 열거체이다.
  • 훨씬 더 유연하고 서술적인 강력한 도구이다.

💡 이름

서술적인 이름을 사용하라

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

가능하다면 표준 명명법을 사용하라

명확한 이름

  • 함수나 변수의 목적을 명확히 밝히는 이름을 선택한다.

긴 범위는 긴 이름을 사용하라

  • 이름 길이는 범위 길이에 비례해야 한다.

인코딩을 피하라

  • 이름에 유형 정보나 범위 정보를 넣어서는 안 된다.

이름으로 부수 효과를 설명하라

  • 함수, 변수, 클래스가 하는 일을 모두 기술하는 이름을 사용한다.

💡 테스트

불충분한 테스트

  • 테스트 케이스는 잠재적으로 깨질 만한 부분을 모두 테스트해야 한다.
  • 테스트 케이스가 확인하지 않는 조건이나 검증하지 않는 계산이 있다면 그 테스트는 불완전하다.

커버리지 도구를 사용하라

  • 커버리지 도구는 테스트가 빠트리는 공백을 알려준다.

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

  • 사소한 테스트가 제공하는 문서적 가치는 구현에 드는 비용을 넘어선다.

무시한 테스트는 모호함을 뜻한다

경계 조건을 테스트하라

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

  • 한 함수에서 버그를 발견했다면 그 함수를 철저히 테스트하는 편이 좋다.

실패 패턴을 살펴라

  • 테스트 케이스가 실패하는 패턴으로 문제를 진단할 수 있다.

테스트 커버리지 패턴을 살펴라

  • 통과하는 테스트가 실행하거나 실행하지 않는 코드를 살펴보면 실패하는 테스트 케이스의 실패 원인이 드러난다.

테스트는 빨라야 한다

  • 느린 테스트 케이스는 실행하지 않게 된다.
  • 테스트 케이스가 빨리돌아가게 최대한 노력한다.

💡 전문가 정신과 장인 정신은 가치에서 나온다. 그 가치에 기반한 규율과 절제가 필요하다.