Page tree
Skip to end of metadata
Go to start of metadata

 

UserService 는 확장에 열려 있는가?

확장에 열려 있는가?

User 도메인의 데이터베이스 스키마 변경
Dao Persitant 기술의 변경 (sql, ibatis, ORM 기술)

핵심

UserService 가 UserDao 와 강력하게 결합되어 직접적인 코드 수정을 하지 않는 이상 변화에 대응 할 수 없다. (OCP)

 

UserDao 의 생성의 책임을 UserService가 가지고 있다.

이 것은 UserService 를 이용하는 Client 코드는 UserDao의 생성에 개입할수없다.
왜 문제시 되는 것일까?
Client 코드 에서 new 키워드를 사용해 구체적(concrete) Class의 인스턴스를 생성한다고 하면
Client 코드가 생성하는 인스턴스의 클래스의 내부 상세 구현사항에 억매여 있다는 것이다.

확장에 닫혀 있는 UserService
public class UserService {
	private static Logger log = LoggerFactory.getLogger(UserService.class);
	public User join(User user) throws SQLException, ExistedUserException {
		log.debug("User : {}", user);
		UserDao userDao = new UserDao();
		User existedUser = userDao.findByUserId(user.getUserId());
		if (existedUser != null) {
			throw new ExistedUserException(user.getUserId());
		}
		userDao.insert(user);
		return user;
	}
	public User login(String userId, String password) throws SQLException, PasswordMismatchException {
		UserDao userDao = new UserDao();
		User user = userDao.findByUserId(userId);
		if (user == null) {
			throw new PasswordMismatchException();
		}
		
		if (!user.matchPassword(password)) {
			throw new PasswordMismatchException();
		}
		return user;
	}
	public User findByUserId(String userId) throws SQLException {
		UserDao userDao = new UserDao();
		return userDao.findByUserId(userId);
	}
}

과제

UserService 를 확장에는 열려있고 수정에는 닫혀 있는 코드로 리펙토링하라!

확장에 열려있는 다음 코드를 위한 상황필요

UserService 를 사용하는 고객은 우리가 만든 UserDao 에 의존하지 않고 독자적인 UserDao 를 가지고 UserService 를 이용하길 원한다.

 

STEP 0 : UserDao 인터페이스

고객에게 세부적인 구현의 선택권을 제공하기 위해 UserDao 는 인터페이스가 되어야 한다.

UserService 는 UserDao의 인터페이스와 느슨하게 결합 된다.

 

STEP 1 : 무식하게 시작하기

flag 를 클라이언트 코드에서 선택하게 할 수 있음.

UserServiceTest 에서 flag 선택 코드 추가 

UserDao 의 구현체 수가 늘어날 수록 flag 선택문의 코드는 늘어남 

flag 선택문이 산재되어 있음

 

STEP 2 : 중복제거하기

Extract Method 를 통해 중복을 제거 

UserService 에 UserDao 의 생성책임은 여전히 가지고 있음

 

STEP 3 : 책임제거하기 

Factory 에게 책임 위임하기 

여전히 UserDao 의 구현체 수가 늘어날 수록 Factory 의 코드는 수정되어야 함.

UserDao 선택에 대한 flag 값을 클라이언트는 숙지하고 있어야함.

 

STEP 4 : 상속을 통한 해결

Template Method Pattern 과 Factory Method를 사용 

클라이언트 입장에서는 flag 에 대한 선택에서 자유로워짐

UserDao 갯수에 비례하여 UserService 가 만들어짐

UserDao의 생성 책임은 여전히 UserService 가 가짐

 

STEP 5 : 전략의 주입

 

또 다른.. 단위 테스트 관점에서 바라본 UserService

현재의 UserServiceTest 테스트가 단위테스트인가 통합테스트인가?

  • No labels