티스토리 뷰

[프로그래밍 방법론] 의미 있는 변수, 함수 명명법 – Clean Code


이 글은 Clean Code 책의 내용을 정리한 것입니다.


소프트웨어에서 명명법은 어디서든 쓰입니다. 우리는 개발 당시 변수에도 이름을 붙이고, 함수에도 이름을 붙이며, 심지어 인수와 클래스, 패키지에도 이름을 붙입니다. 그렇기 때문에 이름에 대한 정리를 잘하게 되면, 개발자 자신은 물론 다른 개발자들도 이해하기 쉬운 코드가 됩니다. 그럼 명명법을 할 때 주의해야 하는 내용에 대해서 정리를 해보도록 하겠습니다.


1) 의도를 분명히 밝혀라


변수, 함수, 클래스 이름을 지정할 때 다음과 같은 질문에 답이 되어야 합니다.

  • 변수(혹은 함수나 클래스)의 존재 이유는 무엇인가?
  • 수행기능과 사용방법은 무엇인가?
  • 주석이 필요한가?

아래의 코드를 보고 좀 더 설명을 드리겠습니다.


public List<int[]> getThem(){

List<int[]> list1 = new ArrayListList<int[]>();

for(int[]x : theList)

if(x[0] == 4)

list1.add(theList)

return list1;

}


위와 같은 코드가 있다고 가정을 하면, 코드가 하는 일을 개발자가 이해하기가 어렵습니다. 즉 가독성이 떨어진다는 의미가 되겠죠.

이 함수에는 화려한 클래스나 다형성 메소드도 없지만, 이름을 잘못 사용하였기에 문제가 됩니다. 이 문제는 코드의 단순성이 아니라 코드의 함축성에 문제를 가지고 있는것입니다.


위의 코드 샘플에는 theList의 목적, 0번째 값이 중요도, 4의 의미가 모두 들어있지 않습니다. 이 코드의 함축성에 문제를 해결하고자 하면 아래와 같이 수정을 할 수 있습니다.


public List<int[]> getFlaggedCells(){

List<int[]> FlaggedCells = new ArrayListList<int[]>();

for(int[]cell : gameBoard)

if(cell[STATUS_VALUE] == FLAGGED) // 혹은 if(cell.IsFlagged())

FlaggedCells .add(cell )

return FlaggedCells ;

}


코드의 단순성을 변화지 않았으나, 명명법을 통해서 코드가 나타내는 함축성에 대한 문제가 해결이 되어 독자가 읽기에 더 편리한 코드가 되었습니다.


2) 그릇된 정보를 피하라.


프로그래머는 코드에 그릇된 단서를 남겨서는 안됩니다. 그릇된 정보는 코드의 의미를 흐리는 역할을 하기 때문이죠.

예를 들어 hp, aix, sco는 변수 이름으로 적합하지 않습니다. 이는 유닉스 플랫폼을 가르키는 의미를 지닌 값이기 때문입니다. 


그릇된 정보를 제공하는 가장 큰 예는 소문자 l이란 대문자 O를 변수 이름으로 사용할 때 입니다. 이는 숫자 1과 0을 혼동하게 할 수 있기 때문에 피해야 합니다. 이런 코드가 많은 부분에서 사용되고 있는걸 확인할 수 있습니다.


3) 의미 있게 구분하라.


컴파일러나 인터프리터 만 통과하려는 생각으로 코드를 구현해서는 안됩니다. 예를 들어 동일 범위에서 다른 두 개념에 같은 이름을 사용하지 못하기 때문에 다른 이름을 마음대로 바꾸고자는 유혹에 빠지기 쉬운데 이렇게 개발을 하면 향후 디버깅에 많은 어려움을 가지게 됩니다.


또한 연속적인 숫자를 덧붙이거나 불용어를 추가하는 방식은 적절하지 못한다. 연속적인 숫자를 a1, a2, ... , aN으로 사용하는 방식을 옳지 않습니다.


하지만 우리는 많은 코드에서 이러한 부분을 확인 할 수 있습니다. 


public static void copyChars(char a1[], char a2[])

{

...

}


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


아래의 예를 통해서 발음하기 쉬운 이름을 사용하는것이 코드 리뷰를 할 때 얼마나 도움이 되는지를 확인할 수 있다.


class DtaRcrd102

{

private Date genymdhms;

}


class Customer

{

private Date generationTimeStamp;

}


"디티에알치알디일공이 클래스의 지이엔와이엠디에이치엠에스" 변수를 살펴봅시다가 편리한가?

"커스터머 클래스의 제너레이션타임스탬프" 변수를 살펴봅시다가 편리한지 한번 생각해 보시기 바랍니다.


5) 인코딩을 피하라.


굳이 부담을 더하지 않더라도 이름에 대해 인코딩할 정보는 아주 많습니다. 따라서 인코딩 '언어'까지 익히라는 요구는 비합리적입니다. 문제해결을 집중해야 하는 개발자가 인코딩에 대한 불필요한 정신적 부담을 가질 필요는 없습니다.

  • 과거 이름 길이가 제한된 언어를 사용했을 때에 고안된 헝가리식 표기법을 굳이 따를 필요는 없습니다.
  • 멤버 변수에 m_이라는 접두어에 붙일 필요가 이제는 없습니다. 
  • 인터페이스에는 I를 붙이지 않도록 합니다. 차라리 인터페이스를 IShapeFactory되는 CShapeFactory 혹은 ShapeFactoryImp로 이를 구현하는 클래스를 ShapeFactory로 두는 방식은 어떨까요?


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


문자 하나만 사용하는 변수 이름은 문제가 있습니다. 루프범위가 작을때 빼고는 문자 하나를 이용한 변수를 선언하지 않도록 합니다. 똑똑한 프로그래머와 전문가 프로그래머 사이에서 나타나는 가장 큰 차이점은 코드의 명료함이 최고인지를 알고 있냐, 모르냐입니다.


코드는 남이 이해하기 좋은 코드가 좋은 코드입니다.

  • 클래스 : 명사나 명사구로 명명
  • 메소드 : 동사나 동사구로 명명

7) 기발한 이름은 피하라.


이름이 기발하면 동일한 기억이나 코드성향을 가진 사람만 알 수 있습니다.


8) 한 개념에 한 단어를 사용하라.


추상적인 개념하나에 단어 하나를 선택해서 고수해야 합니다. 똑같은 메소드를 클래스마다 fetch, retrieve, get으로 제각각 부르면 API를 사용하는 사람 입장에서는 혼란을 가져오게 됩니다. 


이클립스, 인텔리제이 등과 같은 최신 IDE는 문맥에 맞는 단서를 제공합니다. 이를 충분히 활용하도록 합시다.


9) 해법 영역 혹은 문제 영역에서 가져온 이름을 사용하라.


적절한 프로그래머 용어가 없다면 기존의 영역에서 가져온 이름을 사용합니다. 코드를 읽는 사람도 어짜피 프로그래머 이기 때문에 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어등을 사용해도 괜찮습니다. Visitor 패턴에 익숙한 개발자라면 AccountVisitor라고 명명된 클래스를 이해하기 더 쉬울겁니다.


10) 의미 있는 맥락과 불필요한 맥락의 구분


firstName, lastName, street, houseNumber, city, state라는 변수가 있으면 이는 주소에 대한 내용인걸 인지 할 수 있지만, state 변수만 보면 이 변수의 의미를 파악하기 어렵습니다. 따라서 addr이라는 접두어를 만들어 addrFirstName 등으로 변경한다면 좀더 명확해 질 수 있습니다. 


하지만 고급 휘발유 충전소(Gas Station Deluxe)라는 어플리케이션을 만든다고 해서 모든 클래스 이름 앞에 GSD를 붙이는건 정말 잘못된 방법입니다. 


마치면서,


우리들 대다수는 자신이 짠 클래스와 메소드 이름을 모두 암기하지 못합니다. 따라서 우리는 문장이나 문단처럼 읽히는 코드 아니면 적어도 표나 자료 구조처럼 읽히는 코드를 짜는데 집중해야 합니다.


"이는 코드에 대한 가독성을 높여, 생산성을 끌어 올려주는 역할을 하기 때문입니다. "


이 글이 도움이 되셨나요?

그렇다면 아래의 그림을 클릭해주세요.


댓글