Post

Clean Code ~Ch.3

2장까지는 저자의 스탠스가 나는 하나의 의견일 뿐이야~ 라는 입장이었다면, 3장부터는 조금 다른 느낌을 받았다. 나의 말이 정답이야! 정도의 느낌이랄까… 그래도 대다수의 것들이 나도 동의하는 것이고 저자가 틀릴 가능성보다 내가 틀릴 가능성이 조금은 더 높다고 생각한다. 무엇보다도 나는 이 책을 읽으며 배우려는 입장이기때문에 최대한 저자의 입장에서 이해하고 받아들여보려 한다. (사실 아직 틀렸다고 생각하지도 않는다.)

Chapter.3


나는 작은 함수가 좋다고 확신한다.

이번 챕터에서 가장 와닿은 문장이다. 나도 꽤나 동의하는 말이다. 함수는 작을수록 관리하기 쉬워진다.

이건 어느정도 경험에 기반한 것이긴 하지만 디버깅할 때도 유용하다. IDE를 이용해서 직접 한 줄씩 디버깅하는 것이 아닌 프로그램을 실행해서 직접 디버깅할 때, 작게 만드는 것이 좋았다. 왜냐하면 함수를 실행할 때, 여러 일을 동시에 처리한다면 무슨 일을 처리할 때 에러가 생기는 지 알 수 없다. 하지만 함수를 작게 만든다면 어느 함수인지 정확히 가리킬 수 있게 된다.

하지만 책에서의 문장처럼 2~3줄까지 나누는 것이 좋은진 잘 모르겠다. 이건 내가 파이썬을 주로 사용해서인지(언어적 한계) 아니면 내가 함수를 잘 못 나눠서 그런 것인지(실력의 부족) 모르겠지만 너무 촘촘하게 나눈 소스코드는 지저분해 보였다. 자료가 남아있진 않지만 하늘 고래를 제작하며 클린 코드를 잠깐 읽었을 때가 있다. 그때 함수 파트를 읽고 깊게 감명받아 정말 내 최대한으로 함수를 나눈 적이 있다. 처음에는 클린 코딩하는 내가 멋있어보였다. 하지만 결과적으로 소스 코드가 한 눈에 들어오지 않아서 오히려 개발이 더더욱 더뎌졌다.

그리고 지금은 기능의 단위로 함수를 나누어서 작성하고 있다. 최대한 한가지 기능에 집중하는 함수로 코딩을 하는 것이 내게는 (아직까지) 잘 맞는 것 같다.

나중에 내가 실제 개발자가 되고 시니어가 됐을 때 생각의 차이가 분명히 있을 것이다. 그떄 한번 더 이 책을 읽고 어떤 생각을 할지가 궁금해지는 문장이었다.


함수 내 모든 문장의 추상화 수준이 동일해야한다.

이 문장도 꽤 내 마음에 들었다. 내 첫 프로그램인 XPA를 개발할 때 경험으로 익힌 것이다.

잠깐 설명을 하자면 XPA는 엑셀에 사진을 넣는 작업을 해주는 프로그램이다. Openpyxl이라는 라이브러리가 있지만 사진의 크기와 화질 등 직접 편집할 일이 있어서 추상화 수준이 차이가 나는 상황이었다. 당시에는 주석을 넣어서 내가 나름 알아볼 수 있도록 작성했지만 4장에도 나오지만 주석이 들어간 코드는 정말 지저분했다. 결국 마음에 들지 않아 (또) 새롭게 제로부터 프로젝트를 다시 진행했었다.

물론 지금의 내가 이것을 완벽하게 지키느냐고 물어본다면 아직도 아니 라고 말해야한다. 시간에 쫓겨 개발을 하다보면 (1장에서 변명하지 마라고 했지만…) 추상화 수준이 여전히 섞여 있는 경우가 대다수다. 하지만 그럼에도 점점 내 코드를 보면 조금씩이라도 정리되고 있는 느낌이 든다.

나도 저자처럼 정말 추상화 단계를 분리하면서도 내가 생각하는 깔끔한 함수를 작성하는 실력이 되면 좋겠다.


코드는 위에서 아래로 이야기처럼 읽혀야 좋다.

이름이 길어도 괜찮다. 이름을 정하느라 시간을 들여도 괜찮다.

함수는 그 언어에서 동사며, 클래스는 명사다.

함수 이름을 지을 때는 두 경우를 분명히 구분해야 한다. (명령과 조회를 분리하라)

위의 4문장은 내 생각에 일맥상통하는 내용인 것 같다. 결국 우리는 코드라는 글을 작성한다.

지금 이 블로그를 쓰면서도 내 나름 최선의 글을 쓰기 위해 최대한 고민한다. 기본적으로 내 생각을 적는 개인 블로그이지만 혹여나 누군가가 이 글을 읽는다면 최대한 쉽게 읽히길 바라기때문이다. 완벽하지 않지만 문장의 시작부터 단어, 중복의 정도, 비문체는 없는지, 최대한 쉽게 읽히는지 계속 고민한다.

코드도 마찬가지다. 내가 생각하는 문제 해결 방법을 개발 언어로 표현한 것이다. 만일 내가 작성한 코드를 그 누구도 읽지 않는다면 크게 고민하지 않아도 된다. 하지만 애석하게도 내 코드는 누군가에 의해 계속 검증되고 사용되며 수정될 것이다. 그럴 때 내 의도가 정확히 드러나기 위해서는 변수, 함수, 클래스의 이름을 짓는 것이 굉장히 중요하다. 그렇게 이름이 잘 지어지고 추상화의 수준이 비슷해졌을 때 비로소 코드는 위에서 아래로 이야기처럼 읽혀진다(고 생각한다).

사실 첫 문장도 포함하고 싶었으나, 첫 문장에는 하고 싶은 얘기가 너무 많아 따로 분리를 했지만 결국 하나의 이야기를 하고싶었다.


코드를 변경할 이유는 여럿이기 때문이다.

코드를 작성할 땐, 분명히 단 하나의 이유이다. 그 코드가 필요하기때문에.

하지만 코드를 변경하는 이유는 두가지의 이유이다. 하나는 마찬가지로 그 코드가 필요하기때문에. 다른 하나는 그 코드가 필요없기때문에.

사실 별 다른 이유가 있어서 이 문장을 뽑은 건 아니다. 그냥 이런 문장이 생각나서 남기고 싶어서 뽑았다. 이상


테스트 관점에서 보면 인수는 더 어렵다.

작년 GDSC 2기를 진행하며 스프링을 많이 사용했다. 스프링(자바)의 가장 큰 장점 중 하나가 테스트 라이브러리가 잘 되어 있다는 점이다. 테스트가 중요한 이유는 정말 수도 없다. 구글에 테스트가 중요한 이유 를 검색하기만 해도 블로그부터 책까지 정말 다양한 자료가 나올 것이다. (사실 검색은 안 해봄) 그정도로 테스트는 중요한데 인수가 미치는 영향은 생각보다 크다고 느꼈다.

우리는 함수를 작성하고 단위 테스트를 진행했다. 단위 테스트는 여러 의미를 포함하지만 함수를 테스트하는 것도 단위 테스트다. 함수를 테스트할 때 중요한 점이 바로 인수다. a, b, c 3개의 인수를 갖는 함수가 있다고 가정해보자.

우리는 이 함수가 제대로 동작하는지 알기 위해서 어떻게 테스트를 작성해야할까?

  1. a, b, c 모두 올바르게 들어간 경우
  2. a, b, c 중 하나 이상이 (의도하지 않게) 빠진 경우
  3. a, b, c 순서가 바뀐 경우
  4. 3개 초과의 인수가 들어간 경우

이 중 골치가 아픈게 2번과 3번인다. 2번은 7개, 3번은 6개 총 13개의 단위 테스트를 진행해야한다. 물론 JUnit 라이브러리에 이를 편하게 진행해주는 어노테이션이 있거나 메소드가 있을 거라 추측한다. 하지만 기본적으로 우리가 해야할 일이 늘어날 것임은 틀림없다.

인수가 하나씩 늘어갈 때마다 우리가 작성해야할 테스트 코드는 기하급수적으로 늘어나며 이 과정에서 필히 실수는 일어날 것이기에 우리는 최대한 인수가 적은 함수를 설계해서 코드를 작성하도록 노력해야 한다고 생각한다.


플래그 인수는 추하다. 정말로 끔찍하다.

원래부터 플래그 인수를 사용하지 않아서 당연한 것 아닌가 했지만 이렇게 표현할 정도로 안 좋다고 하니 다시 한 번 명심하는 마음에 선택했다.

테스트 관점에서 바라보는 인수를 생각해서라도 이는 절대 허용되면 안 될 일이긴 하다.


부수 효과가 시간적인 결합을 초래한다.

이 문장은 함수가 2가지 일을 할 때 불러올 나비효과에 대해 설명한다. 세션을 초기화하는 중요한 코드를 비밀번호 검증 함수에서 호출한다. 따라서 비밀번호를 검증하는 일이 있을 때마다 세션이 초기화되어 유저도 개발자도 불편한 상황을 겪게된다.

구체적인 기억은 아니지만 내 머릿속에 떠오르는 삽질 중 하나가 이 문장의 비슷한 예시가 아닐까 한다. 아마 나뿐만 아니라 99% 개발자들은 이런 실수를 해봤다고 생각한다. 사실 100%라고 하고싶지만 세상은 넓고 고수는 많기에 이런 실수를 하지 않는 사람이 한명쯤은 있으리라…


출력 인수로 사용하라고 설계한 변수가 바로 this이기 때문이다.

와닿은 문장이기보다 객체지향에 대해 한번 다른 방향으로 생각해볼 수 있었던 문장이었다.

조만간 객체지향에 대해 자세히 공부하기로 마음은 먹었지만 개발 공부를 하면서 어느정도 체득(?)한 내 나름의 규칙이 있다. 객체간의 상호작용이라든가 필드와 메소드를 어떻게 활용하면 좋을지라든가 그 외에도 클래스 메소드에서 자기 자신을 사용하는 느낌(?)이라든가.. 자세하게 공부한 적이 없어서 내가 무엇을 생각하는지 언어로 풀어낼 수 없지만 아무튼 무언가가 있다…(?)

근데 이런 조금 애매모호한, 두루뭉실한 뜬구름 같은 생각을 조금 정리해주는 문장이라고 느꼈다. 처음 C언어를 배우고 함수를 배웠을 때, 포인터를 이용해 함수의 결과를 전달해주는 출력 인수를 사용했다. 그리고 클래스를 배웠을 때 느낀 편리함, 혁신은 아마 이 문장의 느낌이었던 것 같다.


오류 처리도 한 가지 작업이다.

나는 예전에 오류 처리를 굉장히 불필요하다고 느꼈다. 지금은 무조건 필수적이고 세상엔 내가 컨트롤 할 수 없는 오류가 많은 것을 알았다. 오류를 잘 다뤄야 사용자가 불편함을 최대한 적게 겪는다. 우리는, 적어도 서비스를 개발하는 사람들이라면 최대한 유저가 불편함을 겪지 않게 하는 것이 좋다.

XPA를 개발할 때, 이를 절실히 느꼈다. 나는 내가 만든 프로그램이 어떻게 동작하는지, 어떤 순서로 사용해야하는지, 무엇을 하면 안 되는지 정확히 알고있다. 하지만 사용자는 다르다. 내가 최대한 자세히 사용 설명서를 작성한다고 해도 읽지 않을 것이고 (나도 그렇고) 읽는다 하더라도 완벽히 이해해서 사용하는지는 미지수다. 이때 내가 생각한 것은 오류를 최대한 생각하고 오류코드를 남겨 나에게 전송하는 것이다. 물론 전송까지는 못 해도 오류코드를 남기는 것까지는 했고 오류가 생겼을 때 오류 코드를 통해 어디서 발생했는지 알 수 있었다. (물론 당연하게도 모든 오류를 통제하지 못 했다…)

그 이후의 프로젝트는 오류를 섬세하게 통제하지 않았지만 적어도 오류가 발생할 것 같다고 생각하는 부분에서는 컨트롤 하려고 노력은 한다.


처음부터 탁 짜내지 않는다. 그게 가능한 사람은 없으리라.

사실 이 말을 듣고싶었다. 머리로는 위의 과정을 잘 알고있다. 하지만 적용을 하는 것은 쉽지 않다.

클린 코드를 얼른 몸에 익혀 최대한 첫 작성에 풀어내고 싶다.

3장 끝!

This post is licensed under CC BY 4.0 by the author.

Trending Tags