티스토리 뷰

책/Clean Code

2장 이름

IT공부블로그 2019. 7. 16. 20:28
728x90
반응형

의도가 분명하게 이름을 작성하라


변수나 함수 그리고 클래스 이름은 다음과 같은 굵직한 질문에 모두 답해야한다. 

1. 변수(혹은 함수나 클래스)의 존재 이유는? 

2. 수행 기능은? 

3. 시용 방법은? 

따로 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다


public List<int[]> getThem() {

List<int[]> listl = new ArrayList<int[]>();

for (int[] x : theList)

if (x[0] 二二 4)

listl.add(x);

return listl;

}


위 코드는 단순하지만 읽기 어렵다

문제는 코드의 단순성이 아니라 코드의 함축성이 훨씬 중요하다


코드 맥락이 코드 자체에 명시적으로 드러나지 않는다


위 코드는 암암리에 독자가 다음과 같은 정보를 안다고 가정한다.

1. theList에 무엇이 들었는가?

2. theList에서 0번째 값이 어째서 중요한가?

3. 값 4는무슨 의미 인가?

4. 함수가 반환하는 리스트 listl을 어떻게 사용하는가?


public List<int[]> getFlaggedCells() {

List<int[]> flaggedCells = new ArrayList<int[]>();

for (int[] cell : gameBoard)

if (cell[STATUS_VALUE] == FLAGGED)

flaggedCells.add(cell);

return flaggedCells;

}


위와 같이 이름만 고쳐도 좋은 코드가 될수있다


그릇된 정보를 피하라


나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용해도

안 된다

ex) hp  직각삼각형의 빗변(hypotenuse)으로 할때 좋아보여도 hp를 체력으로 오해할수있다.


서로 흡사한 이름을 사용하지않도록 주의


유사한 개념은 유사한 표기법을 사용한다 일관성이 떨어지는 표기법은 그릇된 정보다


의미있게 구분하라


컴파일러나 인터 프리터만 통과하려는 생각으로 코드를 구현하는 프로그래머는 스스로 문제를 일으킨다


동일한 범위 안에서 다른 두 개념에 같은 이름을 사용하지 못한다.

그래서 프로그래머가 한쪽 이름을 마음대로 바꾸고픈 유혹에 빠진다

이걸 바꿨다가 많은 문제가 야기될수있다


이름이 바뀌면 의미도 달라져야한다


public static void copyChars(char al[], char a 2 []) {

for (int i = 0; i < al.length; i++) {

a2[i] = al[i];

}

}


위와 같은 코드는 아무런 정보도 전달해주지않는다


불용어를 추가한 이름 역시 아무런 정보도 제공하지 못한다


Product라는 클래스가 있다고 가정하자. 다른 클래스를 ProductInfo 혹은 ProductData라 부른다면 개념을 구분하지 않은 채 이름만 달리한 경우다


Info나 Data는 a. an, the와 마찬가지로 의미가 불분명한 불용어다


a나 the와 같은 접두어를 사용하지 말라는 소리가 아니다. 의미가 분명히 다

르다면 사용해도 무방하다


불용어는 중복이다 

읽는사람이 차이를 알도록 이름을 지어야한다


ex) getActiveAccount();

    getActiveAccounts();

    getActiveAccountInfo();


위와 같이 이름을 지으면 뭐가 뭔지 모른다


발음하기 쉬운 이름을 사용하라


class DtaRcrdl02 {

private Date genymdhms;

private Date modymdhms;

private final String pszqint = "102";

/* ... */

}



class Customer {

private Date generationTimestamp;

private Date modificationTimestamp;

private final String recordld = "102";

/* ... */

}


genymdhms 이런건 사용하지말고 2번째 코드같이 작성하자


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


긴 이름이 짧은 이름보다 검색하기 쉽다.

이름 길이는 범위 크기에 비례해야한다


int realDaysPerIdeaIDay = 4;

const int WORK_DAYS_PER_WEEK = 5;

int sum = 0;

for(int j=0; j < NUMBER_OF_TASKS; j++) {

int realTaskDays = taskEstimate[j] * realDaysPerldeaIDay;

int realTaskWeeks = (realTaskDays / WORK_DAYS_PER_WEEK);

sum += realTaskWeeks;

}


숫자 5를 찾는것보다 WORK_DAYS_PER_WEEK 를 찾는게 훨씬 빠르다


인코딩을 피하라


인코딩한 이름은 발음하기 어려우며 오타도 자주 발생한다


인터페이스 이름 앞에는 I 접두어를 붙이지 않는다.

ShapeFactorylmp나 심지어 CShapeFactory가 IShapeFactory보다 좋다


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


변수 이름을 자신만 이해 할수있는 이름으로 바꾸는것은 안된다


단순히 카운트를 세는 변수일경우 i, j, k를 사용가능 ( 단, 짧은 루프이며 이름이 충돌나지않을경우)

전문가 프로그래머는 명료함이 최고라는 사실을 이해한다 자신의 능력을 발휘해 남들이 읽기 쉬운 코드를 작성한다


클래스 이름

 클래스 이름은 명사, 명사구가 적합하다 

 Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않는다

 

메소드 이름

 메서드 이름은 동사나 동사구가 적합하다

 접근자Accessor, 변경자Mutator, 조건자Predicaie는 javabean 표준4에 따라 값 앞에 get, set, is를 붙인다


 string name = employee.getName();

 customer.setName("mike");

 if (paycheck.isPosted())


생성자Constructor를 중복정의overload할 때는 정적 팩토리 메서드를 사용한다


Complex fulcrumPoint = Complex.FromReaINumber(23.0);


위 코드가 아래 코드보다 좋다.


Complex fulcrumPoint = new Complex(23.0);


기발한 이름은 피하라


이름이 너무 기발하면 농담을 기억하는 동안만 이름을 기억한다

 HolyHandGrenade라는 함수가 무엇을 말하는지 알겠는가?기발한 이름이지만 Deleteltems가 더 좋다

 의도를 분명하고 솔직하게 표현하라


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


추상적인 개념 하나에 단어 하나를 선택해 이를 고수한다

 ex) controller, manager 이 2개를 번갈아가면서 사용하지않고 하나를 정해 그것만 사용한다


말장난을 하지 마라


한 단어를 두 가지 목적으로 사용하지 마라. 다른 개념에 같은 단어를 사용한다면 그것은 말장난에 불과하다

 ex) 쭉 add를 두 값을 더하거나  더해서 새로운 값을 만드는데 사용했다가 어떤 집합에 값을 하나 추가하는걸로 사용한다면 add라는 이름이 맞는가?  아니다 insert, append로 사용하는것이 맞다


 프로그래머는 코드를 이해하기 쉽게 짜야 한다. 대충 훑어봐도 이해할 코드 작성이 최종 목표이다.

 의미를 해독할 책임이 독자가 아닌 저자에게 있어야함을 잊어선 안된다.


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


코드를 읽을 사람도 프로그래머라는 사실을 명심한다. 그러므로 전산 용어,알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 괜찮다

 모든 이름을 문제 영역domain에서 가져오는 정책은 현명하지 못하다

 JobQueue를 모르는 프로그래머가 있을까?

 프로그래머에게 익숙한 기술, 개념은 아주 많다. 기술 개념에는 기술 이름이 가장 적합한 선택이다


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


적절한 ‘프로그래머 용어’가 없다면 문제 영역에서 이름을 가져온다

 그러면 코드를 보수하는 프로그래머가 분야 전문가에게 의미를 물어 파악할 수 있다

 우수한 프로그래머와 설계자라면 해법 영역과 문제 영역을 구분할 줄 알아야한다. 

 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와야한다


의미 있는 맥락을 추가하라


스스로 의미가 분명한 이름이 없지 않다. 하지만 대다수 이름은 그렇지 못하다.

 그래서 클래스,함수,이름 공간에 넣어 맥락을 부여한다

 모든 방법이 실패하면 마지막 수단으로 접두어를 붙인다


 ex) firstName,lastName, street, houseNumber, city, state, zipcode라는 변수가 있다면

   위 변수들을 차례대로 본다면 주소라는것을 알수있지만 state같은 변수 1개만 본다면 주소라는것을 알수가없다

  그래서 addState, addFirstName 과 같이 앞에 접두어를 추가하면 맥락이  좀 더 분명해진다.


 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 = ,,n;

} else {

number = Integer.toSt ring(count);

verb = "are";

pluralModifier = "s";

}


String guessMessage = String.format(

"There %s %s %s%s", verb, number", candidate, pluralModifier

);

print(guessMessage);

}


위와 같은 코드는 number, verb, pluralModifier가 함수 전반에 나오고 이것들이 guessMessage에 사용된다는것을 함수 마지막까지 읽어야 확인할수있다


함수를 쪼개고자  GuessStatisticsMessage라는 클래스를 만든 후 세 변수를 클래스에 넣었다. 그러면 세 변수는 맥락이 분명해진다


이렇게 맥락을 개선하면 함수를 쪼개기가 쉬워지므로 알고리즘도 좀 더 명확해진다


public class GuessStatisticsMessage {

  private String number;

  private String verb;

  private String pluralModifier;


public String make(char candidate, int count) {

createPluralDependentMessageParts(count);

return String.format(

"There %s %s %s%s",

verb, number, candidate, pluralModifier );

}


private void c reatePlu ralDependentMessagePa rts(int count) {

if (count == 0) {

thereAreNoLetters();

} else if (count == 1) {

thereIsOneLetter();

} else {


thereAreManyLetters (count);

}

}


private void thereAreManyLetters(int count) {

number = Integer.toSt ring(count);

verb = "are";

pluralModifier = "s";

}


private void thereIsOneLetter() {

number = "1";

verb = "is";

pUiralModifier = "";

}


private void thereAreNoLetters() {

number = "no";

verb = "are";

pluralModifier = "s";

}

}


불필요한 맥락을 없애라


 ‘고급 휘발유 충전소Gas Station Detae’라는 애플리 케이션을 짠다고 가정하자. 

  모든클래스 이름을 GSD로 시작하겠다는 생각은 전혀 바람직하지 못하다

  ex) GSD 회계 모듈에 MailingAddress 클래스를 추가하면서 GSDAccountAddress로 이름을 바꿨다. 

  나중에 다른 고객 관리 프로그램에서 고객주소가 필요하다. 

  GSDAccountAddress 클래스를 사용할까? 이름이 적절한가


  일반적으로는 짧은 이름이 긴 이름보다 좋다. 단,의미가 분명한 경우에 한해서다.

  이름에 불필요한 맥락을 추가하지 않도록 주의한다


   Address는 클래스 이름으로 적합하다. 

   포트 주소,MAC 주소, 웹 주소를 구분해야 한다면 PttstalAddress, MAC,URI라는 이름도 괜찮겠다


마치며


사람들이 이름을 바꾸지 않으려는 이유 하나는 다른 개발자가 반대할까 두려워서다

  여느 코드 개선 노력과 마찬가지로 이름 역시 나름대로 바꿨다가는 누군가 질책할지도 모른다. 

  그렇다고 코드를 개선하려는 노력을 중단해서는 안 된다

  이 장에서 소개한 규칙 몇 개를 적용해 코드 가독성이 높아지는지 살펴보라.

  다른 사람이 짠 코드를 손본다면 리팩터 링 도구를 사용해 문제 해결 목적으로 이름을 개선하라. 

  단기 적인 효과는 물론 장기적인 이익도 보장한다

728x90
반응형

' > Clean Code' 카테고리의 다른 글

4장 주석  (0) 2019.07.19
3장 함수  (0) 2019.07.18
1장 깨끗한 코드  (0) 2019.07.15
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함