Clean Code 2장. 의미있는 이름

HYl·2022년 4월 24일
0

Clean Code

목록 보기
2/9

DAY 2

오늘 읽은 범위 : 2장, 의미있는 이름


책에서 기억하고 싶은 내용을 써보세요.

의도를 분명히 밝혀라

“의도가 분명하게 이름을 지으라”고 말하기는 쉽다. 여기서는 의도가 분명한 이름이 정말로 중요하다는 사실을 거듭 강조한다. 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 더 많다.

public List<int[]> getThem() {
	List<int[]> list1 = new ArrayList<int[]>();
	for (int[] x : theList) 
    	if (x[0] == 4)
		list1.add(x); 
    return list1;
}
  1. theList에 무엇이 들었는가?
  2. theList에서 0번째 값이 어째서 중요한가?
  3. 값4는무슨의미인가?
  4. 함수가 반환하는 리스트 list1을 어떻게 사용하는가?
public List<int[]> getFlaggedCells() {
	List<int[]> flaggedCells = new ArrayList<int[]>();
    for (int[] cell : gameBoard)
		if (cell[STATUS_VALUE] == FLAGGED)
        flaggedCells.add(cell);
	return flaggedCells; 
}

위에서 보듯, 코드의 단순성은 변하지 않았다. 연산자 수와 상수 수는 앞의 예와 똑같으며, 들여쓰기 단계도 동일하다. 그런데도 코드는 더욱 명확해졌다.


의미 있게 구분하라

  • getActiveAccount();
  • getActiveAccounts();
  • getActiveAccountInfo();

이 프로젝트에 참여한 프로그래머는 어느 함수를 호출할지 어떻게 알까?
명확한 관례가 없다면 변수 moneyAmount는 money와 구분이 안 된다. cus- tomerInfo는 customer와, accountData는 account와, theMessage는 message
와 구분이 안 된다. 읽는 사람이 차이를 알도록 이름을 지어라.


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

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;
}

위 코드에서 sum이 별로 유용하진 않으나 최소한 검색이 가능하다. 이름을 의미 있게 지으면 함수가 길어진다. 하지만 WORK_DAYS_PER_WEEK를 찾기가 얼마나 쉬운지 생각해보라. 그냥 5를 사용한다면 5가 들어가는 이름을 모두 찾은 후 의미를 분석해 원하는 상수를 가려내야 하리라.


인코딩을 피하라

  • 1.헝가리식 표기법
    • IDE는 코드를 컴파일하지 않고도 타입 오류를 감지할 정도로 발전했다. 따라서 이제는 헝가리식 표기법이나 기타 인코딩 방식이 오히려 방해가 될 뿐이다. 변수, 함수, 클래스 이름이나 타입을 바꾸기가 어려워지며, 읽기도 어려워진다. 독자를 오도할 가능성도 커진다.
PhoneNumber phoneString;
// 타입이 바뀌어도 이름은 바뀌지 않는다!
  • 2.멤버 변수 접두어
    • 이제는 멤버 변수에 m_이라는 접두어를 붙일 필요도 없다. 클래스와 함수는 접 두어가 필요없을 정도로 작아야 마땅하다.
public class Part {
	private String m_dsc; // 설명 문자열 
	void setName(String name) {
		m_dsc = name; 
    }
}
_________________________________________________

public class Part {
	String description;
	void setDescription(String description) {
		this.description = description; 
    }
}
  • 3.인터페이스 클래스와 구현 클래스
    • 때로는 인코딩이 필요한 경우도 있다.
      인터 페이스 클래스 이름과 구현 클래스 이름 중 하나를 인코딩해야 한다면 구현 클 래스 이름을 택하겠다. ShapeFactoryImp나 심지어 CShapeFactory가 IShape Factory보다 좋다.

자신의 기억력을 자랑하지 마라

똑똑한 프로그래머와 전문가 프로그래머 사이에서 나타나는 차이점 하나만 들자면, 전문가 프로그래머는 명료함이 최고라는 사실을 이해한다. 전문가 프로그래머는 자신의 능력을 좋은 방향으로 사용해 남들이 이해하는 코드를 내놓는다.


클래스 이름

클래스 이름과 객체 이름은 명사나 명사구가 적합하다. Customer, WikiPage, Account, AddressParser 등이 좋은 예다. Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다.


메서드 이름

메서드 이름은 동사나 동사구가 적합하다. postPayment, deletePage, save 등이 좋은 예다. 접근자(Accessor), 변경자(Mutator), 조건자(Predicate)는 javabean 표준에 따라 값 앞에 get, set, is를 붙인다.


한 개념에 한 단어를 사용하라

동일 코드 기반에 controller, manager, driver를 섞어 쓰면 혼란 스럽다. DeviceManager와 ProtocolController는 근본적으로 어떻게 다른가? 어째서 둘 다 Controller가 아닌가? 어째서 둘 다 Manager가 아닌가? 정말 둘 다 Driver가 아닌가? 이름이 다르면 독자는 당연히 클래스도 다르고 타입도 다르리라 생각한다.
일관성 있는 어휘는 코드를 사용할 프로그래머가 반갑게 여길 선물이다.


해법 영역에서 가져온 이름을 사용하라

코드를 읽을 사람도 프로그래머라는 사실을 명심한다. 그러므로 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 괜찮다. 모든 이름을 문제 영역(domain)에서 가져오는 정책은 현명하지 못하다.


문제 영역에서 가져온 이름을 사용하라

적절한 ‘프로그래머 용어’가 없다면 문제 영역에서 이름을 가져온다. 그러면 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악할 수 있다. 우수한 프로그래머와 설계자라면 해법 영역과 문제 영역을 구분할 줄 알아야 한다. 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야한다.


의미 있는 맥락을 추가하라

firstName, lastName, street, houseNumber, city, state, zipcode 라는 변수가 있다. 변수를 훑어보면 주소라는 사실을 금방 알아챈다. 하지만 어느 메서드가 state라는 변수 하나만 사용한다면? 변수 state가 주소 일부라는 사실을 금방 알아챌까?
addr라는 접두어를 추가해 addrFirstName, addrLastName, addrState라 쓰면 맥락이 좀 더 분명해진다


오늘 읽은 소감은?

좋은 이름을 선택하는 것은 어렵다. 그렇다고 코드를 개선하는 것을 멈추어서는 안 되고, 나뿐만이 아니라 모든 동료가 다같이 고민하는 환경도 중요한 것 같다.

이 장에서는 규칙 몇 개를 적용하여 코드 가독성이 높아지는 것에 대하여 다루었는데, 이를 따르면 단기적은 효과는 물론 장기적으로 보았을 때도 이익이 보장되는 것 같다.

profile
꾸준히 새로운 것을 알아가는 것을 좋아합니다.

0개의 댓글