Lecture-05-1

Download Report

Transcript Lecture-05-1

Chapter 05.
서비스 추상화
Sep. 2014
Youn-Hee Han
http://link.koreatech.ac.kr
5.1 사용자 레벨 관리 기능 추가
2
5.1.0 비즈니스 로직 추가
 UserDao를 사용한 비즈니스 로직 추가
– 사용자의 레벨은 BASIC, SILVER, GOLD 세가지 중 하나이다.
• 사용자가 처음 가입하면 BASIC 레벨
– 이후 다음 활동에 따라서 한 단계씩 업그레이드될 수 있다.
• 가입 후 50회 이상 로그인하면 BASIC에서 SILVER 레벨이 된다.
• SILVER 레벨이면서 50회 이상 추천을 받으면 GOLD 레벨이 된다.
– 사용자 레벨 변경 작업은 일정한 주기를 가지고 일괄적으로 진행
• 주기적 변경 작업 전에는 조건을 충족해도 레벨 변경이 없다.
3
5.1.1 필드 추가
 User 클래스에 사용자 레벨 추가 (비추천 방식)
– static final int 타입의 상수 선언 및 int 타입 level 선언
– 단점, 아래와 같이 범위를 벗어나는 값을 넣을 위험이 있다.
4
5.1.1 필드 추가
 Level 이늄 (Enum) 사용 (추천 방식)
– 자바 5 이상에서 제공
하는 Enum 타입 사용
– Level 이늄은 내부적
으로 int 타입을 가지고
있지만 겉으로는
Level 타입의 객체
– setLevel(1000)과 같은
코드는 에러 발생
5
5.1.1 필드 추가
 User 클래스에 Level 필드 추가
– 추가 필드 정리
 UserDaoTest에 픽스쳐 추가
6
5.1.1 필드 추가
 User 클래스에
생성자 추가
 User 필드 값 검증을
위한 새로운 메소드
– checkSameUser()
7
5.1.1 필드 추가
 checkSameUser() 메소드 사용한 테스트 코드
8
5.1.1 필드 추가
 UserDaoJdbc 수정
Level 이늄 활용법
철자가 틀린 상태에서
테스트 코드 실패
확인 이후 철자 수정
서버에 올리기 전에
이러한 오류에 대해
테스트를 통하여 검출
하는 것은 매우 중요9
5.1.2 사용자 수정 기능 추가
 수정 기능 테스트 추가
 인터페이스에 update()
메소드 추가
 UserDaoJdbc 클래스
에 update 메소드
구현/수정
5.1.2 사용자 수정 기능 추가
 수정 기능 테스트 보완
– 리스트 5-12에 있는 SQL문에서
where를 빼먹고 적지 않았다면
users 테이블의 모든 row에
업데이트가 수행됨
– 오른쪽의 테스트 코드는 그러한
실수를 감지할 수 있는 코드
5.1.3 UserService.upgradeLevels()
 서비스 계층 추가
– 역할: 서비스 제공
• 예 - 유저들의 레벨 업그레이드 서비스
 사용자 관리 비즈니스 로직 코드의 위치
– 서비스 계층: UserService 클래스
– 테스트 클래스 추가: UserServiceTest 클래스 추가
– 새롭게 형성된 의존관계 그림
5.1.3 UserService.upgradeLevels()
 UserService 클래스와 빈 등록
– 일단 클래스 생성 뒤 UserDao 객체를 저장해둘 인스턴스 변수
선언 및 수정자 메소드 추가
– userService 빈 등록
5.1.3 UserService.upgradeLevels()
 UserServiceTest 테스트 클래스
– userService 빈 주입
5.1.3 UserService.upgradeLevels()
 upgradeLevels() 메소드
– 레벨 업그레이드 비즈니스 로직 구현
5.1.3 UserService.upgradeLevels()
 upgradeLevels() 테스트 (1/2)
– 가능한 모든 조건을 모두 확인해야 함
• BASIC 레벨에서 레벨 변화가 없는 경우/있는 경우
• SILVER 레벨에서 레벨 변화가 없는 경우/있는 경우
• GOLD 레벨은 레벨 변화가 없다는 것을 확인
– 위 조건들을 테스트하기 위한 픽스쳐 변경
5.1.3 UserService.upgradeLevels()
 upgradeLevels() 테스트 (2/2)
5.1.4 UserService.add()
 새로운 유저에게 Level.BASIC 레벨 부여
– UsarDaoJdbc의 add() 메소드를 변경하는 방법 (비추천)
• UserDaoJdbc는 주어진 User 객체를 DB에 정보를 넣고 읽는 방법에만
관심이 있어야 함
– User 클래스에서 level 필드의 초기값을 Level.BASIC으로 할당
• 가능한 방법
– UserService에 add() 메소드를 만들고 Level.BASIC 값 할당
• 가장 적당한 방법
5.1.4 UserService.add()
 새로운 유저에게 Level.BASIC 레벨 부여
– 테스트 부터 작성
5.1.5 코드 개선
 이미 작성된 코드에 대해 개선할 점이 없는지를 검토하면
서 스스로에게 다음 질문 필요
– 코드에 중복된 부분은 없는가?
– 코드가 무엇을 하는지 이해하기 불편하지 않은가?
• 가독성 문제
– 코드가 자신이 있어야 할 자리에 있는가?
– 앞으로 변경이 일어난다면 어떤 것이 있을 수 있고, 그 변화에 쉽게
대응할 수 있게 작성되어 있는가?
5.1.5 코드 개선
 UserService의 기존 upgradeLevels() 메소드 코드의 문제점
– if/elseif/else 블럭들이 나열되어 있음
• 1) 현재 유저 레벨 파악
• 2) 업그레이드 조건 파악
• 3) 다음 단계의 레벨 세팅
• 4) 코드상 멀리 떨어진 플래그 변수 설정
• 5) 데이터베이스에 실제 유저 정보 업데이트
– 관련이 있지만 성격이 조금 다른 코드들이 서로 섞여있거나 분리되
어 나타나는 구조
5.1.5 코드 개선
 UserService의 기존 upgradeLevels() 메소드 코드의 문제점
– 레벨 개수 만큼의 if 조건 블록 필요
– 업그레이드 조건이 복잡해지거나 업그레이드시 수행할 작업이
더 많은 일을 요구한다면 코드가 더욱 길어지고 복잡해짐
– 지저분해진 코드 탓에 버그가 숨어들어갈 가능성 높음
– 별로 복잡하지 않아도 변화에 취약하고 다루기 힘든 코드임
5.1.5 코드 개선
 UserService의 upgradeLevels() 메소드 리펙토링
– 자주 변경될 수 있는 구체적 내용과 추상적인 로직의 분리
• canUpdateLevel()과
upgradeLevel() 메소드별로
역할과 책임이 분명함
– canUpgradeLevel() 구현
5.1.5 코드 개선
 UserService내에 새로운 메소드인 upgradeLevel() 추가
– 업그레이드 작업을 따로 분리함으로써 추후에 코딩이 더 필요할 때
어느 곳을 수정해야 할 지가 명확해진다.
– 위 메소드의 단점
• 유저 레벨의 다음 단계가 어떤 것인가를 직접 결정하는 로직과
유저 객체에 level 필드를 변경하려는 로직이 합쳐져 있음
• 레벨이 많아지면 코드가 길어짐
5.1.5 코드 개선
 Level 이늄 코드 수정
– 다음 레벨이 어떤 레벨
인지에 대한 결정은 Level
이늄에 맡김
5.1.5 코드 개선
 upgradeLevel()를 User로 옮김
– 레벨을 업그레이드하는 메소드를 User 객체 스스로 하도록 수정
– 즉, User클래스에 setLevel() 메소드외에 upgradeLevel() 메소드를
구현
• Level.GOLD 레벨이라면 nextLevel이 null
 이런 경우 IllegalStateException을 던져서 호출한 쪽에 예외 상황임을 분
명하게 알린다.
5.1.5 코드 개선
 간단해진 UserService의 upgradeLevel() 메소드
 현재까지 개선한 코드의 특징
– UserService, User, Level이 내부 정보를 다루는 자신의 책임에 충실
한 기능을 갖고 필요하면 관련 작업을 수행해달라고 서로 요청하는
구조
• UserService는 User에게 ‘레벨 업그레이드 작업을 해달라“고 요청
• User는 Level에게 ‘다음 레벨이 무엇인지 알려달라”고 요청
– 코드의 이해가 쉽다.
– 변경이 필요할 때 어느 곳을 수정해야 할 지가 분명하다
5.1.5 코드 개선
 User 테스트
– User 객체 동작에 대한 테스트
5.1.5 코드 개선
 UserServiceTest 개선
– 기존 테스트에서
checkLevel() 메소드를
호출할 때 다음 단계의
레벨이 무엇인지 넣어준
점에 대한 개선
5.1.5 코드 개선
 UserService에 상수 도입
5.1.5 코드 개선
 UserServiceTest에도 상수 도입
[실습 1]
 현재까지 개선한 코드에 다음과 같은 요구 사항이 들어와
서 수정을 해야 한다.
– “BRONZE 레벨을 BASIC과 SILVER 사이에 추가하고 그 다음 레벨로
업그레이드하는 조건은 로그인 횟수 80번이다. “
– 개선 전 코드에서 위 요구사항을 코딩해볼 것
– 개선 후 코드에서 위 요구사항을 코딩해볼 것
[실습 2]
 현재까지의 코드를 레벨 업그레이드 정책을 유연하게 변경
할 수 있도록 개선
– 업그레이드 정책 인터페이스 사용
– UserService에서 사용자 업그레이드 정책을 분리
– UserService에 UserUpgradePolicy를 DI 시켜서 사용
– 최소 두 개의 UserUpgradePolicy의 구체적 클래스 구현