본문 바로가기
Programming/Clean Code

[Clean Code] 의미 있는 이름 (3)

by eungbbang 2021. 12. 7.
반응형

[이 포스팅은 아래 서적을 읽고 작성한 글입니다]

 

http://www.yes24.com/Product/Goods/11681152

 

Clean Code 클린 코드 - YES24

애자일 소프트웨어의 혁명적인 패러다임을 제시하는 책이다. 저자 로버트 마틴은 오브젝트 멘토(Object Mentor)의 동료들과 힘을 모아 ‘개발하며’ 클린 코드를 만드는 최상의 애자일 기법을 정제

www.yes24.com

 


 

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

계속하여 언급하다시피, 이름을 지을 때는 누가봐도 이해 할 수 있도록 작성하여야한다. 개발자 본인이 기억하지 못할 수도 있고, 기억한다고 하더라도 본인만 알아볼 수 있는 코드는 원활한 의사소통을 방해할 수 있으며, 다른 변수와 충돌을 일으킬 수 있는 등 다양한 문제를 야기할 수 있기 때문이다.

 

다만 작은 범위에서의 루프에서 반복 횟수를 세는 변수 i, j, k는 간간히 허용되기도 한다. 루프에서 반복 횟수 변수는 전통적으로 한 글자를 사용하기 때문이다. 대신 루프 범위가 아주 작고, 다른 이름과 충돌하지 않도록 주의해야 한다. 

 

//student는 학생 정보를 담고 있는 배열이라고 가정

for(int i = 0; i< student.Count(); i++){
	cout << student[i].name <<endl;
}

 

 

클래스 이름
  • 클래스 이름과 객체 이름은 명사나 명사구가 적합하다. (Customer, Account 등)
  • 동사는 사용하지 않는다.
  • 추상적인 명사는 사용을 지양한다. (Manager, Processer, Data, Info 등)

 

 

매서드 이름
  • 매서드 이름은 동사나 동사구가 적합하다.
  • 접근자, 변경자, 조건자는 javabean 표준에 따라 앞에 get, set, is를 붙인다.

 

 

기발한 이름은 피하라

앞서 언급한 수많은 이유들과 일맥상통한다. 기발한 이름은, 지을 당시에는 기발했을지 몰라도 시간이 지나면 쉽게 잊혀진다.

구어체나 속어 등으로 이름을 짓는 것도 지양하도록 한다. 특정 문화에서만 사용하는 농담은 피해야하며, 의도를 분명하고 솔직하게 표현해야한다.

 

 

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

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

예를 들어 적립이라는 개념을 넣어 이름을 정의 할 때, 선택 할 수 있는 여러 단어가 있다. save up, get, earn 등 한가지를 선택하여 이름을 지을 수 있는데, 포인트 적립은 saveUpPoint 라고 작명할 수 있을 것이다. 하지만 포인트가 아닌 스탬프 적립 기능을 만들기 위해 getStamp 라고 이름을 짓는다면,  하나의 개념이 완전히 다른 개념처럼 여겨질 수 있다.

이렇게 이름이 다르면 독자는 당연히 클래스와 타입이 다른 완전한 독자적인 클래스라고 생각할 수도 있으며, 적립이라는 다양한 표현을 모두 알고 있어야 쉽게 코드를 이해할 수 있을 것이다.

 

 

말장난을 하지마라

반대로 두가지 개념에 한 단어를 사용하는 것도 조심해야한다.

aussume은 1. 책임을 맡다, 2. 추정하다 의 두가지 의미를 가진 동사이다. 만약  매니저 권한을 얻는 함수와 수익을 예상하는 함수를 동시에 만든다고 가정한다면, aussumeManager 와 aussumeRevenue를 만들 수 있다. 이 두 함수는 전혀 다른 동작을 수행하지만, 유사한 기능으로 오해를 불어일으킬 수 있다.

 

다른 예제로, add라는 메서드는 기존의 값 2개를 이어서 새로운 값으로 만드는 메서드라고 가정해보자.

이때 완전히 새로운 값을 추가하는 메서드 역시 add라는 단어를 사용 할 수도 있다.

하지만 기존 값을 이용하여 또다른 값을 만드는 것과, 완전히 새로운 값을 추가하는 것은 다른 개념이라고 볼 수 있다. 따라서 값을 연결하여 또 다른 값으로 만드는 것이 add였으니, 완전히 새로운 값을 추가하는 것은 insert가 적당하다. 

개인적인 의견이지만, 기존 값들을 연결한다는 개념보다 단순히 새로운 값을 추가하는 데 초점이 맞춰진 메소드라면 두 메소드 모두  add를 사용할 수 있을 것이다. 따라서 개념을 정의 할 때 같은 개념과 다른 개념을 명확히 분류해주는 것이 좋다.

 

 

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

코드를 읽는 사람도 결국 프로그래머이다. 

공통으로 사용할 수 있는 화면을 개발하여 사용할 때, 이 공통 화면을 사용하는 기능들이 다른 화면으로 값을 전달해주는 변수의 이름이 returnValue 라면 누구나 이 함수가 반환 값을 가지고 있는 변수라는 것을 쉽게 알 수 있을 것이다.

'후불'이라는 단어를 관습적으로 Ar이라고 작성하는 팀을 본 적이 있는데, 왜 그렇게 명명하는지는 아무도 알지 못하지만 해당 팀은 그것이 익숙해졌기 때문에 큰 문제 없이 사용하고 있었다. 하지만 해당 팀과 협업을 하던 팀은 후불 기능을 찾기 위해 오랜 시간이 걸리고 말았다. 

해당 팀에서는 후불을 AR이라고 명칭하는 것이 오래된 규칙이었지만, 코드는 언제 누가 읽어도 쉽게 이해할 수 있어야한다는 것을 다시 한 번 기억해야한다. 

 

문제영역에서 가져온 이름을 사용하라

하지만 적절한 프로그래밍 용어가 없다고 문제 영역과 관련이 깊은 코드라면, 문제 영역에서 이름을 가져와야한다. 

마트에서 매출을 쉽게 관리하기 위해 영수증을 관리하는 시스템을 만들기로 했다면, 영수증의 상태를 저장하는 변수로 bill_status를 사용할 수 있을 것이다. bill은 해법 영역에서 사용되는 용어는 아니지만, 마트의 '영수증'을 나타내는 데에는 어려움이 없다. 따라서 이 시스템이 마트에서 사용된다는 것을 아는 사람이라면 영수증을 뜻한다는 것을 추측할 수 있을 것이다.

 

의미 있는 맥락을 추가하라

가능한 이름만 가지고도 어디서 사용되는 것인지 맥락을 이해할 수 있어야하지만, 그렇지 못하다면 마지막 수단으로 접두어를 붙일 수 있다.

firstName, lastName, street, houseNumber, city, state, zipCode라는 변수가 있을 때 전체적으로 보면 주소를 나타내는 데 사용되는 변수들이라는 사실을 쉽게 알 수 있지만, state라는 변수만 사용한다면 해당 변수가 어떤 역할을 하는 지 잘 파악할 수 없을 것이다. 따라서 변수 앞에 addr이라는 접두어를 추가해 addrState, addrFirstName 등으로 사용한다면 좀 더 명확히 파악하는 것이 가능해진다.

접두어 대신 Address라는 클래스를 생성하여 addr.state 라고 사용하는 것도 좋다.

//접두어
string addrFirstName;
string addrLastName;
string addrStreet;
string addrHouseNumber;
string addrCity;
string addrState;
string addrZipCode;

//클래스
calss Address{
    string firstName;
    string lastName;
    string street;
    string houseNumber;
    string city;
    string state;
    string zipCode;
}

이렇게 하면 여러 변수가 섞여 있을 때, 접두어로 변수를 나열하는 것보다 하나의 묶음이라는 것이 좀 더 명확하게 보인다.

 

불필요한 맥락을 없애라

일반적으로는 짧은 이름보다 긴 이름이 좋다. 줄임말을 사용하지 않고 뜻을 명확히 파악할 수 있기 때문이다. 단, 의미가 분명한 경우에 한해서다. 이름에 불필요한 맥락은 추가하지 않도록 해야한다.

계속해서 마트에 필요한 POS 시스템을 개발 할 때, Mart Pos의 줄임말인 MP를 서비스 함수의 접두어로 사용할 수 있을까?가능은 하겠지만 불필요한 맥락을 추가하는 가장 바보같은 짓이다. 마트에서 사용되는 시스템은 마트에서 사용하는 기능들로 이뤄져있을 것이다. 따라서 이 코드를 읽는 사람은 당연히 마트에서 사용되는 기능임을 알 것이고, 앞에 MP를 추가하는 것은 알고 있는 것을 또 한 번 나열하는 것에 불과하다.

 

 

반응형

댓글