1. 의도를 분명이 밝혀라
변수나 함수 클래스 이름은 의도가 분명한 이름이어야한다.
- 변수(함수, 클래스)의 존재 이유
- 변수(함수, 클래스)의 수행 기능
- 변수(함수, 클래스)의 사용 방법
// 변경 전
int d; //경과 시간 (단위: 날짜);
// 변경 후
int daysSinceCreation;
코드의 단순성이 아닌 코드의 함축성을 고려해야한다 -> 코드 맥락을 코드 자체에 명시적으로 드러나야한다.
코드 맥락 정보 제공 방법 : 개념에 이름을 붙인다
// 변경 전
public List<int[]> getThem(){
List<int[]> list1 = new ArrayList<int[]>();
for(int[] x : the List)
if(x[0] == 4)
list1.add(x);
return list1;
}
/* 변경 후
- 각 칸을 Cell 클래스로 표현
- Cell 필드 값 flagged 확인 메서드로 변경
*/
public List<Cell> getFlaggedCells(){
List<Cell> flaggedCells = new ArrayList<Cell>();
for(Cell cell: gameBoard)
if(cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
2. 그릇된 정보를 피하라
여러 계정을 그룹으로 묶을 때, 실제 List가 아니면 accountList라 명명하지 않는다.
- accountGroup, bunchOfAccounts, Accounts
서로 흡사한 이름을 사용하지 않도록한다.
- XYZControllerForEfficientHandlingOfStrings <-> XYZControllerForEfficientStorageOfStrings
이름만 보고 객체를 선택할 수 있게, 유사한 개념은 유사한 표기법을 사용해 일관성을 준다.
주의 ) l O 1 0 조심히 사용하기!
3. 의미있게 구분해라
연속된 숫자를 덧붙인 이름은 아무런 정보를 제공하지 못한다.
public static void copyChars(char a1[], char a2[]){ // source, destination으로 고치자
for (int i =0; i < a1.length; i++){
a2[i] = a1[i];
}
}
불용어를 추가한 이름은 아무런 정보도 제공하지 않는다. 불용어는 중복이기 때문이다.
Product; ProductInfo; ProductData // 의미가 불분명하다.
NameString; Name;
Customer; CustomerObejct; // 차이를 알 수가 없다.
읽는 사람이 차이를 알 수 있도록 이름을 지어라
moneyAmount; money;
customerInfo; customer;
accountData; account;
theMessage; message;
4. 발음하기 쉬운 이름을 사용하라
발음하기 쉬운 단어를 사용할 때 대화가 편해진다.
// 변경 전
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
// 변경 후
private Date generationTimeStamp;
private Date modificationTimeStamp;
private final String recordId = "102";
5. 검색하기 쉬운 이름을 사용하라
문자 하나를 사용하는 이름이나 상수는 검색이 어렵다.
검색의 관점에서 긴 이름이 짧은 이름보다 좋다.
간단한 메서드의 로컬변수 : 한 문자 (이름 길이는 범위 크기에 비례)
상수의 의미를 나타내는 변수로 바꾸어주자.
// 변경 전
for(int j=0; j>34; j++){
s += (t[j]*4)/5;
}
// 변경 후 : 검색도 가능하고, 이름의 의미를 쫒아 코드 파악이 가능하다.
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for(int j=0; j < NUMBER_OF_TASKS; j++){
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}
6. 인코딩을 피하라
6-1. 헝가리식 표기법
이전에 컴파일러가 타입을 점검하지 않아 타입을 기억할 단서로 헝가리식 표기법을 사용했다.
그러나 지금은 변수 이름에 타입을 인코딩할 필요가 없다.
// 헝가리식 표기법
PhoneNumber phoneString; // 타입 바뀌어도 이름은 안 바뀐다.
// 헝가리식 표기법 적용 X
PhoneNumber phonenumber;
6-2. 멤버변수 접두어
접두어를 무시하고 이름을 해독하자. 멤버 변수를 눈에 띄게 보여주는 IDE를 사용하자.
// 멤버변수를 의미하는 접두어 m_
public class Part{
private String m_dsc;
}
// 접두어가 필요없을 정도로 작아야한다.
public class Part{
private String description;
}
6-3. 인터페이스 클래스와 구현 클래스
인코딩이 필요한 경우가 있다.
- 인터페이스 클래스 :
ShapeFactory.class
- 구현 클래스 :
ShapeFactoryImpl.class
7. 자신의 기억력을 자랑하지 마라
문자 하나만 사용하는 변수이름은 문제가 있다. (루프에서 반복횟수를 세는 변수는 괜찮다.)
전문가 프로그래머는 명료함이 최고다 : 남들이 이해하는 코드를 내놓는다.
URL에서 r이라는 변수를 과시하는 것처럼 기억력을 과시하지말자.
8. 클래스와 메서드 이름
클래스 이름 : 명사구
Customer, WikiPage, Account, AddressParser
Manager, Processor, Data, Info 단어는 피하자.
메서드 이름 : 동사나 동사구
postPaymet, deletePage, save
- 접근자 (Accessor) :
getVerb();
- 변경자 (Mutator) :
setVerb();
- 조건자 (Predicate) :
isVerb();
생성자 중복정의 : 정적 팩토리 메서드 - 인수를 설명한다.
Complex fulcrumPoint = Complex.FromRealNumber(23.0);
- 생성자 사용 제한을 위해 private으로 생성자를 선언한다.
9. 기발한 이름은 피하라
재미난 이름보단 명료한 이름 HolyHandGrenade
-> DeleteItems
구어체나 속어의 이름보단 의도를 분명하게 하는 이름 whack()
-> kill()
10. 한 개념에 한 단어 & 한 단어 한 목적
메서드 이름은 문맥에 독자적이고 일관적이어야한다.
추상적인 개념 하나에 여러 단어를 선택하지 말자
// 어떤 클래스에서 어떤 걸 사용했는지 혼란스럽지 않게 일관성을 유지한다.
fetch, retrieve, get
controller, manager, driver
한 단어를 두 가지 목적으로 사용하지 마라
같은 맥락일 경우에만 '일관성'을 고려하자.
// 기존 : 기존 값 두개를 더하거나 이어서 새로운 값 만듬
add();
// 새로운 것 : 집합에 값 하나 추가 (다른 맥락)
insert(); append()
11. 해법 영역 & 문제 영역에서 가져온 이름을 사용하라
해법 영역 (Solution Domain) : 개발자라면 당연히 알고 있을 전산용어, 알고리즘 이름, 패턴 이름, 수학 용어 등은 사용하자.
JobQueue
, AccountVisitor(Visitor pattern)
등
문제 영역 (Problem Domain) : 실제 도메인의 전문가에게 의미를 물어 파악할 수 있도록 문제 영역에서 이름을 가져오자.
12. 의미있는 맥락을 추가하라 & 불필요한 맥락을 없애라
의미가 분명한 이름이 있게 하자 : 클래스, 함수, 이름 공간에 넣어 맥락을 부여한다.
// 하나만 사용하면 주소 관련 변수임을 모른다.
String firstName, lastName, street, houseNumber, city, state, zipcode;
// 접두어를 사용하면 맥락이 좀 더 분명해진다.
String addrFirstName, addrLastName, addrStreet, addrHouseNumber, addrCity, addrState, addrZipcode;
// 클래스를 생성 : 변수가 큰 개념임이 컴파일러에도 분명해진다.
class Address{
String addrFirstName;
String addrLastName;
String addrStreet;
String addrHouseNumber;
String addrCity;
String addrState;
String addrZipcode
}
맥락을 개선하여 클래스로 만들면 함수를 쪼개기도 쉬워진다.
의미가 분명하다면 일반적으로 짧은 이름이 긴 이름보다 좋다 : 불필요한 맥락을 추가하지 말자.
- 고급 휘발유 충전소 (Gas Station Deluxe) 애플리케이션을 짠다고, 모든 클래스 이름을 GSD로 시작하지 말자
accountAddress
,customerAddress
: 클래스 이름 X, 인스턴스 이름 OPostalAddress
,MAC
,URI
: 클래스 이름 O
'Dev Book Review > Clean Code' 카테고리의 다른 글
CleanCode 1장 깨끗한 코드 (0) | 2020.04.28 |
---|