본문 바로가기
코딩 아카이브/Golang

TDD와 cleancode로 만들면서 배우면서 Golang backend -2

by SteadyForDeep 2022. 4. 11.
반응형

소스코드는 아래의 깃헙에서 볼 수 있다.

https://github.com/hyun06000/go-backend-with-cleancode-and-tdd

 

GitHub - hyun06000/go-backend-with-cleancode-and-tdd: Go언어를 이용한 API서버, 거기다 이제 cleancode와 TDD를 곁

Go언어를 이용한 API서버, 거기다 이제 cleancode와 TDD를 곁들인. Contribute to hyun06000/go-backend-with-cleancode-and-tdd development by creating an account on GitHub.

github.com

이전 글에서는 TDD에 관한 이야기를 간단하게 했는데

 

Red에서 green이 된 이후에 리팩토링을 거친다고 했다.

이때 cleancode가 필요하다.

 

cleancode는 책 이름인데

어떤 코드가 과연 'clean'하다고 할 수 있는가 에대한 책이다.

코드를 clean하게 적는 것은 팀의 협업 효율을 높이고

개인의 생산성을 증대하며 코드의 재 사용성을 높인다.

이런 코드는 더욱 기민한 프로젝트를 구성하게 하여

애자일 정신에도 근간이 되는 유용한 규칙들이다.

 

이 프로젝트 과정동안 cleancode가 무엇인지는

사실 나도 잘 모르기 때문에 자세히 말하지는 않을 것이고

그때그때 필요한 convention을 작성하고 일괄되게 적용하려 한다.

 

서두가 길어졌다. 본론으로 들어가면

 

만약 단순하게 "Hello, world" 가 아닌

다른 여러 상황에 대해 맞춤 처리를 해야하는 경우

예를 들면 이름이 들어올 경우 이름으로 인사하고

이름이 없을 경우는 지정된 인사를 하고 이런식

 

그럴때 테스트를 어떻게 할지를 가정하여

단순히 테스트만 통과하는 상태가 아닌

테스트를 통과하면서 convention에 맞는 cleancode 상태를 만드는 것이

리팩토링 과정이고 TDD 과정의 끝이라고 할 수 있다.

 

예를들어

Hello라는 함수는

1. 사람 이름이 들어오면 그 이름으로 인사하고

2. 빈 문자열을 받았다면 "Hello, World"라고 인사하는

기능을 가진 함수다.

 

라는 설계가 있으면

1. 을 만족하기 위해서

    - "Chris" 가 입력이면 "Hello, Chris"

    - "David"가 입력이면 "Hello, David"

    - "Paul"이 입력이면 "Hello, Paul" 

이렇게 여러 케이스를 만들어서 검사할 수 있을 것이다.

 

2. 를 만족 하려면

    - "" 이 입력이면 "Hello, World"

라고 검사하면 될 것이다.

 

이 검사를 먼저 작성한다.

예를 들어 이런 검사를 작성했다고 하자.

 

hello.go 에 있는 Hello 함수는 아직 입력을 받을 수 있도록 구현되지 않았으므로

테스트에 통과할 수 없어야 하고 빨간 줄이 쳐져 있는 것을 볼 수 있다.

 

역시 테스트 통과를 못한 이유는 argument가 들어갈 수 없기 때문이다.

그래서 Hello를 이렇게 고쳐서 입력이 들어갈 수 있도록 하면

출력값이 예상과 다르기 때문에 문제가 생길 것이다.

이제 출력값을 맞춰주고 테스트를 통과해 보자.

 

이렇게 하면 테스트에 통과했다.

 

그런데 이대로 코드를 그냥 남들과 공유하자니 코드가 너무 더럽다.

따라서 아래의 원칙을 적용해서 코드를 좀 더 깔끔하고 읽기 좋은 상태로 만들어 보자.

단, 계속해서 테스트는 통과해야 한다.

 

그러므로 언제든지 이 상태로 돌아올 수 있게

여기서 git commit을 한번 하고 개인용 작업 브랜치가 있다면 push도 한번 해 둔다.

나는 여기서 hello-test 브랜치를 만들어서 테스트 통과를 유지하면서

최적의 코드로 고친 후 main에 통합하는 작업을 하겠다.

 

우선 코드를 고치기 위해서는 팀원들과 합의된 원칙이 있어야 하고

혹은 개인적으로 결정한 합리적인 규칙이 있어야하고

그 규칙에 어긋나지 않는 선에서 코드를 수정해야 한다.

물론 이 규칙을 잘 만드는 방법을 cleancode에서 제시한다.

 

나는 이렇게 코드를 고치겠다.

1. 중복되는 것들은 한번만 선언할 것

2. 하나의 함수는 하나의 기능만 수행하고 나머지는 추상화할 것

3. 수행하는 함수의 기능은 함수명에 동사구로 명시할 것

4. 변수의 이름은 기능을 고려하여 명사로 명시할 것

5. 테스트하고자 하는 인터페이스 이름은 수정하지 말것

 

이런 원칙으로 hello.go 코드를 고쳐보자.

 

이렇게 바꾼다.

적은 변화지만 중요한 사실은 코드를 어떤 규칙 아래에 작성했다는 것과

이것에 이전의 테스트를 그대로 통과한다는 것이다.

이로써 기능은 동일하지만 규칙을 아는 사람들 간에 더욱 생산성있는 작업이 가능해 졌다.

 

test 코드도 바꿀게 많이 있다.

반복되는 구간을 제거하고 단순한 기능만 나열함으로

조금더 읽기 쉽고 규격에 맞는 코드가 되었다.

특히 테스트 케이스를 더 추가하거나 늘리기 위해서

불필요한 복붙작업이 없어지고

nameList에 추가하는 단순한 방식으로 바뀜으로

테스트의 정확도도 쉽게 높일 수 있어졌다.

 

물론 테스트 자체에는 아무런 영향을 주지 않는다.

 

이런 방식을 통해서 코드의 기능은 동일하면서도

더 협업하기 쉬워지고 읽기 좋은 코드를 작성하는 것이 가능해 진다.

 

PR로 병합해주면 끝난다.

 

유튜브의 많은 TDD 강연들을 찾아본 결과

좋은 TDD는 완벽히 테스트에 의해 이끌리는 코딩방식이 아니었다.

 

오히려 너무 과도한 테스트의 집착은 업무의 성과를 떨어뜨리거나

불필요한 시간을 너무 많이 사용하도록 한다는 문제가 있다는 것이다.

그러면 어떤 TDD가 진정 도움이 되는 방식인가를 놓고 보면

많은 고수분들이 입을 모아 이야기 하는 것이

어떤 것을 드러내고 어떤 것을 숨길 것인가

 

즉 어떤 부분이 노출되는 인터페이스이고 어떤 부분이 숨겨져야하는 부분인가

 

이것에대한 단초를 잡고 가기위한 테스트가 진정한 TDD의 순기능이라고 한다.

 

cleancode를 읽으면서 막상 적용할 때는 추상화 레벨은 어떤 개념이고

하나의 함수에 하나의 기능만 동작하게 하는 것은 어디까지 숨겨야하고

어디까지 하나의 동작으로 볼 것이고

이런 무수한 의문만 남아있었다.

 

하지만 TDD의 정신과 함께 cleancode를 적용하려고 하니 뭔가 일맥상통하면서

서로를 보완해주는 느낌을 받는다.

다음 포스팅부터는 본격적으로 API서버를 만들어 보자.

반응형

댓글