클린코드
나쁜 코드는 개발 속도를 크게 떨어뜨린다.
코드를 고칠 때마다 엉뚱한 곳에서 문제가 생긴다
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 법칙 세 가지
- 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다
- 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다
- 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다
클린 테스트 코드 유지하기 - 테스트 코드 또한 실제 코드 못지 않게 중요하다
클린 테스트 코드 - 어떻게 만드나?
- 가독성
- 가독성
- 가독성
테스트 당 assert 하나
- assert 문이 단 하나인 함수는 결론이 하나
- 코드를 이해하기 쉽고 빠르다
테스트 당 개념 하나
- 테스트 함수마다 개념 하나만 테스트하자
Classes
클래스 체계
- public static constants
- private static variables
- private instance variables
- public functions
- private utilities called by a public function right after
클래스는 작게 만들자
- 클래스 생성 시 첫 번째 규칙은 크기
- 클래스는 작아야 한다
- 두 번째 규칙도 크기 - 더 작아야 한다
단일 책임 원칙 (SRP)
- 클래스나 모듈을 변경할 이유가 단 하나 뿐이어야 한다
- SRP는 객체지향 디자인에서 가장 중요한 컨셉 중 하나
응집도 (Cohesion)
- 응집도가 높아지도록 변수와 메소드를 적절히 분리
- 새로운 클래스 두 세 개로 쪼개주자