티스토리 뷰

반응형

 

개발뿐만 아니라 다른 분야에서도 전문 용어를 사용하는 이유는 한 단어로 많은 뜻을 전달하기 위해서예요. 있는 용어를 사용하는 것이 아니라 이름을 직접 명명해서 사용할 일이 많은 개발에서는 이름을 잘 짓는 것이 중요해요. 다른 사람이 내 코드를 읽을 때 이름 하나로 역할을 보다 쉽게 이해할 수 있을지, 없을지가 결정되기 때문이죠. 

 

애플의 경우 Swift 네이밍 규칙을 API Design Guidelines(https://www.swift.org/documentation/api-design-guidelines/#naming)에 만들어 두었어요.

 

클린 코드 2장에서는 Swift에 한정된 네이밍이 아니라 일반적으로 코딩에서 좋은 명명법에 대해 이야기 해요.

 

다른 글과 다르게 번호가 길어져 나의 생각을 다홍색으로 부분 부분 추가해보려고 해요. 

 

1. 의도를 분명히 밝혀라

변수의 존재 이유, 수행 기능, 사용 방법을 이해하는데 따로 주석이 필요하다면 이름을 통해 의도를 분명히 드러내지 못한 것이에요. 코드의 복잡성과 무관하게 함축성이 코드를 읽는데 영향을 줄 수 있어요. 즉, 코드가 아무리 단순한 구조라 하더라도 의미가 불분명한 네이밍이 된다면 그 코드가 무엇을 위한 것인지(e.g. 그 함수의 역할이 무엇인지) 이해하기 힘들 수 있어요.

 

나의 생각: iOS는 특히 목표 자체가 네이밍이 길어지더라도 의도를 매우 분명히 전달할 것, 영어 문장처럼 읽히게 할 것을 요구하기 때문에 이 부분에 신경을 많이 썼었어요. 하지만 이 주제에 대해 회사에서 대화를 할 때 이게 절대 진리는 아닐 수도 있다는 이야기를 들었어요. 예시로 봤던 코드는 Ruby였는데 코드는 대략 아래와 같았어요.

u = User.getUser()

제가 받은 질문은 위의 u라는 변수가 무엇일 것 같냐는 질문이었고(물론 실제 코드는 더 복잡했어요) u가 유저 정보라는 것을 코드 문맥을 통해 대답할 수 있었어요. "충분히 이해가 가능할 경우 꼭 이런 네이밍이 나쁘지 않을 수 있다, 또한 컴파일러 입장에서도 읽는 코드량이 줄어들기 때문에 좋을 수 있다"라는 말을 들었어요. 무엇이 정답이라기보다 그만큼 개발자들 간의 컨벤션 합의가 중요하고, 절대적인 정답은 없다고 생각해요. 언어마다, 개발 팀마다 더 좋은 네이밍이라는 것은 다르게 정의될 수 있을 것 같아요. 그래도 제가 코드를 작성한다면 애플의 의도에 맞춰 길더라도 의미를 분명히 전달하는 방향으로 작성할 것 같아요.

 

2. 그릇된 정보를 피하라

나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용하면 안 돼요. 

 

예를 들면, 직각삼각형의 빗변(hypotenuse)을 약어 'hp'로 네이밍 한다면 이것은 유닉스 플랫폼으로 오해받을 소지가 있어요. 또한 여러 계정을 그룹으로 묶을 때, accountList라는 이름은 개발자에게 혼란을 줄 수 있어요. 일반적으로 List라는 영어 단어와 개발에서 List는 다른 의미일 수 있기 때문이에요.

나의 생각: 여러 계정을 그룹으로 묶을 때 List나 묶음이라는 의미의 네이밍보다 복수형을 사용하는 네이밍을 사용했어요. 그래서 단수/복수 구분을 위해 네이밍에서 s를 제거하는 수정 작업에 시간을 많이 들인 경험이 있어요.. 꼭 이름 자체에 여러 개라는 의미를 주는 단어가 들어가는 것이 아니라 단수/복수를 구별함으로써 표현해 줄 수 있을 것 같아요.

 

또 숫자 0과 알파벳 'O'처럼 혼동을 줄 수 있는 표현 역시 주의해야 해요.

if O == 1 {
	...
}

같은 코드가 있다면 빠르게 지나가면서 0이 1인 경우라고 생각할 수 있어요. 그러면 항상 false인 코드로 여겨질 수 있어요. 

 

3. 의미 있게 구분하라

컴파일러 통과를 목표로 네이밍을 대충 하는 코드를 경계해야 해요. 특히 연속된 숫자를 붙이거나 불용어(noise word)를 사용하는 건 적절하지 못해요.

 

예를 들면, 연속된 변수에 a1, a2, a3... 같은 네이밍을 하는 것은 의도나 정보를 전달할 수 없어요.

Product라는 클래스가 있을 때, 다른 클래스를 ProductInfo나 ProductData라고 부른다면 개념을 구분하지 않은 채 이름만 달리 한 것이에요. 

 

변수 이름에 variable이라는 단어는 금물이에요. 표 이름에 table이라는 단어도 피해야 해요. Name이라는 변수명을 NameString으로 한다고 더 나아질 것은 없어요. Name의 타입은 String이 되는 것이 자연스럽기 때문이에요. 만약 int 등의 다른 타입이라면 Name이라는 네이밍 자체에 대해 생각해볼 필요가 있을 거예요.

 

나의 생각: 작동만 하는 코드를 위해 네이밍에 불용어를 사용하지 않는다는 것은 중요하다고 생각해요. 하지만 경우에 따라서 Product라는 클래스가 있을 때 다른 클래스에 ProductData라는 네이밍을 충분히 할 수 있다고 생각해요. 책 내용은 일반화된 경우를 상정해서 설명하기 때문에 당연한 설명일 수 있지만, iOS의 경우로 생각해본다면 전체 구조, 문맥에 따라서 분명히 사용할 수 있는 네이밍이라고 생각해요. "Product가 있을 때 ProductData 같은 네이밍은 개념 구분이 안됐다"라고 단정 짓기보다 "ProductData라는 이름을 사용할 거라면 문맥상 다른 개발자들이 보았을 때 그 객체의 역할이 이해가 가야 한다"라고 생각했어요.

 

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

발음이 어려우면 실제 토론에서도 어려움이 생겨요. 

 

generationTimestamp라는 변수를 genymdhms라는 변수로 축약할 경우 실제 토론에서는 발음하기가 어려워져요. 

이것도 책에 나온 것처럼 하나의 재미였던 것 같긴 해요ㅋㅋ 발음 만들기..

 

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

문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈이 띄지 않는 데다가 검색할 경우 어려움이 있을 수 있어요.

 

예를 들어, 변수명이 'e'인 경우 검색을 e로 하면 e가 들어가는 모든 결과물이 나오기 때문에 원하는 변수를 검색하는데 어려움이 있어요. 저자는 간단한 메서드에서 로컬 변수만 한 문자로 사용해요.

 

나의 생각: 이건 정말 중요한 포인트라고 생각해요. 책에서 나온 내용과 반대로, 제가 가장 이 부분을 크게 경험한 건 "내가 작성하지 않은 객체를 검색할 때"였어요. 컨벤션이 통일되어있고 "특정 역할을 하는 게 이미 있지 않을까?"라는 추측으로 제가 만들법한 네이밍으로 검색했을 때 원하는 결과물이 나오면 그 기쁨이 굉장하더라고요. 그래서 그 이후로 더 네이밍에 신경 썼던 것 같아요. 제가 있던 iOS팀에게서 다른 사람이 작성했지만 내가 작성한 것처럼 코드가 되는 방향으로 PR 리뷰하는 것을 배웠어요. 물론 내 생각대로 그 사람의 코드를 바꿔야 하는 거랑은 전혀 다른 문제고요.

 

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

문자 하나만 사용하는 변수 이름은 문제가 있어요. 다만 루프에서 반복 횟수를 세는 변수 i, j, k는 괜찮아요. 단, 루프의 범위가 아주 작고 다른 이름과 충돌하지 않을 때만 괜찮아요. 자신이 기억력이 좋다면 자신의 능력을 좋은 방향으로 사용해 남들이 이해하는 네이밍을 해야 해요.

 

나의 생각: 사실 단순 반복문을 사용할 경우가 한 번도 없던 것 같아요. 사용을 하면 안 되는 게 아니라 단순 반복이 필요할 경우 고차 함수를 사용해서 불필요한 변수를 만들지 않으려고 했던 것 같아요. 물론 반복문 안의 로직이 복잡해지면 필요한 경우도 분명히 있겠지만, 그 역시도 for문 안의 로직을 메서드 분리하는 등의 방법으로 파훼할 수 있을 것 같아요.

 

7. 메서드 이름

메서드 이름은 동사나 동사구가 적합해요.

 

나의 생각: Swift(iOS)의 경우 명사형 네이밍도 많이 써요. 오히려 Java와 다르게 get이라는 prefix를 붙이는 걸 꺼려해서 get은 피하고 꼭 그 의미를 담고 싶다면 fetch 등의 이름을 붙일 수 있을 것 같아요. 다만 명사형 네이밍이라도 메서드의 역할이 분명해야 하고, 반환되는 값의 타입이나 정보를 유추할 수 있다면 더 좋을 것 같아요.

 

8. 기발한 이름은 피하라

재미있는 이름보다 명료한 이름을 선택해요.

 

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

추상적인 개념 하나에 단어 하나를 선택해 이를 고수해요. 예를 들면, 똑같은 메서드를 클래스마다 fetch, retrieve, get으로 제각각 부르면 혼란스러워요.

 

나의 생각: 이름 하나로도 PR 리뷰에서 많은 대화가 있었던 것 같아요. 책에서 나오듯 fetch나 retrieve, get은 비슷한 의미로 써서 혼용되면 문제가 되지만 제가 있던 팀의 경우 그 미묘한 차이를 정의하려고 했어요. fetch도 가져오는 것이고 get도 가져오는 것이지만 영어로서도 미묘한 의미 차이가 있기 때문에 객체의 역할에 따라 네이밍에 차이를 두려고 했어요. fetch와 get을 꼭 섞어 쓰면 혼란스러운 게 아니라 이마저도 역할 차이를 정의해두면 충분히 다른 의미로 사용될 수 있기 때문에 오히려 객체의 역할을 이해할 때 더 디테일하게 해석할 수 있을 것 같아요.

 

10. 말장난을 하지 마라

9번에서 한 개념에 한 단어를 사용한다고 해서 무조건 같은 단어를 사용하라는 뜻은 아니에요.

 

예를 들어, 어떤 객체에서 두 수를 더해 한 가지 결과물을 반환하는 메서드를 add라고 명명했을 때 다른 객체에서도 무조건 add라는 네이밍을 고수해야 하냐면 그건 아니에요. 예를 들어, 다른 객체에서 Array에 값을 넣는 동작을 하는 메서드가 있을 때 이 때에도 add로 통일을 해야하냐면 그건 적절하지 않은 거죠. 역할이 비슷한 듯 다르기 때문에 이럴 때에는 insert나 append가 더 적합할 거예요.

 

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

코드를 읽을 사람은 프로그래머이기 때문에 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 괜찮아요. 모든 이름을 문제 영역(domain)에서 가져오는 것은 현명하지 못해요.

 

나의 생각: 이것도 회사나 팀에 따라 다르다고 생각해요. 제가 있던 회사의 경우, iOS 코드를 iOS 개발자만 보는 것이 아니라 백엔드 개발자, 개발 백그라운드가 없는 PM 분들도 와서 보셨어요. 그래서 Jira로 해당 PR 정보를 첨부하거나 PR 메시지를 자세히 적는 게 더 중요했었어요. 완벽하게 용어가 필요한 부분이라면 당연히 그 이름을 사용하는 게 괜찮다고 생각해요. 다익스트라 알고리즘을 사용하는데 그 부분의 이름을 굳이 다른 걸로 채우면 그게 더 어색할 수 있을 것 같아요. 다만, 코드를 읽을 사람을 프로그래머로 한정해서 용어의 남발을 허용하는 건 경우에 따라 적절하지 않을 수도 있을 것 같아요. 

 

12. 도메인에서 가져온 이름을 사용하라

적절한 프로그래머 용어가 없다면 도메인에서 이름을 가져와요.

 

나의 생각: 이름이 너무 길어지는 경우에도 도메인의 축약어를 활용하면 괜찮은 경우도 있었어요. 다만, 처음 코드를 읽을 때 전혀 무슨 의미인지 몰라서 질문하게 되더라고요. 그래도 회사 내에서 사용되는 축약어 정리를 찾아 읽고 난 후에는 한결 수월했던 것 같아요.

 

13. 의미 있는 맥락을 추가하라

이 부분은 예를 통해 확인하는 게 이해가 더 쉬울 거 같아요.

 

firstName, lastName, street, houseNumber, city, state, zipcode라는 변수가 있는 객체가 있어요. 이 경우 변수를 훑어보면 우편을 위한 주소라는 것을 알 수 있어요. 하지만 어떤 메서드가 이 중 state만 가져와야 하는 경우 그 메서드만 보았을 때 state가 어떤 의미인지 알기 어려울 수 있어요. status의 의미로 오역될 여지도 있구요. 

이럴 경우, 주소를 의미하는 addr이라는 접두어를 붙이는 것만으로 맥락을 분명하게 해 줄 수 있어요. 물론 더 좋은 것은 Address라는 클래스를 생성하는 방법이에요.

 

나의 생각: 개인적으로 변수 자체에 접두어를 붙이는 것보다 Class나 Enum으로 묶어서 표현하는 게 더 좋다고 생각해요. addrState 보단 Address.state가 훨씬 직관적이라고 느꼈어요.

 

14. 불필요한 맥락을 없애라

고급 휘발유 충전소(Gas Station Deluxe)라는 애플리케이션을 짠다고 할 때, 모든 클래스 이름을 GSD로 시작할 필요는 없어요. 의미 중복을 불러일으킬 수 있고, IDE에서 자동완성 시 문제가 될 수 있어요. 모든 클래스에 GSD가 붙어있기 때문에 G를 친다는 것은 모든 클래스를 본다는 의미가 될 수 있죠.

 

일반적으로 짧은 이름이 긴 이름보다 좋아요. 하지만 그것보다 중요한 것은 의미가 분명해야 해요. 그래서 의미를 충분히 드러낸다면, 불필요한 맥락이 추가될 필요는 없어요.

 

 

 

 

클린코드(Clean Code) by Robert.C.Martin

 

반응형
댓글