SlideShare a Scribd company logo
초보
개발자의
TDD
체험기
안녕하세요.
비전공자(경영학전공)
현재 취준생(백수)
김세훈입니다..!
저는 튜터링에서 QA인턴을 하다
개발이 하고싶어 도망쳤스ㄴ다..(농담😋)
개발을 잘 하고 싶어 방황하던 저는
개발을
스승님을 만나.
객체 지향적 설계,
TDD, Refactoring을 통한
클린코드 작성법
좋은 프로그래머가 되기 위한
기본 소양을 배울 수 있었습니다.
스승님께서 강조하신 말씀이 있습니다.
TDD와 의식적인 리팩토링을 반복하면, 설계를
개선하고 '품질 높은 코드'를 만들 수 있다.
저는 두 가지 이유로
저 말씀을 완전히 이해하지 못했습니다.
품질 좋은 코드란?
TDD를 사용하면 무엇이 개선되는지?
품질 좋은 코드란 무엇인가?
우선 저는 코드의 품질에 대해
고민해 본적이 없었습니다.
(애초에 코드에 품질 같은게 있다고 생각도 안 했었습니다..)
“코드는 구현하고 싶은 기능만
작동되게 하면 되는 거 아닌가?”
무지함을 해소하고자 정리해본 좋은 코드의 조건
(클린코드는 아직 다 읽지 못했습니다..ㅜ)
1. 잘 동작한다.
2. 읽기(이해하기) 쉽다.
3. 중복이 없다.
3. 확장이 용이하다.
잘 동작한다.
개발의 목적은 잘 작동하는 소프트웨어를 만드는 것
(기본적으로 작동하지 않으면 무슨 소용인가?)
이해하기 쉽다.
가독성 나쁜 코드는
다른 사람(혹은 본인)이 이해하기 힘들고
파악하는데 시간을 쏟게 한다.
이로 인해 추가적인 커뮤니케이션 비용이 발생한다.
중복이 없다.
코드에 중복되는 내용이 많으면 수정이 힘들다.
때문에 중복된 코드는 분리하여 재사용 가능하게 해야 한다.
‘실용주의 프로그래머’ 저자 데이브 토마스
“중복은 해악이다”
확장이 용이하다.
외부의 요구사항은 변하고 기능은 추가되기 마련.
쉽게 기능을 추가,확장 하기 위해서 코드간 의존성을 낮추어야 한다.
객체지향 5원칙 중 OCP
그렇다면 TDD를 통해 어떻게
코드의 품질을 개선할 수 있을까?
TDD(Test Driven Development)는
1. 실제 동작할 프로덕션 코드를 만들기 전에 테스트 코드를 작성하고,
2. 테스트 케이스를 통과할 만큼의 프로덕션 코드를 만들어
3. 리팩토링하는 과정을 반복하는 개발 방식이다.
TDD Cycle
그래 테스트는 좋은거지..
근데 이거 하면 뭐가 달라지나..?
단위테스트랑
뭐가
다른데..
테스트 만드는거 귀찮..
역시 원리만 알아서는 알 수 없죠. ㅋ
저는 레거시 코드를 TDD를 활용해
리팩토링해보기로 결정했습니다.
프로젝트 주제
두 플레이어가 서로 자신의 카드를 모르고 상대방의 카드만 아는
상태에서, 지난 카드들을 통해 유추해 베팅하는 포커게임
리팩토링 전
Before
자바를 공부하며 만들었던 토이 프로젝트
Legacy Code
AutoGamer
Gamer 클래스를 상속받아, 사용자의 카드와 본인의
카드를 기억하여 자동으로 베팅하는 역할
Dealer
턴을 제어하는 로직을 가진 클래스. 턴의 승패를 판단하고,
게이머에게 칩을 분배한다. 매 턴 마다 Dealer의 상태는
초기화된다.
Gamer
칩과 카드라는 상태를 가지며, 베팅이라는 행위를 할 수
있다. 사용자의 입력을 받아 베팅한다.
IndianPoker
게임을 실행하고 종료조건에 따라 게임의 승패를 판단하는
역할. Dealer와 Gamer 객체에 의존성을 가짐
클래스 구성
실제로 코드를 보기 전까진
“나름 객체지향적으로 설계한 거 같은데?”
라고 생각했습니다.
Gamer 클래스의 betting() 메소드
......?
문제가 많으니 하나씩 살펴봅시다.
한 메소드가
너무 많은 일을 하고 있다.
일단 Gamer라는 도메인의 핵심 로직인
betting()이 직접 입출력, 유효성 검사를 하고 있다.
(기능간 의존성 발생)
게다가 배팅의 유효성 검사 부분에는 동일한
기능을 하는 코드가 반복되어 중복이 발생하고
있다.
많은 분기처리로 코드의
복잡성이 높아짐
모든 경우를 한곳에서 판단 하려해
분기처리가 많아졌고, 이로 인해 코드의 흐름이
복잡해졌다.
본인조차 이해하기 힘든 가독성 낮은 코드가 된
것이다..
가장 큰 문제는 모든 클래스의 모든 메소드가
이런 식이라는 것
일단 &%$같은 코드를 개선하기 전
두 가지 목표를 세웠다.
TDD, Pair Programming 방식으로 개발할 것
콘솔 기반으로 개발하되, 웹 프로젝트로 확장할 것을 고려하여 개발 할 것
TDD, Pair Programming 방식으로 개발할 것
개발 방식에 대한 목표
페어 프로그래밍
한 컴퓨터로 파트너와 함께 번갈아 가며 프로그래밍하는 방식
일정, 의견 조율 같은 커뮤니케이션 비용이 많이 들고
둘이서 한 작업을 같이하기 때문에 효율성은 떨어지지만
파트너의 실시간 리뷰를 통해 익숙하지 않은 TDD 방식을 의식적으로 유지하고,
의견 조율 과정을 통해 좀 더 좋은 코드를 만드는데 도움을 준다.
콘솔 기반으로 개발하되, 웹 프로젝트로 확장할 것을 고려하여 개발 할 것
설계에 대한 목표
사실 TDD 방식 자체는 매우 Simple
가장 중요한 부분은 어떤 설계목표를
가지고 “리팩토링“ 하냐는 것
Wine을 숙성시키는
ripening()이라는 로직을 만들어보자
일단 기본 테스트 케이스
절차적
행위(숙성)와 상태(기간)는 분리되어 있어야 한다.
절차적
Wine 클래스는 age라는 상태를 가진다.
(일종의 구조체 역할)
절차적
ripening() 메소드는 실제 숙성시키는 행위를 담당하고 있다.
메소드는 wine 객체의 현재 age를 가져와 숙성 시킬 기간을 더 해
다시 wine 객체에 값을 저장하는 처리를 순차적으로 실행한다.
함수형
함수를 실행하기 전과 후 매개변수로 쓰이는 값은 변하면 안된다.
(Immutable Object로 만들어야 한다)
함수형
Wine 클래스의 age 필드를 외부에서 직접 접근하지 못하도록
private 접근제어자를 주었고, 외부에서는 getAge() 메소드를 통해서
조회만 할 수 있게 하였다.
함수형
함수형 인터페이스 Ripening을 구현하여 apply()를 실행할 때
인자로 넣은 wine의 age와 숙성기간을 더해 새로운 와인을 생성한다.
(매개변수로 들어간 와인과 숙성된 와인은 전혀 다른 객체)
객체지향적
객체는 상태(기간)와 행위(숙성)를 모두 갖는다.
(객체 자신의 상태는 자신이 직접 변화시켜야 한다.)
객체지향적
Wine 클래스의 age는 외부에서 접근하지 못하고,
ripening() 행위를 통해 변화 시킬 수 있다.
객체지향적
이처럼 어떤 설계 목표를 가지고 리팩토링 하는지에 따라
TDD를 사용하더라도 결과물이 달라집니다.
CONSOLE WEB
Our Goal
To
SpringMVC는 MVC 패턴을 기반으로 설계된 프레임워크
가능하다면 핵심 로직을 그대로 사용하고 싶었기에,
객체지향적으로 설계하고 MVC 패턴을 적용하여 개발하기로 결정
페어프로그래밍
1주일에 4시간씩 2회
콘솔 프로젝트 개발기간
약 2개월
+ 웹 프로젝트는 혼자 개발할 때 1개월 정도 걸림
TDD를 하며 느낀 것
처음부터 큰 문제를 한번에 해결하려 하면
어렵게 다가오고 중간에 포기하고 싶어진다.
큰 문제
1. 큰 문제를 작은 단위로 쪼갤 수 있다.
테스트 케이스를 만들다 보면 큰 문제를 해결하기 위한 작은 문제,
그리고 그 작은 문제를 해결하기 위한 더 작은 문제를 찾게 된다.
이렇게 문제를 쪼개다 보면 자신이 감당할 수 있는 범위의 문제를 알게 된다.
큰 문제
중간
중간
작은
1. 큰 문제를 작은 단위로 쪼갤 수 있다.
작은
작은 작은
1. 큰 문제를 작은 단위로 쪼갤 수 있다.
일단 생각나는 문제들을 적고
해결하기 위한 테스트 케이스를
만들었다.
테스트 케이스는 개발을
시작할 포인트가 되어주었고,
시작점에서 점진적으로 필요한
기능에 대한 테스트 케이스를 만들며
문제의 단위를 쪼갤 수 있었다.
2. 개발의 흐름을 쉽게 파악할 수 있다.
아무리 개발을 좋아해도 365일 24시간 같은 것만 개발할 수 없는 법
개발의 흐름
2. 개발의 흐름을 쉽게 파악할 수 있다.
자릴 비울땐 실패하는 테스트 케이스를 만들어 놓아
어디까지 개발했는지 파악할 수 있었다.
Dealer가 Turn의 승패를 판단하는 테스트
2. 개발의 흐름을 쉽게 파악할 수 있다.
테스트 케이스의 이름은 어떤 것이든 상관없다.
때문에 자신이 파악하기 쉽게 만드는게 좋다.
또 테스트 케이스에 작성된 요소(매개변수, 리턴값)
들이 이 메소드가 어떤 일을 하는 지 알려주는 설명서가 되어준다.
BettingState Test
3. 변경에 자신 있게 대처할 수 있다.
좋은 품질의 코드에는
확장이 용의하다는 조건이 있다.
이 조건은 각 기능간 의존성을 낮추어 해결할 수 있다.
A는 B가 없으면 아무것도 못한다..
3. 변경에 자신 있게 대처할 수 있다.
테스트 케이스를 만들면서 자연스럽게 의존관계에 대한 고민을 하고
테스트를 쉽게할 수 있도록 의존성을 낮추는 설계를 하게 된다.
Turn 클래스와 의존관계가 있는 클래스들
3. 변경에 자신 있게 대처할 수 있다.
고민은 결국 변화하는 부분(Player)와 변화하지 않는 부분(Turn의 행위)를
분리 함으로서 해결할 수 있다.
TurnTest의 일부
3. 변경에 자신 있게 대처할 수 있다.
3. 변경에 자신 있게 대처할 수 있다.
테스트 케이스를 만들어 통과시켜 놓으면,
그 테스트 케이스 자체가 입력타입과 출력타입의 표준이 된다.
Input - output
4. 품질이 보장된 코드를 갖게 된다.
테스트를 통해 이미
검증된 도메인 로직을 갖게 된다.
CONSOLE
WEB
5. 테스트를 통과할 때 마다 느끼는 성취감
테스트 케이스를 모두 통과시키면 나름 짜릿
TDD를 활용해 리팩토링한 코드
After
TDD를 활용해 리팩토링한 코드
Refactored
패키지 구성
controller
적절한 행위를 할 수 있도록 입력과 출력을 분기
처리하는 컨트롤러들이 있는 패키지
domain
게임의 핵심로직을 담당하는 클래스들이 모여있는 패키지
dto
도메인 로직의 처리결과를 뷰에서 보여질 수 있도록
가공한 클래스들이 모여있는 패키지
exception
직접 정의한 예외 클래스들이 모여있는 패키지
view
입력과 출력을 담당하는 클래스들이 모여있는 패키지
vo
직접 지정한 상수형 클래스들이 모여있는 패키지
support
프로그램의 실행에 직접적인 연관은 없지만
도움을 줄 수 있는 클래스들이 모여있는 패키지
리팩토링한 Player 클래스의 betting() 메소드
(정확히는 Player 인터페이스를 구현한 추상클래스 AbstractPlayer의 메소드)
......?
일단 리팩토링 전과 달리
메소드 자체의 길이가 매우 짧아졌다.
또한 입출력 로직을 분리하여 입출력 로직에서 직접 입력 값에 대한
유효성을 검사할 수 있게 되었다. (중복제거)
여기서 실제 베팅이라는 행위는 도메인 객체 중 하나인
BettingState라는 클래스가 담당
BettingState로 처리를 분담시켜
분기문이 없어져 가독성이 좋아졌다.
State Pattern 적용
TDD만을 이용해 얻은 성과일까?
“단위테스트”와 “TDD”는 테스트 케이스를 만드는 순서만 다르지,
프로덕션 코드를 검증하기 위한 테스트 케이스가 있다는 것은 같다.
TDD의 다른 점은 리팩토링이라는 설계 개선의 과정이 있다는 것
결국 중요한 것은 의식적인 리팩토링으로
더 나은 설계가 무엇인지 고민하는 과정
TDD란 프로그래밍 의사결정과 피드백 사이의
간극을 의식하고 이를 제어하는 기술이다.
“Test Driven Development by Example” Kent Beck
감사합니다
Github : https://github.com/Sehun-Kim
Blog : https://sehun-kim.github.io/sehun/blog/

More Related Content

PDF
Tdd with JUnit 1
Junyoung Lee
 
PDF
Tdd live spring camp 2013
beom kyun choi
 
PPTX
TEST?
beom kyun choi
 
PDF
TDD.JUnit.조금더.알기
Wonchang Song
 
PPTX
TDD: Test Driven Development 첫번째 이야기
Ji Heon Kim
 
PDF
200820 NAVER TECH CONCERT 15_Code Review is Horse(코드리뷰는 말이야)(feat.Latte)
NAVER Engineering
 
PDF
TDD with JUnit 2
Junyoung Lee
 
PPTX
C++과 TDD
선협 이
 
Tdd with JUnit 1
Junyoung Lee
 
Tdd live spring camp 2013
beom kyun choi
 
TDD.JUnit.조금더.알기
Wonchang Song
 
TDD: Test Driven Development 첫번째 이야기
Ji Heon Kim
 
200820 NAVER TECH CONCERT 15_Code Review is Horse(코드리뷰는 말이야)(feat.Latte)
NAVER Engineering
 
TDD with JUnit 2
Junyoung Lee
 
C++과 TDD
선협 이
 

What's hot (17)

PPTX
Tdd ver.2
Henry Lee
 
PDF
TDD 발담그기 @ 공감세미나
beom kyun choi
 
PDF
C++ 코드 품질 관리 비법
선협 이
 
PDF
코드 리뷰 시스템 소개
Young-Ho Cha
 
PDF
플리토 코드리뷰 - Code Review in Flitto
Yongjun Kim
 
PPTX
Test driven development
Jinho Song
 
PPTX
깨끗한 코드 (클린 코드, Clean Code)
Jay Park
 
PDF
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
SangIn Choung
 
PPTX
TDD
Henry Lee
 
PDF
TDD&Refactoring Day 02: TDD
Suwon Chae
 
PPT
간단하게 알아보는 좋은 코드 서영훈
Seo YoungHoon
 
PPTX
E1_Deview nhn애자일개발 tdd_질문답
NAVER D2
 
PPTX
S66 goos-w7
한재 제
 
PPTX
사내 TDD 도입을 위한 설명 문서
Kim kyoung-song
 
PPT
목 오브젝트(Mock Object)의 이해
Yong Hoon Kim
 
PPTX
테스트 자동화와 TDD(테스트 주도 개발방법론)
KH Park (박경훈)
 
PDF
파이썬 TDD 101
정주 김
 
Tdd ver.2
Henry Lee
 
TDD 발담그기 @ 공감세미나
beom kyun choi
 
C++ 코드 품질 관리 비법
선협 이
 
코드 리뷰 시스템 소개
Young-Ho Cha
 
플리토 코드리뷰 - Code Review in Flitto
Yongjun Kim
 
Test driven development
Jinho Song
 
깨끗한 코드 (클린 코드, Clean Code)
Jay Park
 
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
SangIn Choung
 
TDD&Refactoring Day 02: TDD
Suwon Chae
 
간단하게 알아보는 좋은 코드 서영훈
Seo YoungHoon
 
E1_Deview nhn애자일개발 tdd_질문답
NAVER D2
 
S66 goos-w7
한재 제
 
사내 TDD 도입을 위한 설명 문서
Kim kyoung-song
 
목 오브젝트(Mock Object)의 이해
Yong Hoon Kim
 
테스트 자동화와 TDD(테스트 주도 개발방법론)
KH Park (박경훈)
 
파이썬 TDD 101
정주 김
 
Ad

Similar to 초보개발자의 TDD 체험기 (20)

PDF
엔지니어의 학습, 그리고 테스트 코드
Mijeong Park
 
PPTX
Test Driven Development (TDD) basic
Curt Park
 
PPT
Responding to change
기룡 남
 
PDF
TDD - 테스트 주도로 개발하기
현승 배
 
PDF
Devon 2011-b-5 효과적인 레거시 코드 다루기
Daum DNA
 
PPTX
TDD - Test Driven Development
ChangHyeon Bae
 
PDF
Growing object oriented software guided by test
라한사 아
 
PDF
아꿈사.C++ api 디자인.20140315 a
Choonghyun Yang
 
PPTX
TDD or TFD
young-il Park
 
PDF
개발이 테스트를 만났을 때(Shift left testing)
SangIn Choung
 
PDF
테스트 기발 개발, TBD(Test based developement)
도형 임
 
PDF
Effective Unit Testing
Yeon Soo Kim
 
PDF
TDD&Refactoring Day 03: TDD
Suwon Chae
 
PPTX
프로젝트 Xxx에 적용하고 싶은 개발방법
도형 임
 
PPT
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Ryan Park
 
PDF
Testing & refactoring
Lim Hosung
 
PPTX
Violentica Path System with TDD
cwZo
 
PPTX
리펙토링 4장 테스트만들기
Heo Seungwook
 
PDF
Istqb 2-소프트웨어수명주기와테스팅-2015
Jongwon Lee
 
PPTX
자동화된 Test Case의 효과
도형 임
 
엔지니어의 학습, 그리고 테스트 코드
Mijeong Park
 
Test Driven Development (TDD) basic
Curt Park
 
Responding to change
기룡 남
 
TDD - 테스트 주도로 개발하기
현승 배
 
Devon 2011-b-5 효과적인 레거시 코드 다루기
Daum DNA
 
TDD - Test Driven Development
ChangHyeon Bae
 
Growing object oriented software guided by test
라한사 아
 
아꿈사.C++ api 디자인.20140315 a
Choonghyun Yang
 
TDD or TFD
young-il Park
 
개발이 테스트를 만났을 때(Shift left testing)
SangIn Choung
 
테스트 기발 개발, TBD(Test based developement)
도형 임
 
Effective Unit Testing
Yeon Soo Kim
 
TDD&Refactoring Day 03: TDD
Suwon Chae
 
프로젝트 Xxx에 적용하고 싶은 개발방법
도형 임
 
Agd Test Driven Development For Games What, Why, And How)(Game Connect 2006...
Ryan Park
 
Testing & refactoring
Lim Hosung
 
Violentica Path System with TDD
cwZo
 
리펙토링 4장 테스트만들기
Heo Seungwook
 
Istqb 2-소프트웨어수명주기와테스팅-2015
Jongwon Lee
 
자동화된 Test Case의 효과
도형 임
 
Ad

초보개발자의 TDD 체험기