Post

Clean Code ~Ch.2

나는 안 좋은 버릇이 몇 개 있다. 그 중 하나가 리팩토링을 다짐하는 것이다. ‘리팩토링이 무슨 문제인가?’ 라고 의문을 던지는 사람도 있을 것이다. 리팩토링 자체는 큰 문제가 되지 않는다. 오히려 훌륭하다고 생각한다. 하지만 천성이 게으른 나는 한 번 실행되는 코드를 작성하면 한동안 그 코드를 쳐다보지 않는다. 꽤 오랜 시간이 흐른 후에 유지보수를 위해 코드를 열면 과거의 내 실력에 한숨을 크게 내쉰 뒤, 처음부터 다시 설계에 들어가서 프로그램을 완전히 새로 작성하게 된다. 물론 그 사이 발전한 실력도 크게 다르지 않다… 😢 (계속 반복되겠지..)

클린 코드를 읽고 클린 코딩을 하는 내가 되길 바라며 책을 집어본다.

Chapter.1


이 책이 작성된 이유를 여러 상황 및 유명한 사람을 예시로 들며 설명하고 있다. 뼈에 구멍나는 기분으로 읽었다.

나중은 결코 돌아오지 않는다.

내가 클린 코드를 읽기로 다짐한 이유를 설명하는 문장이다.

구체적인 계획없이 ‘나중에…’는 정말 지양해야할 말버릇인 것 같다. 리팩토링이 훌륭하다지만 애초에 리팩토링을 할 필요가 없는 코드가 정말 좋은 코드가 아닐까…?


나쁜 코드가 쌓일수록 팀 생산성은 떨어진다.

가장 마음에 와닿은 문구다. 이 문장의 예시로 원대한 재설계의 꿈 을 들고 있다.

마치 내 이야기를 적어둔 느낌이 들어 많이 반성했다. 현재 서비스 중인 하늘 고래 봇을 개발할 때의 내 모습이었다. 초창기에 끊김없는 음악을 듣기위해 간단하게 만든 봇이었다. 점차 수요가 생기자 코드를 조금 다듬어 급하게 서비스를 시작했다.

하지만 정말 단순히 “사용”만을 위해 작성된 코드에 유지보수가 가능할리가 없다. 처음부터 다시 설계를 시작했고 내 기억에만 3번정도 완전히 뒤엎고 제로부터 시작했다.

직접 경험으로 느껴봤기에 제일 아프게 다가온 문장인 것 같다. 나중에 이 책을 다시 읽었을 때, 아픈 문장이 더 적어지면 좋겠다.


관리자의 말을 그대로 따르는 행동은 전문가답지 못하다.

이 문장 자체로는 조금 오해의 소지가 있어 보일 수도 있다. 나는 이 문장이 포함된 단락을 읽으며 저자는 ‘“핑계 대지 마라” 는 메시지를 전하고 싶었던 것 아닐까?’ 라고 생각한다.

코드가 더러워지는 수많은 요소(변명) 중 하나는 ‘원래 설계와 달라져서’ 라고 생각했다. 토이 프로젝트 레벨만 봐도 초기 계획이 틀리는 것은 흔히 있는 일이다. 나도 종종 어쩔 수 없다고 합리화를 했다. 하지만 저자는 “이는 틀렸다”고 말한다. 안 되는 것은 분명 안 된다고 말을 해야한다.

처음에는 이 말이 이해가 가지 않았다. 속된 말로 까라면 까야하는 것이 사회생활인데 어떻게 안 된다고 말을 할까? 하지만 조금 생각을 해보니 완전 거절을 하는 것이 아니라 기획 변경에 따른 늘어날 개발 일정을 얘기하고 이를 합의를 해서 코드를 깔끔하게 유지해야한다는 것으로 정리했다.


깨끗한 코드를 작성하려면 ‘청결’이라는 힘겹게 습득한 감각을 활용 절제와 규율이 필요하다.

이 문장이 있는 단락은 깨끗한 코드에 대한 내용이다. 우리는 개발을 하며 많은 공부를 한다. 각자 처음은 다르겠지만 대부분 시작은 대학교 1학년의 C (혹은 Python) 수업일 것이다. 이때부터 두각을 드러낸 친구도 있고 열심히 공부를 해서 실력을 쌓은 친구도 있을 것이다. 우리가 가지고 있는 ‘코드 감각’은 사람마다 다르겠지만 우리는 이를 열심히 갈고 닦아서 내가 쓰는 코드에 녹여내야할 필요가 있다는 것 같다.


절대적으로 ‘옳다’라는 단정은 금물이다.

이 책은 분명 깔끔한 코드를 작성하는 가이드에 대한 내용이다. 그리고 자세히는 모르지만 꽤나 존경받는 사람인 것 같다. 하지만 그는 우리(저자들)뿐만 아니라 많은 집단과 전문가에게서도 배우라고 한다. 이는 내가 살면서 배워야할 자세라고 생각한다. 늘 겸손하게 살자…


새 코드를 짜면서 우리는 끊임없이 기존 코드를 읽는다.

이건 생각보다 인지하기 힘든 행동인 것 같다. 나는 늘 새로운 기능을 개발하는 것에 몰두하고 있었다. 그래서 그런지 당연히 기존 코드는 제쳐둔다고 자연스럽게 생각했지만 이는 명백히 틀린 생각이었다. 기존의 기능들과 잘 융합되기 위해서는 기존 코드를 새로운 코드보다 더 많이 보는 것이 당연했다.


캠프장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라.

바로 위 문장과 조금 (많이) 이어지는 내용이다. 책에서는 보이스카우트 규칙이라고 적혀있다. 우리는 기존 코드를 자주 본다. 소스 코드 전체를 고치라는 말이 절대 아니다. “딱 하나만”이라도 더 나은 작은 리팩토링을 진행하라는 말인 것 같다.

Chapter.2


이 장은 변수, 함수, 클래스 이름을 지을 때 고려할 점들이 적혀있다.

그릇된 정보를 피하라, 의미 있게 구분하라, 발음하기 쉬운 이름을 사용하라, 검색하기 쉬운 이름을 사용하라, 인코딩을 피하라, 자신의 기억력을 자랑하지 마라, 기발한 이름은 피하라, 한 개념에 한 단어를 사용하라, 말장난을 하지 마라, 해법 영역에서 가져온 이름을 사용하라, 문제 영역에서 가져온 이름을 사용하라, 의미 있는 맥락을 추가하라, 불필요한 맥락을 없애라.

이를 나열하면 끝이 없을 것 같아서 느낀 점 위주로 작성하려고 한다.

더 나은 이름이 떠오르면 개선하기 바란다.

읽을 때, 와닿은 문장을 체크하면서 읽었더니 3번 연속 비슷한 의미의 문장이 나왔다. 이름을 지을 때, 의미를 명확하게 지어야한다. 사실 이 장의 내용이 결국 최대한 함축적이지만 구체적이고 짧지만 충분한 내용을 포함하는 이름을 지어라. 라는 것이다. 코드를 작성하면서 새로 작성하는 코드뿐만 아니라 기존의 코드도 계속 생각하며 다음어야한다는 의미에서 이 문장을 선택했다.


IDE, 컴파일러에 최대한 의지해라.

사실 이건 문장이 아니라 내가 이 장을 읽다가 느낀 점이다. 예전에는 IDE와 컴파일러가 지금처럼 똑똑하지 않았다. 그래서 이름에 타입이나 기타 정보를 포함하는 경우가 있었다. 하지만 지금은 컴파일 이전에 IDE가 타입을 체크하며 미리 개발자에게 알려준다. 그래서 이런 불필요한 작업을 할 필요가 없어졌다.


의미 있는 맥락을 추가하라.

아래는 똑같은 기능을 하는 코드이지만 클래스와 함수를 나눔으로써 맥락을 추가하였고 이는 개발자가 코드 단락만 보고 무슨 기능을 하는지 알 수 있게 해준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 맥락이 불분명한 변수
private void printGuessStatistics(char candidate, int count) {
  String number;
  String verb;
  String pluralModifier;
  if(count === 0) {
    number = "no";
    verb = "are";
    pluralModifier = "s";
  } else if(count === 1) {
    number = "1";
    verb = "is";
    pluralModifier = "";
  } else {
    number = Integer.toString(count);
    verb = "are";
    pluralModifier = "s";
  }
  String guessMessage = String.format("There %s %s %s%s", verb, number, candidate, pluralModifier);
  print(guessMessage);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 맥락이 분명한 변수
public class GuessStatisticsMessage {
  private String number;
  private String verb;
  private String pluralModifier;

  public String make (char candidate, int count) {
    createPluralDependentMessageParts(count);
    return String.format("There %s %s %s%s", verb, number, candidate, pluralModifier);
  }

  private voide createPluralDependentMessageParts(int count) {
    if(count === 0) {
      thereAreNoLetters();
    } else if (count === 1) {
      thereIsOneLetter();
    } else {
      thereAreManyLetters(count)
    }
  }

  private voide thereAreManyLetters(int count) {
    number = Integer.toString(count);
    verb = "are";
    pluralModifier = "s";
  }

  private void thereIsOneLetter() {
    number = "1";
    verb = "is";
    pluralModifier = "";
  }

  private void thereAreNoLetters() {
    number = "no";
    verb = "are";
    pluralModifier = "s";
  }
}
This post is licensed under CC BY 4.0 by the author.

Trending Tags