Function을 작성 하는 규칙에 대해서 좀 더 알아보자
1. 하나의 Function은 상태를 변경(void)하거나, 값을 반환하거나 둘 중 하나여야만 한다.
흔히 하는 것인거 같다. 함수 내에서 객체의 값을 변환 하고 그 값을 리턴하는 식의..
User u = authorizer.login(userName, password);
다음 코드는 두가지 문제점을 가지는데,
1. user를 사용하기 위해서는 항상 login을 해야 한다는 점
2. login을 하면 원치 않아도 user의 정보를 읽어야 한다는 점
결국 User를 생성하면서 동시에 login이라는 상태를 바꾸게 되버리기 때문에 군더더기가 생기게 된다.
해당 코드는 다음과 같이 고칠 수 있다.
authorizer.login(userName, password);
User u = authorizer.getUser(userName);
2. Tell don't Ask
if(user.isLoggedIn())
user.execute(command);
else
authenticator.promptLogin();
해당 코드는 user가 로그인이라면 command를 실행시키고, 그렇지 않다면 로그인을 하게 시킨다. 이러한 if문은 이전에도 살펴보듯이(기억이 안난다면 clean code 책리뷰를 살펴보자.) 조건 처리가 힘들어 지게 만든다. 뿐만 아니라 강의에서는 Query(조건)와 Command(실행)를 함께 사용하지 말라고 한다. 이를 해결하기 위해 try-catch문을 사용해 왔었다.
try {
user.execute(command);
}
catch(User.NotLoggedIn e) {
annuciator.promptLogin();
}
조금 나아 졌다. 하지만 이러한 로직은 사실 User 객체에서만 알면 되는 거지 main이나 상위 프로그램에서 알 필요도 없고(연관성이 짙어진다.) 이는 객체지향적이지 못하다.
user.execute(command, annuciator);
결국 메인 함수에서는 user가 실행되는 것만 알면 되고 로그인 여부는 User객체 본인이 처리하면 캡슐화에도 뛰어나고 객체가 확실히 분리된다.
3. Error handling
public class Stack {
public void push(int element) {
if(size == capacity)
throw new Overflow();
this.elements[size++] = element;
}
public int pop() {
if(size == 0)
throw new Underflow();
return elements[--size];
}
public static Stack make(int capacity) {
if(capacity < 0)
throw new IllegalCapacity();
return new Stack(capacity);
}
public class Overflow extends RuntimeException {
}
public static class IllegalCapacity extends RuntimeException {
}
public class Underflow extends RuntimeException {
}
}
if문을 사용하지 않고 unexpected한 Exception을 상속받은 커스텀 예외를 통해서 문제를 해결한 좋은 코드이다.
4. Special Cases
Stack의 capacity가 0인 경우를 만들려고 한다면 어떤 식으로 작성해야 할까 이는 Stack의 모든 메소드와 같지는 않지만 그 의미를 가진다.
강좌에선 다음과 같이 수정했다.
1. Extract Interface

IDE의 Extract Interface를 이용하여 기존의 클래스를 BoundedStack으로 바꾸고 네개의 메소드를 인터페이스 메소드에 추가시켰다.
public static Stack make(int capacity) {
if(capacity < 0)
throw new IllegalCapacity();
if(capacity == 0) {
return new Stack() {
public Boolean isEmpty() {
return true;
}
public Integer getSize() {
return 0
}
public void push(int element) {
throw new Overflow()
}
public void pop() {
throw new Underflow();
}
return new BoundedStack(capacity);
}
원래 리턴하는 클래스는 BoundedStack으로 리턴하고, 0일 경우에는 익명 클래스로 리턴해주었다.
원한다면 move를 이용하여 익명 클래스를 이름이 있는 클래스로 생성해도 무방하다.
'TDD, CleanCode' 카테고리의 다른 글
클린코더스 강의 리뷰 5. TDD의 기본 예시 (0) | 2019.05.13 |
---|---|
클린코더스 강의 리뷰 4. Forms (0) | 2019.05.11 |
클린코더스 강의 리뷰 3. Function Structure (0) | 2019.05.08 |
클린코더스 강의 리뷰 2. Function part2 (0) | 2019.05.07 |
[TDD]테스트 주도 개발 예제(Money) - KentBeck (0) | 2019.05.06 |