Contents

클린코드

나쁜 코드는 개발 속도를 크게 떨어뜨린다.

코드를 고칠 때마다 엉뚱한 곳에서 문제가 생긴다

Boy Scout Rule : 캠핑장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라

클린 코드는 단순하고 직접적이다 - 잘 쓴 문장처럼 읽힌다 클린 코드는 읽기 좋아야 한다 - 문학적이어야 한다

Meaningful Names

의도가 드러나는 이름들을 사용하자

  • list1 -> flaggedCells
  • theList -> gameBoard

그릇된 정보를 피하자

  • l이나 O는 가급적 피하자

의미 있게 구분하자

  • copyChars() 메서드 파리미터의 a1 , a2 배열은 각각 무엇인지?

발음하기 쉬운 이름을 사용하자

  • DtaRcrd -> generationTimestamp
  • pszqint -> recordId

검색하기 쉬운 이름을 사용하자

  • i, j, t[j] -> 코드 상 의미 있는 변수 (NUMBER_OF_TASKS 등)

헝가리식 표기법 인코딩을 피하자

  • phoneString -> phone
  • 과거에는 변수 타입을 찾기 어려워서 이런 네이밍 차용했지만 이제는 IDE가 해줌

멤버 변수 접두어 인코딩을 피하자

  • m_dsc -> description
  • 멤버 변수 또한 이제는 IDE가 해줌

자신의 기억력을 자랑하지 말자

  • for문의 a, b -> i, j

클래스 이름은 명사나 명사구로 하자

  • Manager, Processor, Data, Info -> Customer, WikiPage, Account, AddressParser

메소드 이름은 동사나 동사구로 하자

  • getName(), fromRealNumber()

개념 하나에 단어 하나를 사용하자

  • fetch, retrieve, get, controller, manager, driver -> 하나로 통일하는게 좋음

말장난을 하지 말자

  • add -> 하나의 단어로 여러 기능을 사용하는 것보다는 insert, append 등 다른 단어로 사용 권장

도메인 영역에서 사용하는 이름을 사용하자

  • Visitor 패턴, JobQueue 용어는 친숙하다

의미 있는 컨텍스트를 추가하자

  • state -> 하나만 보고서는 주소의 일부라는 것을 알기 어렵다
  • 접두어 addr을 붙인다면?
  • Address 클래스를 생성하고 위 변수들을 필드로 넣는다면?

불필요한 컨텍스트를 제거하자

  • AccountAddress, CustomerAddress -> 클래스 이름으로는 부적합
  • MAC addresses, port addresses, Web addresses -> PostalAddress, MAC, URI

Functions

작게 만들자

  • 가로 < 150자, 세로 < 20줄

한 가지만 하자

  • 함수는 한 가지를 해야 한다. 그 한 가지를 잘 해야 한다.

함수 당 추상화 수준은 하나로 하자

  • getHtml() -> 고수준의 추상화
  • PathParser.render(pagePath) -> 중간 정도의 추상화
  • .append("\n") -> 저수준의 추상화

위에서 아래로 코드가 읽히도록 하자

  • 코드는 위에서 아래로 이야기처럼 읽혀야 한다
  • 한 함수 다음에는 추상화 수준이 한 단계 낮은 함수가 온다

Switch문

  • 사용 자제
  • 근본적으로 길 수 밖에 없고, 다양한 케이스를 핸들링
  • switch 문에서 수행해야 할 역할을 객체로 추상화하여 구성

서술적인 이름을 사용하자

  • testableHtml -> includeSetupAndTeardownPages

함수 인자에 관하여

  • 함수에서 이상적인 개수는 0개
  • 그 다음은 1개, 그 다음은 2개
  • 3개는 가능한 피하는 게 좋고, 4개는 지양하자

인수 객체

  • 함수에 argument로 들어가는 객체로 개념을 표현해 인수를 줄일 수 있다

동사와 키워드

  • write -> writeField
  • assertEquals -> assertExpectedEqualsActual

부수 효과를 일으키지 말자

  • 어떤 동작을 하던지 어떤 결과값을 내던지 하자.
  • 둘 모두 하진 말자

반복하지 말자

  • DRY, Don’t Repeat Yourself
  • duplication은 소프트웨어에서 악의 근원일 것이다

구조적 프로그래밍

  • 하나의 entry, 하나의 exit

Comments

주석은 나쁜 코드를 보완하지 못한다.

  • 나쁜 코드를 주석하지 말고, 새로 쓰자

코드로 의도를 표현하자

  • ‘\\직원에게 복지 혜택을 받을 자격이 있는지 검사한다’ 주석 -> employee.isEligibleForFullBenefits() 메소드로 변경

좋은 주석

  • 법적인 주석 (라이선스 등)
  • 정보를 제공하는 주석 (테스트 중인 Responder 인스턴스를 반환한다 등)
  • 의미를 설명하는 주석
  • 의미를 명료하게 밝히는 주석
  • 결과를 경고하는 주석 (~가 쓰레드 세이프하지 않으니 인스턴스 생성한다 등)
  • TODO 주석
  • 중요성을 강조하는 주석
  • 공개 API에서의 Javadocs

나쁜 주석

  • 주절거리는 주석 (주석을 봤는데 다시 코드를 봐야 하는 주석)
  • 같은 이야기를 중복하는 주석
  • 의무적으로 다는 주석
  • 이력을 기록하는 주석 (버전 관리 시스템으로 다 관리하기 때문에 필요 없음)
  • 있으나 마나 한 주석
  • 함수나 변수로 표현할 수 있다면 주석을 달지 말자
  • 위치를 표시하는 주석
  • 닫는 괄호에 다는 주석 (IDE 수준에서 지원)
  • 공로를 돌리거나 저자를 표시하는 주석 (개인적으로 이건 좀 찔린다..)
  • 주석처리해둔 코드
  • HTML 주석
  • 전역 정보 (포트 기본 값등)
  • 너무 많은 정보 (RFC 내용은 레퍼런스로 대체 등)
  • 모호한 관계 (주석 내용의 필터 바이트가 무엇인지?)
  • 함수 헤더 - 짧은 함수는 긴 설명이 필요 없다.
  • 비공개 코드에서의 Javadocs

Formatting

형식을 맞추는 목적은? - 의사 소통 신문 기사처럼 작성하자 - 고수준 추상화 -> 상세 내용 개념은 빈 행으로 분리하자 - 빈 행은 새로운 개념을 시작한다는 시각적 단서

세로 밀집도는?

  • 세로 밀집도는 연관성을 나타낸다
  • 의미 없는 주석으로 두 인스턴스 변수를 떨어뜨려 놓으면 연관 없어 보임, bad!

수직 거리

  • 변수는 사용하는 위치에 최대한 가까이 선언하자
  • 인스턴스 변수는 클래스 맨 처음에 선언하자
  • 종속 함수
    • 만약 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치
    • 또한 가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치한다
  • 개념적 유사성
    • 친화도 높을 수록 코드를 가까이 배치

가로 공백과 밀집도

  • 할당 문은 왼쪽 요소와 오른쪽 요소가 분명히 나뉜다
  • 함수와 인자는 밀접하기에 붙인다
  • 연산자 우선 순위에 따라 계산되는 그룹끼리 붙인다

가로 정렬 - 크게 의미 없음 들여쓰기를 무시해서는 안됨.. 회사나 특정 언어의 컨벤션을 따라 가야 함

팀 규칙

  • 모든 프로그래머는 자신이 선호하는 규칙이 있음
  • 하지만 팀에 속한다면 자신이 선호해야 할 규칙은 팀 규칙
  • 팀은 한 가지 규칙에 합의해야 한다

Objects and Data Structures

데이터 추상화

  • 구현을 노출하는 것보다는 가급적 은닉하는 것이 좋다
  • 구체적인 숫자값으로 반환하는 것보다는 백분율이라는 추상적 개념으로 알려주는 게 낫다

자료 / 객체 비대칭

  • 객체는 추상화 뒤로 자료를 숨긴 채 자료를 다루는 함수만 공개한다
  • 자료 구조는 자료를 그대로 공개하며 별다른 함수를 제공하지 않는다

디미터 법칙

  • ctxt.getOptions().getScratchDir().getAbsolutePath() 와 같은 사용 지양 (기차 충돌)
  • 위 코드는 4줄로 풀어쓴다면 기차 충돌 해결할 수 있어 좋음

Error Handling

오류 코드보다 예외를 사용하라

  • E_OK와 같은 코드 사용 지양

Try / Catch 블럭을 추출하자

  • 서로 다른 목적을 가진 코드이기 때문에 추출하는 방법이 좀 더 나은 구조

정상 흐름을 정의하자

Null을 반환하지 말자

  • Collections.emptyList() 반환이나 Optional 사용

Null을 전달하지 말자

  • 아예 null이 인자로 들어오지 않도록 전달하지 않는것이 중요

Unit Test

TDD 법칙 세 가지

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

클린 테스트 코드 유지하기 - 테스트 코드 또한 실제 코드 못지 않게 중요하다

클린 테스트 코드 - 어떻게 만드나?

  1. 가독성
  2. 가독성
  3. 가독성

테스트 당 assert 하나

  • assert 문이 단 하나인 함수는 결론이 하나
  • 코드를 이해하기 쉽고 빠르다

테스트 당 개념 하나

  • 테스트 함수마다 개념 하나만 테스트하자

Classes

클래스 체계

  1. public static constants
  2. private static variables
  3. private instance variables
  4. public functions
  5. private utilities called by a public function right after

클래스는 작게 만들자

  • 클래스 생성 시 첫 번째 규칙은 크기
  • 클래스는 작아야 한다
  • 두 번째 규칙도 크기 - 더 작아야 한다

단일 책임 원칙 (SRP)

  • 클래스나 모듈을 변경할 이유가 단 하나 뿐이어야 한다
  • SRP는 객체지향 디자인에서 가장 중요한 컨셉 중 하나

응집도 (Cohesion)

  • 응집도가 높아지도록 변수와 메소드를 적절히 분리
  • 새로운 클래스 두 세 개로 쪼개주자