brunch

You can make anything
by writing

C.S.Lewis

by 최창규 Apr 13. 2018

카카오헤어샵의 Clean Code

이름 짓는 건 너무 어려워요.

카카오헤어샵 프로젝트는 Claen Code 를 추구했습니다.



의미 있는 이름 짓기

개발자들이 가장 어려워 하는 것이 바로 이름 짓는 것입니다. 패키지명, 클래스명, 함수명, 변수명 등 하루에도 수십 번은 고민에 빠지게 됩니다. 그래서 카카오헤어샵 프로젝트에서는 몇 가지 규칙을 정했습니다.


1. 준말(약어)은 지양

Product를 prod로 쓰지 않고 Reservation을 rsv로 쓰지 않았습니다. 그리고 코드값도 'S', 'R' 형태를 사용하지 않고 'Stopped', 'Ready'와 같이 본말을 그대로 사용했습니다. 처음에는 변수명/함수명 같은 것들이 길어져서 불편했지만 시간이 지날수록 가독성이 높아졌습니다. 특히 RDB의 컬럼과 레코드만 봐도 데이터를 이해하기가 수월했습니다.


2. 데이터와 응용 클래스 분리

getter/setter는 Entity, Value Object, Date Transger Object와 같이 필드만 있고 operation이 없는 데이터 클래스에서만  get, set 함수명을 사용했습니다. 오퍼레이션만 있는 응용 클래스는 findByShopId(), createShopOne(), addItemToList()처럼 다른 형태의 동사를 사용했습니다.


3. 상수는 대문자와 '_'로 사용

MAX_FETCH_SIZE = 10


4. 클래스명은 명사로

CreateProductListService, InsertShopSearchBatch, MainDataSourceInitializer 형태로 작성했습니다. ProductInfo와 같이 역할이 불분명한 이름은 지양했습니다.


5. 데이터의 필드명에 클래스명을 중복으로 사용하지 않음

product.productName (x) -> product.name (o)


함수는 간단하게

1. 함수는 4줄이 넘지 않도록

코드가 길어질 경우 외부 클래스에 위임하고 함수는 가능하면 4줄이 넘지 않으려고 노력했습니다. 물론 현장에서는 4줄이 넘는 경우도 많이 있습니다. 그래도 코드 리뷰 시에 4줄 넘지 않았으면 좋겠다고 피드백을 많이 냈습니다.


2. 일관된 추상화 수준으로

일관된 추상화 수준으로 함수를 분리했습니다.


- 틀린 쓰임) https://gist.github.com/cg4jins/764ca0c1107322e072f87bcea5d789b4

- 맞는 쓰임) https://gist.github.com/cg4jins/aa8bcceb79d3ad75966e96443652249b


3. if문은 return과 함께 쓰고 else는 지양

if 문 안에 복잡한 조건식이 나오지 않게 하였습니다. if 문이 나오면 return 하고 그 아래 코드로 쭉쭉 읽을 수 있도록 하였습니다.

if (상황 1)
    return;

doA();

doB();

위와 같이 주로 작성했습니다.


- 틀린 쓰임) https://gist.github.com/cg4jins/177cb726e05539d0907d926814f37674

- 맞는 쓰임) https://gist.github.com/cg4jins/a7fc6c9528a699521716b007ae8b984d


4. 함수 인자는 1개

함수의 인자는 가능하면 1개의 클래스로 하는 것을 지향했습니다. 여러 개의 인자가 필요할 경우 클래스를 새로 정의해서 사용했습니다. 실제로는 적용하기가 굉장히 어려워서 인자가 많은 경우도 있었습니다. 매번 클래스를 정의하는 것이 번거로운 작업이었기 때문입니다.


5. null을 반환하거나 null을 전달하지 않도록

null을 잘못 사용하는 것은 NullPointerException을 유발하는 안 좋은 습관입니다. 그래서 함수에서 null을 반환하거나 전달하지 않게 했습니다.


주석은 반드시 필요한 곳만

1. 안 쓰는 소스코드는 주석처리 대신 반드시 삭제

우리는 git으로 버전 관리를 하고 있기 때문에 안 쓰는 코드를 주석하지 않았습니다. 나중에 소스코드를 읽는 사람이 혼란을 겪지 않도록 해야 했기 때문입니다.


2. 최대한 signature로 대체

주석 내용을 메쏘드명, 변수명에 최대한 녹일 수 있도록 했습니다.


객체

1. 생성자 대신 정적 팩토리 메쏘드

비즈니스 로직에서 객체를 new 해서 생성하지 않게 했습니다. 반드시 Factory를 만들어 정적 메쏘드로 생성하게 했습니다.


https://gist.github.com/cg4jins/992454b038686de7f87d408d1d61eb9f


생성자를 직접 사용하지 않은 이유는

- 생성자는 이름이 없어서 의도를 알 수 없어서 readablity가 떨어집니다.

- 생성 후 다른 클래스의 인자로 넘기고 그 안에서 다시 set을 하는 것을 방지할 수 있습니다.  


2. 객체 생성을 막을 때는 private 생성자 지정

생성자 대신 정적 팩토리 메쏘드를 사용한 곳은 private 생성자를 지정했습니다. 그러면 외부에서 new로 객체를 생성할 수 없습니다. 해당 객체를 생성하는 것은 반드시 정적 팩토리 메쏘드를 사용해야만 한다는 것을 알려주는 좋은 방법입니다.


정리

프로젝트를 시작하기 전에 개발자들끼리 위 규칙을 정했고 처음에는 잘 지켰습니다. 하지만 시간이 흐르고, 새로운 개발자들도 오게 되면서 점차 규칙은 흐려졌습니다.

특히 "함수 2. 일관된 추상화 수준으로"와 "4. 함수 인자는 1개" 규칙이 잘 지켜지지 않았습니다. 팀원들과 위 규칙에 대하여 다시 한번 얘기를 하지 못한 것이 후회가 됩니다.

그리고 클래스 1개의 코드가 너무 긴 경우도 많았습니다. 다음에는 클래스는 메쏘드 4개 이하로 하자는 규칙을 만들어야겠습니다.


P.S. 프로그래머는 Author라고 합니다. 즉 읽는 독자가 있다는 것입니다. 제 생각에 독자는 내 소스코드를 유지 보수할 다른 개발자입니다. "컴퓨터가 알아듣는 소스코드는 누구나 짤 수 있지만 다른 개발자가 이해할 수 있는 소스코드는 뛰어난 엔지니어만 할 수 있다."는 말이 있습니다. 본 브런치를 읽으시는 분이라면 더 좋은 코드, 읽기 쉬운 코드를 작성하는데 노력하는 분일 거라고 믿습니다. 더불어 후배 개발자들도 이러한 생각을 가질 수 있도록 이끌어 주시길 바랍니다.


http://book.daum.net/detail/book.do?bookid=BOK00022070866YE

http://book.daum.net/detail/book.do?bookid=KOR9788966261161

http://book.daum.net/detail/book.do?bookid=KOR9788979149142

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari