clean code chapter.2
TRANSCRIPT
Clean CodeCh.2 의미 있는 이름
chois79
12년 7월 22일 일요일
이장에서 다룰 내용
• 소프트웨어에서 이름은 어디나 쓰인다
• 변수, 함수, 인수, 클래스, 파일, package, jar, war 등...
• 이러한 이름을 잘 짓는 것이 중요하다
• 이해도를 높인다.
• 이름을 잘 짓는 방법은 무엇인가?
12년 7월 22일 일요일
의도를 분명히 밝혀라
• 의도가 분명한 이름을 사용하는 것이 중요하다
• 좋은 이름을 짓는데 걸리는 시간 < 좋은 이름으로 인해 절약하는 시간
• Why? 코드의 이해와 변경이 쉬워짐
• 변수, 함수, 클래스의 이름을 짓는 가이드
• 다음의 질문에 답할 수 있는 이름을 사용
• 존재 이유는?
• 수행 기능은?
• 사용 방법은?
• 만약 주석이 필요하다면, 의도를 제대로 표현하지 못한 것
12년 7월 22일 일요일
의도를 분명히 밝혀라 - 예제
의도가 모호한 코드 의도가 분명한 코드
int d; // 경과 시간 (단위: 날짜 수) int elapsedTimeInDays; int daysSinceCreation; int daysSinceModification; int fileAgeInDays;
// 각 이름이 충분한 정보 제공을 하지 않음 public List<int[]> getThem() { List<int []> list1 = new ArrayList<int []>(); for(int [] x: theList) { if(x[0] == 4) list1.add(x); } return 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; }
// int []을 Cell Class로 변환 public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList<Cell>(); for(Cell cell: gameBoard) { if(cell.isFlagged()) flaggedCells.add(cell); } return flaggedCells; }
12년 7월 22일 일요일
그릇된 정보를 피하라
• 프로그래머는 코드에 그릇된 단서를 남겨서는 안된다
• 일반적으로 사용되는 의미와 다르게 사용하면 안됨
• ex) 여러 계정을 그룹으로 묶을때 실제로 List 컨테이너가 아닌데 accountList 로 칭할 경우
• accountGroup, bunchOfAccounts 혹은 Accounts로 명명
• 서로 흡사한 이름을 사용하지 않도록 주의
• XYZControllerForEfficientHandlingOfStrings, XYZControllerForEfficientStorageOfString
• 유사한 개념은 유사한 표기법 사용
• 알파벳에 의한 모호성 주의
• 소문자 L과 숫자 1: l, 1
• 대문자 O와 숫자 0: O, 0
12년 7월 22일 일요일
의미 있게 구분하라
• 읽는 사람이 차이를 알도록 이름을 지어라
• 연속된 숫자를 사용하여 이름을 짓지마라
• 불용어를 사용하여 구분하지마라
• ex1) Info나 Data는 a, an, the와 마찬가지로 의미가 불분명
• ProductInfo, ProductData (차이점이 모호함)
• ex2) NameString과 Name, moneyAmount와 money, customerInfo와 customer
// a1, a2보다 source, destination 을 사용하여 가독성을 높일수 있음 public static void copyChars(char a1[], char a2[]) { for(int i = 0; i < a1.length; i++) { a2[i] = a1[i]; } }
12년 7월 22일 일요일
발음하기 쉬운 이름을 사용하라
• 발음하기 어려운 이름은 의사 소통을 힘들게 한다
• ex) genymdhms (generate date, year, month, day, hour, minute, second)
• 이 이름에 대해 어떻게 의사 소통 해야 하는가?
• “젠 와이 엠 디 에이취 엠 에스”, “젠 야 무다 힘즈”
발음하기 어려운 이름 발음하기 쉬운 이름
class DtaRcrd102{ private Date genymdhms; private Date modymdhms; private final String pszqint = "102"; /* ... */ }
/* 코드를 통한 지적인 대화가 가능 */ class Customer { private Date generationTimestamp; private Date modificationTimestamp; private final String recordId = "102"; /* ... */ }
12년 7월 22일 일요일
검색하기 쉬운 이름을 사용하라
• 변수나 상수를 코드 여러 곳에서 사용한다면 검색하기 쉬운 이름이 바람직
• 문자 하나를 사용하는 이름과 상수는 가독성을 떨어뜨린다
• 간단한 메소드에서 로컬 변수만 한 문자를 사용
• 이름을 의미 있게 지으면 함수가 길어지지만 찾기가 쉽다
검색하기 어려운 이름 검색하기 쉬운 이름
for(int j = 0; j < 34; j++) { s += (t[j] * 4) / 5; }
int readDaysPerIdealDay = 4; final int WORK_DAYS_PER_WEEK = 5; int sum = 0; for(int j = 0; j < NUMBER_OF_TASKS; j++) { int realTaskDays = taskEstimate[j] * readDaysPerIdealDay; int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK); sum += realTaskWeeks; }
12년 7월 22일 일요일
인코딩을 피하라
• 부담을 더하지 않아도 이름에 인코딩할 정보는 아주 많다
• 인코딩한 이름은 발음하기 어렵다
• 헝가리안 표기법 (윈도우 C API 표기법)
• 특징: 당시 컴파일러가 타입을 점검하지 않았기 때문에 타입을 변수명에 명시한 표기법
• 현대적 IDE는 컴파일 하지 않아도 타입을 감지하기 때문에 오히려 방해가 됨
• 클래스 이름이나 타입을 바꾸는 것이 어렵고, 읽기도 어렵다
• 멤버 변수 접두어
• 멤버 변수에 m_ 이라는 접두어를 붙이는 것보다 다른 색으로 표시해 주는 IDE 툴 사용
• 인터페이스 클래스와 구현 클래스
• 인터페이스에 접두어 ‘I’를 붙이는 것 보다 구현 클래스에 ‘C’ or 접미어 ‘Imp’ 를 추가하는 것이 낫다
12년 7월 22일 일요일
자신의 기억력을 자랑하지 마라
• 기억력을 믿고, 의미 없는 이름을 사용하지 마라
• 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 이름은 바람직하지 못한 것이다
• 문제 영역이나 해법 영역에서 사용하지 않는 이름을 선택했기 때문
12년 7월 22일 일요일
클래스 이름
• 클래스 이름과 객체 이름은 명사나 명사구가 적합
• Customer, WikiPage, Account, AddressParser
• 불용어는 피해라
• Manager, Processor, Data, Info...
12년 7월 22일 일요일
메소드 이름
• 메소드 이름은 동사나 동사구가 적합
• ex) postPayment, deletePage, save ...
• 접근자, 변경자, 조건자는 자바 빈 표준에 따른 표기법 사용
• get, set, is
• 생성자를 중복해 정의할 때는 정적 팩토리 메소드를 사용
생성자 정적 팩토리 메소드
Complex fulcrmPoint = new Complex(23.0); Complex fulcrmPoint = Complex.FromReadlNumber(23.0);
12년 7월 22일 일요일
기발한 이름은 피하라
• 이름이 너무 기발하면 저자와 생각이 비슷한 사람만 이름을 기억한다
• 재미난 이름보다 명확한 이름을 선택
12년 7월 22일 일요일
개념 하나에 단어 하나를 사용하라
• 추상적인 개념 하나에 단어 하나를 선택
• ex) fetch, retrieve, get을 제각각 사용할 경우 혼란이 초래
• 일관성 있는 어휘를 사용해라
12년 7월 22일 일요일
말장난을 하지 마라
• 한 단어를 두 가지 목적으로 사용하지 마라
• Ex) 기존 값 두개를 더하거나 이어서 새로운 값을 만드는 메소드 add가 있을 경우
• 집합에 값 하나를 추가하는 메소드는 무엇으로 해야할까?
• add 보다 insert나 append가 적당
12년 7월 22일 일요일
해법 영역에서 사용하는 이름을 사용하라
• 기술적인 개념에는 기술적인 이름이 적합
• 코드를 읽는 사람은 프로그래머
• 문제 영역에서 모든 이름을 가져 올 경우 같은 기존 개념과 충돌이 있을 수 있음
• EX) AccountVisitor, JobQueue ...
12년 7월 22일 일요일
문제 영역과 관련 있는 이름을 사용하라
• 적절한 ‘프로그래머 용어’가 없을 경우 문제 영역 내의 이름을 사용
• 유지 보수시 업무 전문가를 통해 의미 파악 가능
• 문제 영역 개념과 관련 깊은 코드라면 문제 영역의 이름을 사용
12년 7월 22일 일요일
의미 있는 맥락을 추가하라
• 대다수 이름은 스스로 의미가 분명하지 않다
• 클래스, 함수, 이름 공간에 넣어 맥락을 부여
• 모든 방법이 실패하면, 접두어를 사용해라
• Ex) firstName, lastName, street, houseNumber, city, state, zipcode
• 전체적으로 보면 주소를 표현 한 것을 알 수 있지만, 각각을 보았을 때는 의미가 모호
• addr 접두어 추가
• addrFirstName, addrLastName, addrStreet, addrHouseNumber ...
• But, Address 클래스를 생성하고, 그 속성으로 사용하는 것이 더 효과적
12년 7월 22일 일요일
의미 있는 맥락을 추가하라 - 예제맥락이 불분명한 변수 클래스를 사용하여 맥락을 분명하게 한 변수
private void printGuessStatistics(char candidate, int count) { String number; String verb; String pluralModifier; if(count == 0) { number = "no"; verb = "are"; pluralModifier = "s"; } else if(count == 1) { number = "1"; verb = "is"; pluralModifier = ""; } else { number = Integer.toString(count); verb = "are"; pluralModifier = "s"; } String guessMessage = String.format("There %s %s %s %s", verb, number, candidate, pluralModifier); print(guessMessage); }
public class GuessStatisticsMessage{ private String number; private String verb; private String pluralModifier; public String make(char candidate, int count) { createPluralDependentMessagePars(count); return String.format("There %s %s %s %s", verb, number, candidate, pluralModifier); } private void createPluralDependentMessagePars(int count) { if(count == 0) { thereAreNoLetters(); } else if(count == 1) { thereIsOneLetter(); } else { thereAreManyLetters(count); } } private void thereAreNoLetters() { number = "no"; verb = "are"; pluralModifier = "s"; } private void thereIsOneLetter() { number = "1"; verb = "is"; pluralModifier = ""; } private void thereAreManyLetters(int count) { number = Integer.toString(count); verb = "are"; pluralModifier = "s"; } }
12년 7월 22일 일요일
불필요한 맥락을 없애라
• 의미가 분명한 경우에 짧은 이름이 긴 이름보다 낫다
• Ex) 고급 휘발유 충전소(Gas Station Deluxe) 시스템 내의 클래스 이름
• 모든 클래스의 접두어로 GSD를 사용하는 것은 바람직하지 못함
12년 7월 22일 일요일
마치면서
• 좋은 이름을 선택하려면?
• 설명하는 능력이 뛰어나야 한다
• 문화적 배경이 같아야 한다
• 좋은 이름은 가독성을 높인다
• 자신의 기억력에 의존하기 보다는 명확하고 읽기 쉬운 이름을 사용해라
12년 7월 22일 일요일