G1: 한 소스 파일에 여러 언어를 사용한다.
•
하나의 소스 파일에 3,4개의 언어가 있다면 정말 보기 좋을 것이다. 그렇지 않은가?
•
막 머릿속에서 컨텍스트 스위칭 돌아가면서 쟤 이해하고 얘 이해하고 혼란스러울 거다.
•
현실적으로 어려운 것 안다. 최대한 그 수를 줄이자.
G2: 당연한 동작을 구현하지 않는다.
•
함수를 구현할 것이라면 직관적으로 기대되는 바에 대한 요구를 충족시켜야 한다.
•
그렇지 않는다면 남들은 당신의 함수를 봤을 때, 구체적인 부분까지 확인할 것이다.
G3: 경계를 올바로 처리하지 않는다.
•
항상 끝을 조심해야 한다. 엣지 케이스는 언제나 우리를 불편하게 만드니까.
G4: 안전 절차 무시
•
안전 절차를 무시하면 끝이 좋지 못하다.
•
컴파일러 경고를 무시해버리면 당장은 편할지 몰라도 나중에 배로 돌려받을 걸?
G5: 중복
•
중복을 발견할 때마다 추상화할 기회로 간주하자.
•
추상화 수준을 높여 좋은 객체지향을 향한 발자국을 내딛을 기회다.
•
switch/case나 if/else문의 조건을 거듭 확인하는 중복은 다형성으로 처리하는 것이 좋다.
•
알고리즘이 유사하나 약간의 코드가 다르다면 디자인 패턴을 떠올려서 해결해보자.
•
어디서든 중복을 발견하면 바퀴벌레를 본 것 마냥 없애버리자.
G6: 추상화 수준이 올바르지 못하다.
•
추상화는 저차원 상세 개념과 고차원 일반 개념을 분리한다.
•
그들이 같이 존재하는 것 자체만으로도 안티패턴이다. 유지보수를 해치고 문제가 생긴다.
G7: 기초 클래스가 파생 클래스에 의존한다.
•
효자도 아니고 부모가 어찌 자식에게 의존할 수 있는가.
•
예외는 있다. 파생 클래스가 수정될 일이 없다면 간혹 기초 클래스가 수정 클래스를 선택하는 코드가 존재한다.
G8: 과도한 정보
•
잘 정의된 모듈은 인터페이스가 아주 작다. 부실하게 정의된 모듈은 구질구질하다.
•
좋은 개발자는 클래스나 모듈 인터페이스가 노출할 함수를 제한, 제어할 줄 알아야 한다.
•
자료를 숨겨라, 인스턴스 변수를 숨겨라, 상수와 임시 변수를 숨겨라.
•
1만 하면 1만 알면 된다. 2만 하면 2만 하면 된다.
•
컴퓨터는 똑똑하지만 멍청해야 일을 잘한다는 것을 기억하자.
G9: 죽은 코드
•
절대 일어날 일이 없는 조건을 체크하는 if, case문
•
throw 문이 없거나 발생할 일이 없는 try-catch
•
아무도 호출 않는 유틸리티 함수
•
죽은 코드는 적절한 장례식을 치루고 떠나보내자.
G10: 수직 분리
•
변수와 함수는 사용되는 위치에 가깝게 위치시킨다.
◦
글 쓸 때, 비슷한 주제끼리 떨어뜨려 놓지 않지 않는가.
•
비공개 함수는 첫 호출이 일어난 메소드 블록 다음에 정의한다.
G11: 일관성 부족
•
일관적이지 않은 사람은 신뢰가 없다.
•
일관적인 코드는 빠른 이해를 가져다 준다.
G12: 잡동사니
•
필요 없는 건 지워라
•
방 정리는 잘 못해도 내가 이건 잘 할 수 있다.
G13: 인위적 결합
•
서로 무관한 개념을 인위적으로 결합하지 않는다.
G14: 기능 욕심
•
클래스 메서드는 자기 클래스의 인스턴스, 매개변수와 함수에만 관심을 가져야 한다.
G15: 선택자 인수
•
public int calculateWeeklyPay(boolean overtime)
•
플래그 인수 쓰지 말자.
G16: 모호한 인수
•
코드를 짤 때는 의도를 최대한 분명히 밝히자.
G17: 잘못 지운 책임
•
책임은 요구되어지는 바에 적절하게 배치되어야 한다.
•
Fruit 클래스가 PI를 가지고 있을 필요는 없다.
G18: 부적절한 static 함수
•
Math.max(double a, double b)는 좋은 정적 메서드다.
•
HourlyPayCalculator.calculatePay(employee, overtimeRate)는 좋지 않은 정적 메서드다.
•
불필요한 정적 메서드는 낭비다.
•
재정의할 가능성이 있다면 정적 메서드로 두지 말아라.
G19: 서술적 변수
•
프로그래밍은 논리적 글쓰기다.
•
가독성을 높이려면 처리 단계를 적절히 나누고 각 단계를 서술하듯 써야한다.
G20: 이름과 기능이 일치하는 함수
•
이름에서 기대되는 기능만 해야한다.
•
이름에서 기대되는 기능을 해야한다.
G21: 알고리즘을 이해하라.
•
구현이 끝났다고 하기 전에 본인이 구현한 함수의 알고리즘을 정확하게 이해해라.
G22: 논리적 의존성은 물리적으로 드러내라
•
의존하는 모듈이 상대 모듈에 대해 뭔가를 가정하면(즉, 논리적으로 의존하면) 안 된다.
•
의존하는 모든 정보를 명시적으로 요청하는 편이 좋다.
G23: if/else 혹은 switch/case 보다는 다형성을 사용하라
•
선택 유형 하나에는 switch 문을 한 번만 사용한다.
•
같은 선택을 수행하는 다른 코드에서는 다형성 객체를 생성해 switch 문을 대신한다.
G24: 표준 표기법을 따르라.
•
팀의 컨벤션은 업계 표준에 기반하여 작성하여야 한다.
•
팀의 컨벤션는 충분한 정보를 명시해야 한다.
◦
인스턴스 변수 이름을 선언하는 위치
◦
클래스/메서드/변수 이름을 정하는 방법
◦
괄호를 넣는 위치 등
•
팀이 정한 표준은 팀원들 모두가 따라야 한다.
G25: 매직 숫자는 명명된 상수로 교체하라.
•
매직 숫자는 나만 알고 있는 암호와 같다.
•
상수명 등의 도움을 받아 처리하자.
G26: 정확하라
•
정확하게 처리하라.
•
코드에서의 모호성과 부정확을 제거하라.
G27: 관례보다 구조를 사용하라
•
설계가 결정 되었을 때, 이 결정을 강제하려면 규칙보다 관례를 사용하라.
•
구조 자체로 강제하는 것이 제일 좋다.
◦
switch/case 문보다 추상 메서드가 있는 기초 클래스
G28: 조건을 캡슐화하라
•
부울 논리는 이해하기 어렵다.
◦
age > constaraintAge보다 isOver(age)가 낫다.
G29: 부정 조건은 피하라
•
부정 조건은 긍정 조건보다 이해하기 어렵다.
G30: 함수는 한 가지만 해야 한다
•
함수는 한 가지만 수행하는 여럿 함수들로 나눠지고 이들 간의 상호작용으로 구성되어야 마땅하다.
G31: 숨겨진 시간적인 결합
•
어떠한 코드에 명백한 순서가 존재할 때, 이 순서를 명시하여아 한다.
•
이것이 명시되지 않아 순서대로 처리되지 않는다면 문제가 발생할 것이다.
G32: 일관성을 유지하라
•
일관성 있는 사람이 되어라
G33: 경계 조건을 캡슐화하라
•
+ 1과 같은 경계를 넘나드는 연산을 방지하자.
◦
for i in range(5 + 1):
G34: 함수는 추상화 수준을 한 단계만 내려가야 한다
•
함수 내 모든 문장은 추상화 수준이 동일해야 한다.
•
그리고 그 추상화 수준은 현재 함수보다 한 단계 낮아야 한다.
•
추상화 수준은 너가 정하는 거다. 너가 설계한 계층대로 추상화 수준이 결정된다.
G35: 설정 정보는 최상위 단계에 둬라
•
추상화 최상위 단계에 둬야 할 상수들은 저차원 함수에 존재해서는 안 된다.
•
해당 추상화 단계에서 명시되어 있다면 해당 상수들은 그 메소드의 매개변수여야 한다.
G36: 추이적 탐색을 피하라
•
A 모듈이 B 모듈을 사용할 때, B 모듈이 C 모듈을 이용한다면
•
A 모듈은 C 모듈이 뭘 하는지 몰라야 한다.