깨끗한 코드는 한가지를 제대로 한다.
1. 깨끗한 코드
- "깨끗한 코드는 단순하고 직접적이다 .깨끗한 코드는 잘 쓴 문장처럼 읽힌다. 깨끗한 코드는 결코 설계자의 의도를 숨기지 않는다. 오히려 명쾌한 추상화와 단순한 제어문으로 가득하다"
- "기계가 실행할 정도로 상세학 요구사항을 명시하는 작업, 바로 이것이 프로그래밍이다. 이렇게 명시한 결과가 바로 코드다."
- "나는 우아하고 효율적인 코드를 좋아한다. 논리가 간단해야 버그가 숨어들지 못한다. 의존서을 최대한 줄여야 유지보수가 쉬워진다. 오류는 명백한 전략에 의거해 철저히 추리한다. 성능을 최적으로 유지해야 사람들이 원칙없는 최적화로 코드를 망치려는 유혹에 빠지지 않는다. 깨끗한 코드는 한가지를 제대로 한다."
- "함수는 한 가지를 해야한다. 그 한가지를 잘해야 한다. 그 한가지만을 해야한다"
- "주석은 쉰들러 리스트가 아니다. 주석은 '순수하게 선하지' 못하다. 사실상 주석은 기껏해야 필요악이다.
프로그래밍 언어 자체가 표현력이 풍부하다면, 아니 우리에게 프로그래밍 언어를 치밀하게 사용해 의도를 표현할 능력이 있다면,
주석은 거의 필요하지 않으리라. 아니, 전혀 필요하지 않으리라" - "처음부터 올바르게 시스템을 만들 수 있다는 믿음은 미신이다.
대신에 우리는 오늘 주어진 사용자 스토리에 맞춰 시스템을 구현해야 한다. 내일은 새로운 스토리에 맞춰 시스템을 조정하고 확장하면 된다. 이것이 반복적이고 점진적인 애자일 방식의 핵심이다.
테스트 주도 개발, 리팩터링, 그로 얻어지는 깨끗한 코드는 코드 수준에서 시스템을 조정하고 확장하기 쉽게 만든다" - "소프트웨어 시스템은 물리적인 시스템과 다르다.
관심사를 적절히 분리해 관리한다면 소프트웨어 아키텍처는 점진적으로 발전할 수 있다.
... 소프트웨어 시스템은 수명이 짧다는 본질로 인해 아키텍처의 점진적인 발전이 가능하다"2. 의미있는 이름
- 의도를 분명히 밝혀라
- 그릇된 정보를 피하라
- 의미 있게 구분하라
- 발음하기 쉬운 이름을 사용하라
- 검색하기 쉬운 이름을 사용하라
- 클래스 이름은 명사, 메서드 이름은 동사구
- 한 개념에 한 단어
3. 함수
- 작게 만들어라
- 한가지만 해라
- 함수당 추상화 수준은 하나로
- 내려가기 규칙
- 서술적인 이름을 사용하라
- 함수 인수는 0~1. flag는 사용하지 말것
- 부수 효과는 일으키지 마라
- 명령과 조회를 분리하라
- 오류코드보다 예외를 사용하라
- 반복하지마라
4. 주석
- 주석은 나쁜 코드를 보완하지 못한다
- 코드로 의도를 표현하라
- 좋은 주석 : 법적인 주석, 정보를 제공하는 주석, 의도를 설명하는 주석, 의도를 명료하게 밝히는 주석, 결과를 경고하는 주석, todo 주석
- 나쁜 주석 : 주절거리는 주석, 같은 이야기를 중복하는 주석, 오해할 여지가 있는 주석
5. 형식 맞추기
- 적절한 행 길이를 유지하라
- 개념은 빈 행으로 분리하라
- 밀접한 코드 행은 세로로 가까이
- 변수는 사용하는 위치에 최대한 가까이 선언(인스턴스 변수는 클래스 맨 처음에 선언)
- 공백을 넣으면 여러개의 개념으로 보인다, 승수사이에는 공백이 없다. 항 사이에는 공백
6. 객체와 자료구조
- 자료 추상화 : 개발자는 객체가 포함하는 자료를 표현할 가장 좋은 방법을 심각하게 고민해야 한다. 아무 생각없이 조회/설정 함수를 추가하는 방법이 가장 나쁘다
- 자료/객체 비대칭 : "객체 지향 코드에서 어려운 변경은 절차적 코드에서 쉬우며, 절차적인 코드에서 어려운 변경은 객체 지향 코드에서 쉽다."
- 디미터 법칙 : 클래스 c의 메서드 f는 클래스c, f가 생성한 객체, f인수로 넘어온 객체, c인스턴스 변수에 저장된 객체만 호출
- 자료전달객체 : 객체는 동작을 공개하고 자료를 숨긴다. 그래서 기존 동작을 변경하지 않으면서 새 객체 타입을 추가하기는 쉬운 반면, 기존 객체에 새 동작을 추가하기는 어렵다. 자료 구조는 별다른 동작 없이 자료를 노출한다. 그래서 기존 자료 구조에 새 동작을 추가하기는 쉬오나, 기존 함수에 새 자료구조를 추가하기는 어렵다. 어떤 시스템을 구현할 때, 새로운 자료 타입을 추가하는 유연성이 필요하면 객체가 더 적합하다. 새로운 동작을 추가하는 유연성이 필요하면 자료구조와 절차적인 코드가 더 적합하다. 우수한 소프트웨어 개발자는 편견없이 이 사실을 이해해 직면한 문제에 최적인 해결책을 찾는다.
7. 오류처리
- 오류 코드보다 예외를 사용하라
- unchecked 예외를 사용하라
- 예외에 의미를 제공하라(=오류메시지에 정보를 담아 던진다)
- 호출자를 고려해 예외 클래스를 정의하라 : 오류를 정의할 때 프로그래머에게 가장 중요한 관심사는 오류를 잡아내는 방법이 되어야한다
- null을 전달/반환하지 마라
8. 경계
- 외부코드 사용하기
- 경계 살피고 익히기
- log4j 익히기
- 아직 존재하지 않는 코드를 사용하기
9.단위테스트
- TDD(Test Driven Development - 테스트 주도 개발)
- TDD 법칙 세가지
- 실패하는 단위테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
- 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다
- 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다
- 깨끗한 테스트코드 유지하기
- 테스트는 유연성, 유지보수성, 재사용성을 제공한다
- 깨끗한 테스트코드 = 가독성(최소한의 표현으로 많은 것을 나타내야함)
- 테스트당 assert하나 : 테스트랑 개념하나
- Fast / Independent / Repeatable / Self-validating(테스트결과는 boolean, 자가 검증) / Timely(적시에)
10. 클래스
- 클래스는 작아야 한다 : 클래스는 해당 클래스 책임을 기술해야 한다. 간결한 이름이 떠오르지 않는다면 클래스 크기가 너무 크거나 책임이 너무 많아서다
- 변경하기 쉬운 클래스
11. 시스템 (??)
- 관심사 분리
- 확장
- AOP(Aspect Oriented Programming, 관점지향프로그래밍) : 특정 관심사를 지원하려면 시스템에서 특정 지점들이 동작하는 방식을 일관성 있게 바꿔야 한다고 명시한다
- 자바프록시, POJO
- AspectJ관점 : 관심사를 관점으로 분리하는 강력한 도구, 언어 차원에서 관점을 모듈화 구성으로 지원하는 자바 언어 확장
- 테스트주도 시스템 아키텍처 구축
- 의사 결정을 최적화하라
- 명백한 가치가 있을 때 표준을 현명하게 사용하라
- 시스템은 도메인 특화 언어가 필요하다
12. 창발성
- 단순한 설계규칙
- 모든 테스트를 실행하라
- 중복을 없애라
- 표현하라 - 좋은 이름을 선택한다, 함수와 클래스 크기를 가능한 줄인다, 표준 명칭을 사용한다, 단위테스트케이스를 꼼꼼히 작성한다
- 클래스와 메서드 수를 최소로 줄여라
13. 동시성
여러 스래드를 동시에 돌리는 이유, 어려움, 이런 어려움에 대처하고 깨끗한 코드를 작성하는 방법
- 동시성이 필요한 이유? 동시성은 결합을 없애는 전략, 무엇과 언제를 분리하는 전략
- 동시성 방어원칙 - 동시성 코드는 다른 코드와 분리하라, 자료를 캡슐화하라, 공유 자료를 최대한 줄여라
- 라이브러리를 이해하라