의도를 명확하게
클린 코드에서는 의도를 명확하게 하는 것을 매우 중요하게 생각한다.
코드에 대해 명확한 의도를 가지지 않고 코딩을 하게된다면 어떻게 될까 아래의 예제를 통해 알아보자
List<LocalDateTime> dateTimes;
위의 변수를 보고 어떤 역활을 하는지 생각해보자. 코드에 아무런 의도가 없어서 추론이 불가능하다. 우리는 결국 이코드를 하나하나 추적해서 알아가는 수 밖에 없다. 하지만 이렇게 이름에 의도를 나타낸다면?
List<LocalDateTime> memberJoinedDateTimes;
아! 멤버(회원)가 가입한 시간을 모은 변수구나! 라고 바로 생각하게 된다. 코드에 의도를 명확하게 표현하는 것은 중요하고 이러한 네이밍 하나로 엄청난 시간을 절약하게 된다.
물론 조건문 반복문에도 의도를 나타내는 것은 매우 중요하다.
List<String> data = bookRepository.findAllOrderBySaleDesc();
List<String> data2 = new ArrayList();
for(int i=0; i<data.length; i++) {
if(i == 0) {
bookstoreRepository.save(data.get(i));
}
data.add(data.get(i));
}
이렇게 하드 코딩하는 경우는 없겠지만 예로 들면 우리는 data, data2 가 무슨 의미인지 전혀 알 수가 없고 무엇을 위한 반복문이고 무엇을 위한 제어문인지 모르겠다. 이제 아래의 코드를 봐보자
List<String> bestSellerBooks = bookRepository.findAllOrderBySaleDesc();
List<String> discardBooks = new ArrayList();
bestSellerBooks.stream().findFirst()
.ifPresent(book -> bookstoreRepository.save(book));
myList.stream().skip(1)
.forEach(book -> data.add(book));
바로 이코드를 한 눈에 봤을 때 제일 잘팔리는 책을 저장하고 그외에는 폐기한다고 이해할 수 있다. 이처럼 의도를 명확히 나타냄으로써 가져올 수 있는 엄청난 위력이다.
그릇된 정보 피하기
우리는 프로그래밍을 하면서 공통적으로 쓰이는 변수와 클래스들이 존재한다. 예를 들어 List, Service, Dto들이 이에 해당한다. 우리는 이처럼 암묵적으로 해당 클래스는 이렇게 이름을 짓고 해당 변수는 이렇게 이름을 짓자. 정하고 네이밍을 한다. 그렇기 때문에 우리는 이런 이름을 피하고 중복되는 개념이 나오지 않도록 조심해야한다.
public class Payment {
String cardNumber;
......
}
public class MobilePayMent {
String cardSequenceNumber
.....
}
다른 클래스지만 너무 흡사해서 같은 역활을 한다고 착각이 생길 수 있다. 그릇된 정보를 피하라는 이유가 이것이다.
의미있게 구분하기
우리는 변수를 구별하면서 흔히 하는 실수가 있다. 바로 비슷한 개념을 뭉치다 보니 각각의 변수를 구분하는 것이 두루뭉실해져서 결국 우리는 나중에 봤을 때 해당 메서드와 변수가 무슨 역활인지 또 찾게 된다. 아래의 코드를 보면 그 이유를 알 수 있다.
getUser();
getUserInfo();
getUsers()
모른는 사람이 해당 메서드를 구분하려면 코드를 다 뒤집어야 할 것이다. 이처럼 우리는 명확하게 구분하여 사용해서 각각의 코드가 무슨 역활인지 명확히 해야한다.
발음하기 쉬운 단어 사용
private int[] actseq;
private int[] activeSequence;
한눈에 봐도 아래 것이 발음하기도 쉽고 이해하기 쉽다. 이처럼 우리는 줄인 말을 써서 코드량을 줄이는 것 보단 때론 전부 작성하여 발음하기 좋게 작성하는 것이 클린코드가 될 수 있다.
검색하기 쉬운 이름을 사용하라
우리가 코드를 검색할 때 어떻게 검색을 하는지 생각해보자. 변수에 담긴 값으로 검색을 할까?
우리는 검색하면서 주로 변수나 클래스를 검색하게 된다. 그러니 우리는 검색하기 쉽도록 코드를 짤 필요가 있다. 아래의 예제를 이해한다면 편할 것이다.
public int dayToYear(int days) {
return days/365;
}
------------------------------------------------------------------------------------
private final int YEAR_DAYS = 365;
public int dayToYear(int days) {
return days/YEAR_DAYS;
}
인코딩을 피하자
인코딩: 어떤 정보를 정해진 규칙(Code) 에 따라 변환하는 것(en-code-ing)을 일컫는다.
인코딩을 피한다는 것이 무엇을 의미하는 걸까? 바로 헝가리식 표기법을 보면 이해할 수 있다. 옛날에는 타입을 기억하지 않고 문자열만을 통해 기억해서 헝가리안 기법이 사용되었지만 현재 지금은 타입체크를 IDE에서 할 수 있을 정도로 발전했기 때문에 굳이 클래스나 변수명에 str, f 등을 써서 해당 변수명이 무슨 타입인지 의미할 필요가 없어진 것이다.
f
|
float
|
d, db
|
double
|
ld
|
long double
|
w
|
word
|
dw
|
double word
|
qw
|
quad word
|
✓ 그래도 인코딩을 해야할 땐 해야한다.
공통적으로 쓰이는 개념이 있는데 해당 개념에 대해 전부 명시하게 되면 우리의 코드는 이해하기 어려운 단어 천지로 변하게 될 것이다.
예시:
인터페이스와 구현 클래스 (UserService, UserServiceImpl)
DTO, VO 등 (signUpRequestDto, UserVo)
기억력 자랑하지 않기
영드에 나오는 셜록을 보면 모든 기억을 저장하고 도서관처럼 기억을 찾아서 쓰는 장면이 있다. 나도 셜록처럼 모든 코드를 머리에 저장하고 도서관처럼 찾아 쓸 수 있으면 좋겠지만 나는 천재도 아니고 기억력도 셜록처럼 좋지 않다.
기억이 좋다하더라도 대규모의 서비스를 혼자 개발하고 유지보수하는 것은 불가능하다고 생각한다. 그렇기에 우리는 혼자 기억할 수 있는 코드가 아닌 남이 이해할 수 있도록 코드를 짜야한다.
클래스와 메서드 이름
클래스에는 명사구와 명사가 적절하다. 메서드는 동사와 동사구가 적절하다. 왜 그래야 한다고 묻는다면 클래스의 역활과 메서드의 역활을 생각하면 바로 이해할 수 있다. 클래스는 객체를 정의하거나 객체의 설계도 처럼 사용되어진다. 다르게 메서드는 객체의 행동을 나타내는데 사용되게 된다. 이처럼 역활에 맞게 정의를 해줘야 이해하기 편해진다.
기발한 상상하지 않기
예를 들어 통신이 느릴 때 처리하는 로직과 통신이 빠를 때 처리를 분리한다고 생각해보자. 느린건 거북이 같으니 Turtle라고 명시하고 코드를 짜고 빠른 통신은 토끼처럼 빠르니까 rabbit이라고 표현해서 구현하면 어떻게 될까?
public class Turtle {
void connect() {}
void close() {}
}
public class Rabbit {
void connect() {}
void close() {}
}
기발하다고 생각할 수 있지만 남이 봤을 때는 왜 거북이가 뭘 연결하고 뭘 종료하는데? 라고 생각할 수 있다. 우리가 하는 기발한 표현을 남이 생각하기에 다르게 생각될 수 있다. 그렇기에 우리는 기발한 표현을 쓰지 않고 사전적으로 정의되어 있는 의미를 사용하는 이유가 이것이다.
의미있는 맥락 사용하기
대화를 하거나 책을 읽을 때 맥락만 읽고 들어도 무엇을 의미하는지 이해할 수 있다. 그렇다면 이런 것을 코드에 적용한다고 하면 어떻게 해야될까? 예를 들어 주소 처리하는 로직을 아래와 같이 나열한다면 파라미터만 보고도 무엇을 의미하는지 알 수 있게 될 것이다.
public void input (String city, Stirng state, String Country) {
}
위에 코드를 봤을 때 무엇을 입력받는 코드라고 생각되는지 생각해보자, 바로 주소를 입력받는 코드라고 맥락을 통해 이해할 수 있다. 이처럼 코드를 입력하는 맥락을 잘 표현하게 된다면 메서드에 명시하지 않더라도 한 눈에 알 수 있게 된다.
이번 챕터 정리
- 남이 이해할 수 있는 코드를 짜는 것이 우선이다.
- 문맥, 맥락, 단어 사용이 명확해야한다.
- 코드는 농담모음집, 시집이 아니다. 사전처럼 우리가 작성한 단어에 대해 명확하게 의미해야한다.
- 우리가 단어로 표현하는 것에 시간을 써서 코드를 작성하고 이로써 아껴지는 시간을 생각해야한다.
- 주관적인 코드가 아닌 객관적인 코드짜기
'도서' 카테고리의 다른 글
클린코드 (주석) (0) | 2022.07.07 |
---|---|
클린코드 (함수) (0) | 2022.07.04 |
클린 코드에 대하여 (0) | 2022.06.21 |
테스트 주도 개발 패턴 (2) (0) | 2022.05.29 |
테스트 주도 개발 패턴 (0) | 2022.05.15 |