[클린코드] 2장 의미 있는 이름

유시준·2022년 4월 12일
0

clean_code

스터디 매주 화, 금

화요일 금요일까지 각각 두장씩 읽고 각자 한 장씩 발표하기

분량에 따라 유동적으로 조정

  • 화요일 : 진형 홀수 장, 시준 짝수 장

  • 금요일 : 시준 홀수 장, 진형 짝수 장

이름

우리가 작성하는 코드는 영어로 작성을 한다. 결국 사람이 읽을 수 있는 문자이기 때문에 가독성이 매우 중요하다. 모든 변수,파일에 이름을 붙이고 이름을 잘 지으면 한눈에 그 파일,변수,함수등의 의도를 파악할 수 있다.

의도

  • 좋은 이름을 지으려면 시간이 걸리지만 좋은 이름으로 절약하는 시간이 훨씬 많다
  • 변수나 함수,클래스의 이름을 지을 때 존재이유,수행기능,사용방법등에 대해 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말

알고리즘 문제를 풀때 흔히 단문자로 변수명을 사용하는 경우가 많다.
실제 개발을 할때는 의미가 분명하게 드러나도록 작성해야한다.

int d;//경과시간
int elapsedTime;//경과시간
  • 위 두 변수는 둘다 경과시간을 나타내는 변수지만 elapsedTime은 주석이 없어도 그 의미를 알수있다.

그릇된 정보를 피하라

  • 애매한 의미를 부여하는 이름을 사용하면 안된다.
  • hp,aix,sco와 같은 변수명은 유닉스 플랫폼을 가리키는 이름
  • 계정들을 묶을 때 accountList라는 변수명을 사용한다면 프로그래머는 해당 컨테이너가 List라 생각할 수도 있다. 실제 List에 저장되어 있지 않다면 잘못된 정보를 제공하는 것
  • 일관성이 떨어지는 정보는 그릇된 정보이다.

의미있게 구분하라

public static void copyChars(char a1[],char a2[]){
	for(int i=0;i<a1.length;i++){
    	a2[i] = a1[i];
    }
}

위 코드는 a2에 a1의 내용을 copy하는 메소드이다.
하지만 메소드의 파라미터를 아래와 같이 바꾼다면 훨씬 읽기 쉬워진다.

public static void copyChars(char source[],char desination[]){
	for(int i=0;i<a1.length;i++){
    	desination[i] = source[i];
    }
}
  • 불용어를 추가한 이름도 아무런 정보를 제공하지 못함
    • ProductInfo,ProductData라는 클래스는 Product클래스와 개념이 구분되지 않는다.
  • 읽는 사람이 차이를 알도록 이름을 지어야한다.

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

class Customer{
	private date genymdhms;
    private date modymdhms;
}
  • GENeratedate,Year,Month,Day,Hour,Minute,Second - GENYMDHMS
  • MODify,Year,Month,Day,Hour,Minute,Second - MODYMDHMS
  • 발음하기도 힘든데 설명이 없다면 무슨 기능을 하는지 이해하기 힘들다.
class Customer{
	private date generationTimestamp;
    private date modificationTimestamp;
}
  • 편안

검색하기 쉬운 이름 사용

  • 단문자와 상수는 코드에서 쉽게 눈에 띄지 않음
  • 검색을 해야하는 상황이 발생하였을 때 해당 문자를 포함하는 이름이 많기 때문에 까다롭다.
  • 긴이름이 짧은 이름보다 좋고 상수보다 좋다.
for(int j=0;j<34;j++){
	s+=(t[j]*4)/5;
}

단문자와 상수가 포함되어 있기 때문에 5나 s를 검색한다면 5를 포함한 모든 이름을 찾기 때문에 원하는 단문자,상수를 아래처럼 가려내야 한다.

int realDaysPerIdealDay = 4;
private static final 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;
}

이름을 의미있게 지으면 메소드가 길어지지만 WORK_DAYS_PER_WEEK변수를 찾기는 매우 쉬워진다.

기억력을 믿지 마라

  • 단문자 사용을 자제해야한다.
  • 반복문 변수 i,j,k는 예외적
  • 모든 변수의 의미를 기억할 수는 없다.

네이밍 규칙

  • 클래스 이름과 객체이름은 명사나 명사구가 적합하다.

    • Customer,Account등이 좋은 예
    • Manager,Data,Info등이 좋지 못한 예
  • 메소드 이름은 동사나 동사구가 적합하다.

    • deletePage,save등이 좋은 예
  • 게터,세터등은 표준에 따라 접두사로 get,set,is를 붙인다.

  • 생성자의 중복정의는 정적 팩토리 메서드를 사용

Complex fulcrumPoint = Complex.FromRealNumber(23.0);

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

Complex fulcrumPoint = new Complex(23.0);

일관성있는 단어선택

  • 추상적 개념 하나에 단어 하나를 선택해야 한다.
    • 클래스마다 fetch,get등 제각각 사용한다면 혼란스럽다.
    • controller,driver,manager를 섞어 쓴다면 혼란스럽다.
  • add메서드가 기존 값 두개를 더하여 새로운 값을 만드는 메서드라고 할 때 집합에 값을 추가하는 메서드를 add라고 한다면 혼란스러울 수 있기 때문에 insert나 append를 사용

의미있는 맥락

  • firstName,lastName,street,houseNumber,city,state,zipcode라는 변수가 있을 때 변수를 본다면 주소를 의미한다는 사실을 금방 알수있다. 하지만 메소드에 state라는 변수만 있다면 의미를 알기 힘들다. 그렇기 때문에 접두사로 addrState,addrFirstName등으로 사용한다면 맥락이 분명해진다.
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 GuessStaticsMessage{
	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 createPluralDependentMessageParts(int count){
        if(count == 0){
			thereAreNoLetters();
        }else if(count == 1){
            thereIsOneLetter();
        }else{
            thereAreManyLetters(count);
        }
    }
}
  • 짧은 이름보다 긴 이름이 좋지만 의미가 분명한 경우에 한해서 이다.
  • 이름에 불필요한 맥락을 추가하지 않도록 한다.

결론

  • 암기는 도구에게 맡기고 읽히는 코드를 짜는데 집중해야 한다.
  • 의미가 명확한 이름을 지어야 한다.
  • 짧은 이름보단 긴 이름이 좋다.
  • 일관성 있게 단어를 선택해야 한다.
profile
금꽁치's Blog

0개의 댓글