[Clean Code] 2. 의미 있는 이름

Youngwoo Lee·2022년 4월 18일
0

Clean Code

목록 보기
2/4
post-thumbnail

들어가며

학부생 시절, 프로젝트 과제를 할 때는, 네이밍을 단 한번도 신경써본 적이 없다. 어차피 프로젝트가 끝나면 보지도 않을 코드... 그리고 과제는 결과만 제출하고, 교수님은 코드를 보지도 않기 때문에 내게는 네이밍은 0.1도 중요하지 않은 포인트였다. iOS 교육을 들으면서 진행하면서 정말 느낀 점이 많지만, 나에게 있어서 가독성 좋은 코드를 작성해야 된다는 점은 새롭게 다가왔다. 어떻게 네이밍을 해야되는지도 몰랐고, 작명소마냥 매순간마다 네이밍에 고민을 하는 것이 매우 어색했다.

Swift를 처음 배울 때, Swift API Guidelines 를 보면서 Swift 특유의 네이밍 규칙에 대해서 익혔다. Clean Code에서는 어떤 규칙을 소개하는지 알아보도록 하겠다.

1. 의도를 밝혀라

변수(혹은 함수나 클래스)의 존재 이유, 수행기능, 사용방법을 설명하는데 있어서 주석이 필요하다면 네이밍 자체가 그 의도를 분명히 드러내지 못하고 있다는 것입니다. 문제는 코드의 단순성이 아니라 코드의 함축성입니다. 즉, 코드가 아무리 단순한 구조라 하더라도 의미가 불분명한 네이밍이 된다면 그 코드가 무엇을 위한 것인지 이해하기 힘들 수 있기 때문입니다.

Swift API Guidelines 를 보면, iOS 에서는 네이밍이 아무리 길어지더라도 함축어를 사용하지 않으며, 영어 문장처럼 읽히는 것을 선호한다. 메서드의 경우 이런 조건을 맞추기 위해 네이밍 하다보면 네이밍이 너무 길어질 경우가 있는데, 가끔 당황스럽기도 하다... 하지만, 이러한 조건들을 지키지 않을 경우 3일만 지나고 다시볼 경우 "이 에서드가 무슨 일을 하더라..?" 라는 생각이 든다.

2. 그릇된 정보를 피하라

여기서 이야기하는 주 내용은 총 4가지 입니다.

  • 첫째, 나름대로 널리 쓰이는 의미가 있는 단어를 다른 의미로 사용하면 안됩니다. 예를들어서 hp 라는 단어를 직각삼각형의 빗변(hypotenuse) 을 표현하기 위해서 사용하는 것은 독자에게 혼란을 줄 수 있습니다.
  • 둘때, 여러 계정을 그룹으로 묶을 경우에는 실제 List가 아니라면, accountList라 명명하지 않고, -s 를 붙여서 accounts로 사용합니다. list 라는 단어는 개발자들에게 있어서 특수한 의미이기 때문이죠. 계정을 담는 컨테이너가 실제 List가 아니라면 그릇된 정보 전달이 될 수 있어요
  • 셋째, 서로 흡사한 이름을 사용하지 않습니다. "XYZControllerForEfficientHandlingOfStrings"라는 이름을 사용하고, 조금 떨어진 모듈에서 "XYZControllerForEfficientStorageOfStrings"라는 이름을 사용할 경우, 사용자는 무엇이 다른지 쉽게 파악하기 힘들 겁니다.
  • 넷째, 유사한 개념은 유사한 표기법을 사용합니다. Xcode에서도 자동 완성 기능을 사용하는데 우리는 대부분 코드를 자세히 살피지 않고 경험을 통해서 객체 네이밍만 보고 역할을 기대하고 사용하죠. 그렇기 때문에 유사한 개념의 경우 유사한 표기법으로 사용자가 쉽게 파악할 수 있게 해야 됩니다.

가장 최근에 진행한 프로젝트에서 List를 사용할 것인지 혹은 -s 를 사용할 것인지에 대해서 팀원들과 토론했던 적이 있는데 반갑네요. 해당 자료형에 대해 정확하게 표현하면 좋겠지만, 여의치 않다면 단/복수를 통해서 표현하는 것도 그릇된 정보를 주지 않는 방법 중 하나인것 같습니다.

3. 의미 있게 구분하라

컴파일러나 인터프리터만 통과하려는 생각으로 코드를 작성하는 것에 대해 경계해야 됩니다. 가끔 컴파일러 통과를 위해 연속된 숫자를 덧붙이거나 불용어를 추가하는 경우가 있는데, 이는 아무런 정보를 제공하지 못합니다.

그리고 data 와 information 또한 ProductInfo, ProductData 와 같이 사용하면 전혀 구분이 되지 못합니다. a, an, the 와 같은 관사 또한 의미가 불분명한 불용어입니다. 의미가 전혀 없습니다. 또 다른 예시를 보면, 변수에 variable 이라는 단어를 무심코 사용하는 것입니다. 의미가 중복되면서 variable 이라는 단어 자체가 주는 의미가 없습니다.

중요한 것은 읽는 사람이 차이를 알 수 있도록 이름을 지어야 한다는 것입니다. 한 걸음 뒤로 물러나서 멀리서 객체 혹은 변수, 메서드를 바라보면 네이밍이 의미 있게 사용되고 있는지 파악할 수 있습니다.

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

영어를 잘 못하는 사람으로써 공감이 되는 규칙 중 하나입니다. 가끔 Open Source 를 볼 때면 낯선 단어들을 마주칠 때가 있는데 발음하기도 힘들고, 팀원들과 해당 객체에 대해 이야기를 나눌 때 방해됩니다.

프로그래밍은 사회 활동이니, 팀원들과 이야기하기 편한 단어를 사용하는 것이 아무래도 유리할 것입니다.

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

문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다는 문제점이 있습니다. 만약 e라는 문자도 변수 이름으로 사용할 경우, 검색을 하면 e를 포함하는 모든 상수, 변수, 클래스... 등등이 검색될 겁니다.

저자의 경우는 간단한 메서드에서 로컬 변수만 한 문자를 사용한다고 합니다. 이름 크기는 범위 크기에 비례해야 된다는 기준 또한 가지고 있네요.

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

독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못한 것입니다. 이는 일반적으로 문제 영역이나 해법 영역에서 사용하지 않는 이름을 선택했기 때문에 생기는 문제입니다.

문자 하나만 사용하는 변수 이름은 문제가 있습니다. 물론 루프에서 반복 횟수를 세는 변수 i, j, k는 괜찮습니다. 단, 루프 범위가 아주 작고 다른 이름과 충돌하지 않을 때만 괜찮다. 루프에서 반복 횟수 변수는 전통적으로 한 글자를 사용하기 때문입니다. 그 외에는 대부분 적절하지 못합니다.

위 처럼 2,3중 루프문을 사용한 경험이 별로 없어서 해당 의견은 잘 모르겠네요. 평소에 고차함수를 사용한다던지 혹은 index 로 네이밍을 결정해서 사용했던 것 같아요. 그리고 왠만하면 루프문을 중복으로 사용하는 방법보다는 메서드를 분리하는 방법을 선택하는 것이 더 좋아보이네요

7. 클래스 & 메서드 이름

클래스

  • 클래스 이름과 객체 이름은 명사나 명사구가 적합하다고 합니다.
  • 대신, Manager, Processor, Data, Info 등과 같은 단어는 피하고, 동사는 사용하지 않습니다.

최근 프로젝트에서도 HTTP 통신을 하는 Data Repository Layer 객체 네이밍을 NetworkManager 로 했었는데, 조금 더 괜찮은 네이밍이 있는지 고민해봐야겠네요.

메서드

  • 메서드 이름은 동사나 동사구가 적합합니다.
  • postPayment, deletePage, save 등이 좋은 예입니다.
  • 접근자, 변경자, 조건자는 javabean 표준에 따라 값 앞에 get, set, is를 붙인다.

Swift API Guidelines 를 보면 메서드 네이밍의 경우 명사, 명사구 또한 추천하고 있습니다. 다만 명사, 명사구로 정의할 경우에는 그에 따른 반환 타입을 명백하게 할 필요가 있을 것 같습니다. 그리고 get, set 과 같은 네이밍은 지양하는 것 같습니다. getter와 setter를 의식한 규칙 같아요.

8. 기발한 이름은 피하라

유머 감각이 비슷한 사람만 이해할 수 있는 네이밍은 피합니다.

실제로 저자가 소개하고 있는 유머가 섞인 네이밍을 보는데... 하나도 이해 못하고 있습니다. 어디가 웃음 포인트인지 전혀 모릅니다. 재미난 이름보다는 명료한 이름으로 모든 문화권 사람들이 이해할 수 있는 네이밍을 지향하는 것이 좋아보입니다.

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

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

예를 들어, 네트워킹 요청을 하는 메서드의 경우, 많이들 request, fetch, retrieve, get 으로 제각각 네이밍을 하는 경우가 많습니다. 이전 프로젝트에서는 해당 내용에 대해서 미리 회의를 했던 기억이 있네요. UIKit에서는 해당 네이밍을 구별해서 사용하고 있어, UIKit의 컨벤션에 따라 사용했었습니다.

10. 말장난을 하지마라

한 단어를 두 가지 목적으로 사용하면 안됩니다. 책에서는 add 라는 단어를 "배열에 요소를 추가하는 메서드"의 네이밍으로 사용하는 것을 비추천하는데, 이는 맥락이 다르기 때문입니다. 실제로 Swift 에서도 같은 타입을 더할 때는 add를 쓰지만, 추가하는 의미로는 insert 와 append 를 사용하고 있습니다.

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

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

12. 문제 영역에서 가져온 이름을 사용해라

적절한 프로그래밍 용어가 없다면 문제 영역에서 이름을 가져와야겠죠. 하지만, 이후에 코드를 보수하는 개발자가 해당 네이밍을 분야 전문가에게 물어서 파악해야만 할 수 있습니다.

해당 부분은 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와서 해결해야겠네요

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

스스로 의미가 분명한 이름이 없지는 않습니다. 하지만 대다수 이름은 그렇지 못하기도 하며, 그래서 클래스, 함수, 이름 공간에 맥락을 부여합니다. 마지막 수단으로 접두어를 붙이기도 하고요.

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

이럴 경우 네이밍 자체를 addressStreet 으로 하거나 혹은 addr 이라는 접두어를 붙일 수도 있겠네요. 하지만, 개인적으로 변수 자체에 접두어를 붙이는 것보다 Struct 혹은 Enum 으로 묶어서 캡슐화해주는 것이 더 좋게 느껴집니다. addrState 보다는 Address.state 가 훨씬 자연스럽게 느껴졌어요.

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

고급 휘발유 충전소 (Gas Station Delluxe) 라는 애플리케이션을 짠다고 가정하겠습니다. 모든 클래스 이름을 접두어 GSD로 시작하겠다는 생각은 전혀 바람직하지 못합니다. IDE에서 자동완성 시 문제가 될 수 있습니다. 모든 클래스에 GSD가 붙어있기 때문에 G를 친다는 것은 모든 클래스를 본다는 의미가 될 수 있습니다.

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

profile
iOS Developer Student

0개의 댓글