도대체뭐가문제임

변수명에 관하여 본문

개발 기타

변수명에 관하여

뭐가문제임 2021. 4. 29. 12:53

개발을 처음 접할때는 변수라는 개념부터 잘 와닿지 않았다.

일상에서 사용하는 변수라는 단어는 한자의미 그대로 "변할 수 있는 수" 였다.

하지만 프로그래밍에선 변수(Variable)에 [저장공간]의 개념이 붙는다.

저장공간(메모리) 안에 담기는 수가 변할 수 있기 때문에 변수라고 부르는 것이다.

메모리에 담기는 변하지 않는 수는 상수라고 부른다.

 

처음 혼자 개발을 할 땐 변수명이 그다지 중요한 요소가 아니었다.

프로젝트의 규모도 크지 않고 개발하는 스스로만 구분할 수 있다면 이름이 a, b, c라도 상관이 없었다.

하지만 여러사람과 함께 개발을 하고 프로젝트의 규모가 생기면서 변수명은 생산성에 중요한 요소가 되었다.

목적에 맞는 올바른 이름을 가진 변수는 변수명을 읽는 것만으로도 어느정도 역할을 파악할 수 있었지만 임의적으로 지은 변수명이나 목적에 올바르지 않은 변수명은 프로젝트 혹은 다른 사람의 코드를 파악하는데 걸림돌이 되었다.

 

그래서 변수명에 관한 정리를 해보고자 한다.

 

변수명의 기본 규칙

컴파일러에서 제한하는 변수 명명 규칙

  • 대소문자는 구분되며 길이의 제한은 없다.
  • 예약어를 사용해서는 안 된다.
  • 숫자로 시작하면 안 된다.
  • 특수문자는 _  $ 만 허용한다.

JE22 에서 권장하는 변수 명명 규칙

  • 변수는 첫 글자의 소문자로 시작하는 명사로 짓는다.
  • 여러 단어로 이루어진 이름인 경우 각 단어의 첫 글자를 대문자로 한다. (카멜 표기법 사용)

예시.

//예약어를 사용할 수 없다.
var true: Boolean = false

//숫자로 시작할 수 없다.
var 1stUserName: String = "robin"

//변수명은 첫글자의 소문자로 시작하는 명사로 짓는다.
//여러 단어로 이루어진 이름인 경우 각 단어의 첫 글자를 대문자로 한다.(CamelCase)
var userAge: Int = 10

예약어

자바의 예약어

abstract assert boolean break byte case catch
char class const continue default do double
else extends false final finally float for
goto if implements import instanceof int interface
long native new null package private protected
public return short static super switch synchronized
this throw throws transient true try void
volatile while          

 

 

좋은 변수명을 짓기 위한 몇 가지 방법

변수의 목적을 분명히 하도록 이름짓기

변수명은 하나의 목적을 표현하도록 변수가 가지는 의도를 명확하게 밝히는 것이 좋다.

 

예시.

//findItem의 인자 i의 의도를 바로 알기 어렵다.
fun getItem(i: Int) {
//생략
}

//인자 i의 의도를 변수명으로 정확히 나타낼 수 있다.
fun getItem(itemIndex: Int) {
//생략
}
//page와 currentPage가 이렇게 같이 있다면 page의 의도가 애매해지기때문에 좋은 변수명이라고 하기 어렵다.
var page: Int = 30
var currentPage: Int = 10

 

협업을 염두해서 이름짓기

private void validateNumericPosition(String[] expressionAsArray) {
    for (int i = 0; i < expressionAsArray.length; i += 2) {
    	...
    }
}

위 코드에서 2가 의미하는게 뭘까? 다른 사람이 봤을 때 i += 2 를 통해 어떤 처리를 하는지 파악하려면 코드를 분석해야 한다.

private void validateNumericPosition(String[] expressionAsArray) {
    int numberIndex = 2;
    for (int i = 0; i < expressionAsArray.length; i += numberIndex) {
    	...
    }
}

2에 numberIndex 라는 의미 있는 변수명을 붙여주면 숫자만 걸러내기 위한 식인지 알 수 있다.

맥락을 고려해서 짓기

//정확한 의도를 담으려는 의도는 좋지만 굳이 User 클래스의 속성값에도 user라는 키워드가 들어갈 필요는 없다.
data class User(
	var userName: String,
	var userAge: Int
)

//개선
data class User(
	var name: String,
	var age: Int
)

위의 클래스는 읽어보자면 사용자의 사용자명, 사용자의 사용자 나이 이다.

변수의 의도를 분명히 나타내도록 최대한 자세하게 적는 것은 좋지만 과하다면 오히려 독이된다.

의도를 분명히 나타내려다보니 변수명이 너무 길어진다면 약속에 따라 축약어를 사용하는 것도 좋은 방법이다.

 

Boolean 변수에 대하여

Boolean은 true 혹은 false를 표현한다.

즉, 맞다 혹은 아니다의 상태만 표현하는 변수이다.

그렇기 때문에 Boolean의 변수명은 맞다 혹은 아니다로 대답할 수 있도록 지어야한다.

그래서 보통 Boolean 변수명은 be동사 is, 조동사 has, can, should, 동사원형 includes, allows등을 앞에두는 등 의문문 형식의 변수명을 사용한다.

하지만 done, error, ok 등 성공과 실패의 의미를 나타내고자 한다면 found, processingComplete등 무엇을 성공했는지에 대해 구체적인 설명이 되는 변수명을 사용하는 것이 좋다.

 

Boolean 변수는 부정형으로 만들지 않는것이 좋다. 부정을 부정, 부정을 긍정하는 코드는 가독성이 떨어지기 때문이다.

예시.

//해석: 못찾지 않았다.
var notfound: Boolean = false

//해석: 찾았다.
var found: Boolean = true

 같은 의미지만 긍정의미에 대해서 구분하는 편이 더 읽기 좋다.

 

Boolean은 is, 조동사, 동사원형을 사용하여 보통 변수명을 짓지만 경우에 따라 접두어를 생략하는 편이 더 이해하기 쉬운 경우가 있다.

 

예시.

var isComplete: Boolean = true
var complete: Boolean = true

 

Collection 변수에 대하여

val userList: List<User> = listOf<User>()

위와같이 변수명에 자료형이 들어가게 된다면 자료형이 바꾸는 상황(예를들어 List -> Set)에서 변수명도 변경해야하는 번거로움이 생긴다. 

때문에 Collection 자료형은 아래와 같이 복수형으로 표현하는것이 좋다.

val users: List<User> = listOf<User>()

 

참고:

opentutorials.org/module/1226/8103

woowacourse.github.io/javable/post/2020-04-24-variable_naming/

soojin.ro/blog/naming-boolean-variables

 

Comments