클린코드 5~9장

HR·2023년 1월 5일
0

목록 보기
2/2

[5장] 깨끗한 코드

1) 적절한 행 길이

200줄 미만의 길이로도 충분하다. 일반적으로 작은 파일이 큰 파일보다 이해하기 쉽다. 이는 단일 책임 원칙 (SRP)과, 높은 응집도와도 연관된다.

2) 로직과 변수의 거리

서로 밀접한 개념들은 하나의 파일에 있는 것이 마땅하고, 세로 거리로 가까이에 위치시켜야 한다.
변수 또한 사용하는 위치에 최대한 가깝게 선언한다.

이 조각 저 조각들의 위치를 기억하며 시스템을 파악하는 것은 굉장히 수고스러운 일이다.


[6장] 객체와 자료구조

1) 클래스와 추상화

구현을 내부에 숨겨 추상화하면, 사용자가 구현의 핵심을 몰라도 자료를 조작할 수 있다. 클래스를 설계할 때에는 단순한 조회/설정 함수만 사용하는 것이 아닌, 객체가 포함하는 자료들을 어떻게 표현할 것인지 고민해야 한다.

2) getter와 setter

타입스크립트에서 객체 내부의 속성 값을 접근할 때에, 직접적인 접근보다는 gettersetter를 통해 캡슐화된 객체에 접근하는 것이 좋다.

이런 방식을 사용하면 아래와 같은 장점이 있다.

  • set을 사용할 때, 일관된 유효성 검사 처리가 가능합니다.
  • 로그 기록과 에러 처리가 용이하다.

3) 불변성

예상치 못한 값의 변경을 막기 위해, typescript에서 지원하는 readonly속성을 이용할 수 있다. 해당 속성을 이용하면, 변수를 읽기 전용으로 설정한다.

interface Config {
  readonly host: string;
  readonly port: string;
  readonly db: string;
}

값 자체를 변경하는 concatslice등은 사용 가능하지만, push, fill과 같은 값에 변경이 생길 가능성이 있는 연산은 불가능하다.

4) 메소드 체이닝

클래스를 사용하면, 메소드 체이닝을 사용할 수 있다.

하나의 클래스 내부의 다양한 메소드들을 사용하려면, 일반적으로는 아래와 같이 사용할 수 있다.

class Demo {
  sort() {
    sort logic
  }
  
  change() {
    change logic
  }
  
  handle() {
    handle logic
  }
  
  submit() {
    submit logic
  }
}

const d = new Demo();
d.change();
d.sort();
d.submit();

위의 함수를 메소드 체이닝을 이용하면, 아래와 같이 변경될 수 있다.

class Demo {
  sort(): this {
    sort logic
    
    return this;
  }
  
  change(): this {
    change logic
    
	return this;
  }
  
  handle(): this {
    handle logic
    
    return this;
  }
  
  submit() {
    submit logic
  }
}

const d = new Demo()
				.change();
				.sort();
				.submit();

[7장] 오류 처리

1) 에러 처리의 필요성

깨끗한 코드안전한 코드는 서로 상충하지 않는 개념이다. 오류 처리 로직에 의해 기존 프로그램 로직의 이해가 어려워 진다면 에러 처리를 프로그램 로직과 분리하여 관리하면 좋은 코드를 작성할 수 있으며, 유지보수성도 높아진다.

2) 에러는 에러 타입으로

에러가 발생한다면(ex. promise의 reject), throw new Erorr()를 통해 에러 타입으로 반환하는 것이 좋다.
이유는 다음과 같다.

  • 상위 코드의 catch에서 감지된다.
  • 에러 stack이 반환되어 에러를 추적할 수 있다.

3) null을 조심하자

대부분의 언어는 실수로 넘어온 null을 처리할 수 있는 좋은 방법이 없다. 따라서 null을 넘겨주지 않도록 주의해야 한다.


[8장] 경계

1) 외부 코드를 올바르게 사용하기

개발을 하다 보면 외부 코드를 사용하게 될 일이 많다.
하지만 외부 코드는 익히거나 통합하는 데에 시간이 굉장히 오래 걸리고, 발생한 버그가 나의 코드인지 외부 코드인지 파악이 어려워 디버깅에도 어려움이 생긴다.

따라서 외부 코드를 사용하기 전에, 문서를 충분히 읽어 사용법을 숙지하고, 테스트를 통해 원하는 결과가 나오는지 확인해봐야 한다. 이를 학습 테스트라 한다.


[9장] 단위 테스트

1) 테스트의 필요성

돌아가는 코드가 아닌, 제대로 돌아가는 코드를 작성하기 위해서.
테스트가 없다면, 추가되는 모든 코드는 잠정적 버그와 같다.
테스트가 있다면 변경에 대한 공포가 사라진다.

2) TDD의 세가지 법칙

1. 실패하는 단위 테스트를 작성할 때까지 코드를 작성하지 않는다.
2. 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
3. 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.

3) 좋은 테스트 코드

가독성, 유지보수성, 명료성, 단순성
테스트 코드의 퀄리티는 곧 다른 코드의 퀄리티로 이어진다.
하나의 테스트에는 하나의 개념, 하나의 assert만 존재해야 한다.
DSL(도메인 특화 언어)를 이용하면 테스트 코드를 작성하기 쉽다.

4) F.I.R.S.T.

First
테스트는 빨라야 한다.

Independent
각 테스트는 서로 의존하면 안 된다. 각 테스트는 독립적으로, 순서에 관계없이 실행될 수 있어야 한다.

Repeatable
테스트는 어떤 환경에서도 실행할 수 있어야 하고, 반복 가능해야 한다.
테스트가 실패하는 데에 환경이 이유가 되어서는 안된다.

Self-Validating
테스트의 결과는 boolean 값이어야 한다. 성공 또는 실패를 결과로 내야 한다는 뜻이다. 이렇게 되지 않으면 판단은 주관적이 되고, 수작업이 따라오게 된다.

Timely
테스트는 적절한 시기에 작성되어야 한다. 실제 코드 작성 이후 테스트 코드를 작성하게 되면 테스트가 어려워질 가능성이 높다.

0개의 댓글