TDD, Refactoring

이번 미션에서는 TDD(Test Driven Development ; 테스트 주도 개발)를 집중적으로 경험하고,
점진적으로 확장되는 요구사항에 맞게 Refactoring을 경험해보는 것이 목표였다.

이미 우리는 개발이라는 행위를 하면서도 어떤식으로든 TDD를 얕게라도 경험해왔다. System.out.println(…)
하지만, 이번 미션에서는 TDD의 개념을 정의하고, TDD 사이클을 경험하는 것이 첫번째 목표였고,
각 단계별로 확장되는 요구사항에 맞게 다시 TDD 사이클로 Refactoring 하는 것이 두번째 목표였다.

특히, 객체지향 생활 체조 원칙을 지키면서 개발한다는 것은,
나처럼 경험이 미숙한 주니어 개발자에겐 좋은 설계와 코드를 배울 수 있는 좋은 경험이었다.

TDD를 통해 얻는 이점을 몸소 체험하면서 왜 TDD로 개발해야 하는 지,
리팩토링을 어떻게 해야하는 지 알 수 있는 좋은 경험이었다.

아래에 간단하게 TDD의 이점과 방법, 리팩토링의 접근 방법에 대해 정리해보려고 한다.

TDD

TDD = TFD(Test First Development) + Refactoring으로 한 마디로 말하면,
‘테스트 먼저 개발하고, 이를 통과하는 소스코드를 작성하며 리팩토링으로 전체적인 개발을 진행하는 방법’이다.

그렇다면 테스트를 먼저 작성하면 뭐가 좋을까?

테스트를 먼저 작성하면 좋은 점

  • 작성한 테스트 단위로 디버깅을 할 수 있으므로 디버깅 시간이 현저하게 줄어든다.
  • 테스트 코드 자체가 그 기능에 대한 문서이다.(개발자들끼리)
  • 변화에 유연하게 대처할 수 있다

TDD 사이클

  1. 실패하는 테스트를 구현한다.(이미 이 자체가 어느정도 설계를 반영함)
  2. 테스트가 성공하도록 프로덕션 코드를 구현
  3. 프로덕션 코드와 테스트 코드를 리팩토링

Refactoring

리팩토링이란 정답이 없는 문제를 푸는것과 같다. 하지만, 정답에 가까운 비스무리한 것은 존재한다.
바로 객체지향 생활 체조 원칙을 지켰는가?를 반문하며, 객체지향 생활 체조 원칙을 지키는 코드로 변경하는 것이다.

회고

로또 발급 & 수익률 계산 시스템 개발

로또에 대한 비즈니스 로직은 매우 간단한편이다.

  • 6개의 숫자를 자동 혹은 수동으로 발급해준다.
  • 당첨된 로또 번호와 발급한 로또 번호를 비교하여 등수를 정한다
  • 구매한 금액 대비 당첨된 금액을 수익률로 표현해준다.

이번 미션에서 잘한 점

개인적으론 학습 목표를 정확히 이해하고, 이를 상기하며 개발한 점이 가장 잘 한 것으로 생각된다.
이를 통해, TDD의 장점과 리팩토링 방법에 대해 잘 이해할 수 있었고 앞으로의 개발에도 적극적으로 활용할 것 같다.

기술적으론 Stream API를 적극적으로 사용하였다. 이를 통해, Lambda와 Stream API의 장점을 이해하고,
코드 수를 줄이며 깔끔한 코드를 작성하여, 나중에 보고도 한번에 이해할 수 있는 코드를 작성하였다.

또한 원시값과 문자열 포장, 캐싱, 일급 콜렉션등 다소 생소했던 개념들을 학습하고,
이를 적극적으로 적용하려고 노력했다.

마지막으로 설계에 대한 깊은 고민을 경험했다. 다소 간단한 비즈니스 로직을 가지고 있어도,

  • 객체 설계에 대한 고민
  • 객체 간 결합도를 낮추고 응집도를 높이는 것에 대한 고민
  • 객체의 역할과 책임에 대한 고민과 해당 객체의 기능에 대한 고민

각 단계마다 피드백을 비판적인 시선으로 적극적으로 고민해본 점이
이번 미션에서 가장 잘한 점이 아닌가 싶다.

어려웠던 점

그럼에도 불구하고 부족한 점이 많았다.

외부 코드 or API - 경계에 대한 학습 테스트 부족

학습 테스트라는 것이 이번 미션 1단계에 존재 했음에도 불구하고
어떤 개념인지 이해하지 못하고 넘어갔었다.

미션 중간에 API의 사용법이라던지, JUnit에 사용법에 대한 피드백을 받으면서,
학습 테스트란 개념이 무엇인지 알게 되었다.

내가 이해한 학습 테스트내가 몰랐던 API에 대한 사용 방법을 TDD로 작성해보는 것이다.
앞으로는 학습 테스트를 습관화하여, 사용할 부분에 대한 API 사용법을 간단하게 터득하면서,
이 또한 TDD의 연장으로 생각하며 외부 좋은 API에 대한 지식도 습득할 수 있는 좋은 습관으로 형성해야겠다.

설계에 대한 경험 부족

객체지향언어를 처음 배우는 레벨에서는 추상화에 대하여 실세계를 그대로 투영하는 것이라는
다소 1차원적인 방법으로 배우곤 한다.
나도 이런 방법으로 객체지향언어를 배워서 인지 모르겠지만,
요구사항에서 객체를 뽑아낼 때, 실세계의 시스템을 기반으로 생각하는 버릇이 생긴 것 같다.
하지만, 엄연히 소프트웨어 내에서의 객체와 실세계의 객체는 다르다

예를 들면, 실세계를 반영하여 로또 구매자, 로또 판매자등의 객체를 설계하려고 했지만,
객체지향 생활 체조 원칙에 부합하지 않는 객체들이 자꾸 생겨나게 되었다. 이 부분에서 내가 뭔가 크게 잘못하고 있구나 느꼈다

객체를 설계하는 것에 정답은 당연히 없다. 하지만, 정답에 가까운 무언가는 존재한다고 생각한다.
그래도 나름 설계에 대한 근자감이 있었는데, 내가 설계를 잘 못하는 구나 라고 뼈저리게 깨닳았다.

또한, MVC에 대한 기본적인 이해도도 부족하다고 느꼈다.
이제까지 무조건 Service, Repository, Controller 는 기본적으로 생성하고 봤는데,
Domain에 집중한 개발을 경험하면서 각 Layer의 역할에 대해 이해해 볼 수 있는 경험이었고,
강박적으로 각 Layer를 통해 접근해야 한다는 생각을 고칠 수 있었다.

생각해보자

종합적으로 평가해보면 TDD, Refactoring 미션을 진행하면서
개발자로써 갖춰야 할 좋은 무기를 하나 든 것 같다는 생각이 들었다.

더 나아가서 습관적으로 TDD와 리팩토링(객체지향 생활 체조 원칙)을 형성하여,
이 좋은 무기를 잘 쓸 수 있도록 갈고 닦아야겠다는 생각이 든다…

참고