학부생 시절, 프로젝트 과제를 할 때는, 네이밍을 단 한번도 신경써본 적이 없다. 어차피 프로젝트가 끝나면 보지도 않을 코드... 그리고 과제는 결과만 제출하고, 교수님은 코드를 보지도 않기 때문에 내게는 네이밍은 0.1도 중요하지 않은 포인트였다. iOS 교육을 들으면서 진행하면서 정말 느낀 점이 많지만, 나에게 있어서 가독성 좋은 코드를 작성해야 된다는 점은 새롭게 다가왔다. 어떻게 네이밍을 해야되는지도 몰랐고, 작명소마냥 매순간마다 네이밍에 고민을 하는 것이 매우 어색했다.
Swift를 처음 배울 때, Swift API Guidelines 를 보면서 Swift 특유의 네이밍 규칙에 대해서 익혔다. Clean Code에서는 어떤 규칙을 소개하는지 알아보도록 하겠다.
변수(혹은 함수나 클래스)의 존재 이유, 수행기능, 사용방법을 설명하는데 있어서 주석이 필요하다면 네이밍 자체가 그 의도를 분명히 드러내지 못하고 있다는 것입니다. 문제는 코드의 단순성이 아니라 코드의 함축성입니다. 즉, 코드가 아무리 단순한 구조라 하더라도 의미가 불분명한 네이밍이 된다면 그 코드가 무엇을 위한 것인지 이해하기 힘들 수 있기 때문입니다.
Swift API Guidelines 를 보면, iOS 에서는 네이밍이 아무리 길어지더라도 함축어를 사용하지 않으며, 영어 문장처럼 읽히는 것을 선호한다. 메서드의 경우 이런 조건을 맞추기 위해 네이밍 하다보면 네이밍이 너무 길어질 경우가 있는데, 가끔 당황스럽기도 하다... 하지만, 이러한 조건들을 지키지 않을 경우 3일만 지나고 다시볼 경우 "이 에서드가 무슨 일을 하더라..?" 라는 생각이 든다.
여기서 이야기하는 주 내용은 총 4가지 입니다.
hp
라는 단어를 직각삼각형의 빗변(hypotenuse) 을 표현하기 위해서 사용하는 것은 독자에게 혼란을 줄 수 있습니다.-s
를 붙여서 accounts로 사용합니다. list 라는 단어는 개발자들에게 있어서 특수한 의미이기 때문이죠. 계정을 담는 컨테이너가 실제 List가 아니라면 그릇된 정보 전달이 될 수 있어요가장 최근에 진행한 프로젝트에서 List를 사용할 것인지 혹은
-s
를 사용할 것인지에 대해서 팀원들과 토론했던 적이 있는데 반갑네요. 해당 자료형에 대해 정확하게 표현하면 좋겠지만, 여의치 않다면 단/복수를 통해서 표현하는 것도 그릇된 정보를 주지 않는 방법 중 하나인것 같습니다.
컴파일러나 인터프리터만 통과하려는 생각으로 코드를 작성하는 것에 대해 경계해야 됩니다. 가끔 컴파일러 통과를 위해 연속된 숫자를 덧붙이거나 불용어를 추가하는 경우가 있는데, 이는 아무런 정보를 제공하지 못합니다.
그리고 data 와 information 또한 ProductInfo
, ProductData
와 같이 사용하면 전혀 구분이 되지 못합니다. a
, an
, the
와 같은 관사 또한 의미가 불분명한 불용어입니다. 의미가 전혀 없습니다. 또 다른 예시를 보면, 변수에 variable
이라는 단어를 무심코 사용하는 것입니다. 의미가 중복되면서 variable
이라는 단어 자체가 주는 의미가 없습니다.
중요한 것은 읽는 사람이 차이를 알 수 있도록 이름을 지어야 한다는 것입니다. 한 걸음 뒤로 물러나서 멀리서 객체 혹은 변수, 메서드를 바라보면 네이밍이 의미 있게 사용되고 있는지 파악할 수 있습니다.
영어를 잘 못하는 사람으로써 공감이 되는 규칙 중 하나입니다. 가끔 Open Source 를 볼 때면 낯선 단어들을 마주칠 때가 있는데 발음하기도 힘들고, 팀원들과 해당 객체에 대해 이야기를 나눌 때 방해됩니다.
프로그래밍은 사회 활동이니, 팀원들과 이야기하기 편한 단어를 사용하는 것이 아무래도 유리할 것입니다.
문자 하나를 사용하는 이름과 상수는 텍스트 코드에서 쉽게 눈에 띄지 않는다는 문제점이 있습니다. 만약 e라는 문자도 변수 이름으로 사용할 경우, 검색을 하면 e를 포함하는 모든 상수, 변수, 클래스... 등등이 검색될 겁니다.
저자의 경우는 간단한 메서드에서 로컬 변수만 한 문자를 사용한다고 합니다. 이름 크기는 범위 크기에 비례해야 된다는 기준 또한 가지고 있네요.
독자가 코드를 읽으면서 변수 이름을 자신이 아는 이름으로 변환해야 한다면 그 변수 이름은 바람직하지 못한 것입니다. 이는 일반적으로 문제 영역이나 해법 영역에서 사용하지 않는 이름을 선택했기 때문에 생기는 문제입니다.
문자 하나만 사용하는 변수 이름은 문제가 있습니다. 물론 루프에서 반복 횟수를 세는 변수 i, j, k는 괜찮습니다. 단, 루프 범위가 아주 작고 다른 이름과 충돌하지 않을 때만 괜찮다. 루프에서 반복 횟수 변수는 전통적으로 한 글자를 사용하기 때문입니다. 그 외에는 대부분 적절하지 못합니다.
위 처럼 2,3중 루프문을 사용한 경험이 별로 없어서 해당 의견은 잘 모르겠네요. 평소에 고차함수를 사용한다던지 혹은 index 로 네이밍을 결정해서 사용했던 것 같아요. 그리고 왠만하면 루프문을 중복으로 사용하는 방법보다는 메서드를 분리하는 방법을 선택하는 것이 더 좋아보이네요
클래스
최근 프로젝트에서도 HTTP 통신을 하는 Data Repository Layer 객체 네이밍을 NetworkManager 로 했었는데, 조금 더 괜찮은 네이밍이 있는지 고민해봐야겠네요.
메서드
Swift API Guidelines 를 보면 메서드 네이밍의 경우 명사, 명사구 또한 추천하고 있습니다. 다만 명사, 명사구로 정의할 경우에는 그에 따른 반환 타입을 명백하게 할 필요가 있을 것 같습니다. 그리고 get, set 과 같은 네이밍은 지양하는 것 같습니다. getter와 setter를 의식한 규칙 같아요.
유머 감각이 비슷한 사람만 이해할 수 있는 네이밍은 피합니다.
실제로 저자가 소개하고 있는 유머가 섞인 네이밍을 보는데... 하나도 이해 못하고 있습니다. 어디가 웃음 포인트인지 전혀 모릅니다. 재미난 이름보다는 명료한 이름으로 모든 문화권 사람들이 이해할 수 있는 네이밍을 지향하는 것이 좋아보입니다.
추상적인 개념 하나에 단어 하나를 선택해 이를 고수합니다.
예를 들어, 네트워킹 요청을 하는 메서드의 경우, 많이들
request
,fetch
,retrieve
,get
으로 제각각 네이밍을 하는 경우가 많습니다. 이전 프로젝트에서는 해당 내용에 대해서 미리 회의를 했던 기억이 있네요. UIKit에서는 해당 네이밍을 구별해서 사용하고 있어, UIKit의 컨벤션에 따라 사용했었습니다.
한 단어를 두 가지 목적으로 사용하면 안됩니다. 책에서는 add 라는 단어를 "배열에 요소를 추가하는 메서드"의 네이밍으로 사용하는 것을 비추천하는데, 이는 맥락이 다르기 때문입니다. 실제로 Swift 에서도 같은 타입을 더할 때는 add를 쓰지만, 추가하는 의미로는 insert 와 append 를 사용하고 있습니다.
코드를 읽을 사람은 프로그래머이기 때문에 전산 용어, 알고리즘 이름, 패턴 이름, 수학 용어 등을 사용해도 괜찮습니다. 모든 이름을 문제 영역(domain)에서 가져오는 것은 현명하지 못합니다.
적절한 프로그래밍 용어가 없다면 문제 영역에서 이름을 가져와야겠죠. 하지만, 이후에 코드를 보수하는 개발자가 해당 네이밍을 분야 전문가에게 물어서 파악해야만 할 수 있습니다.
해당 부분은 문제 영역 개념과 관련이 깊은 코드라면 문제 영역에서 이름을 가져와서 해결해야겠네요
스스로 의미가 분명한 이름이 없지는 않습니다. 하지만 대다수 이름은 그렇지 못하기도 하며, 그래서 클래스, 함수, 이름 공간에 맥락을 부여합니다. 마지막 수단으로 접두어를 붙이기도 하고요.
firstName, lastName, street, houseNumber, city, state, zipcode라는 변수 객체가 있습니다. 이 경우 변수를 훑어보면 우편을 위한 주소라는 것을 알 수 있습니다. 하지만 어떤 메서드가 이 중 state만 가져와야 하는 경우 그 메서드만 보았을 때 state가 어떤 의미인지 알기 어려울 수 있어요.
이럴 경우 네이밍 자체를 addressStreet 으로 하거나 혹은
addr
이라는 접두어를 붙일 수도 있겠네요. 하지만, 개인적으로 변수 자체에 접두어를 붙이는 것보다 Struct 혹은 Enum 으로 묶어서 캡슐화해주는 것이 더 좋게 느껴집니다. addrState 보다는 Address.state 가 훨씬 자연스럽게 느껴졌어요.
고급 휘발유 충전소 (Gas Station Delluxe) 라는 애플리케이션을 짠다고 가정하겠습니다. 모든 클래스 이름을 접두어 GSD
로 시작하겠다는 생각은 전혀 바람직하지 못합니다. IDE에서 자동완성 시 문제가 될 수 있습니다. 모든 클래스에 GSD가 붙어있기 때문에 G를 친다는 것은 모든 클래스를 본다는 의미가 될 수 있습니다.
일반적으로 짧은 이름이 긴 이름보다 좋습니다. 하지만 그것보다 중요한 것은 의미가 분명해야 된다는 것입니다. 그래서 의미를 충분히 드러낸다면, 불필요한 맥락이 추가될 필요는 없습니다.