Undergoing

Controller Component 작성 - 1 본문

개발/TDD

Controller Component 작성 - 1

Halkrine 2012. 6. 11. 11:25

컨트롤러는 다음과 같은 역할을 수행한다.


- 요청을 수락

- 요청에 따른 공통 연산 수행

- 적절한 request handler 선택

- 핸들러가 관련 비즈니스 로직을 수행할 수 있도록 요청 routing

- 오류나 예외 처리를 위한 최상위 핸들러 제공


표현/비즈니스 계층 패턴 등 여러 분야에서 컨트롤러가 광범위하게 사용됨을 인지한다면, 컨트롤러의 기본적인 작성법은 숙지해야 할 것이다.


기본적인 인터페이스(요청하고, 요청 핸들러에 전달하고, 응답 개체를 반환한다)는 다음 소스처럼 구현될 수 있다.


Request.java 

 public interface Request

{

String getName();

}

 Response.java

 public interface Response

{


}

 RequestHandler.java

 public interface RequestHandler

{

Response response(Request request) throws Exception;

}

 Controller.java

 public interface Controller

{

Response processRequest(Request request);

void addHandler(Request request, RequestHandler requestHandler);

}


현재 이 소스는 요청에 대한 고유한 이름을 반환하는 getName 메서드 하나만을 포함한 Request 인터페이스가 정의되어 있다. 이는 필요에 따라 추가 및 수정 가능하다. 그리고 빈 Response 인터페이스가 추가되어 있다. 아직은 마땅히 반환할 Response 객체가 없기 때문에 빈 공간으로 두어도 충분하다. 다음으로는 RequestHandler인데, 이는 Request를 처리하여 Response를 반환한다.  즉 대부분의 궂은 일을 도맡아 처리해줄 목적으로 설계된 helper component이다. process 메서드에 넘겨질 클래스가 어떤 예외를 던질지는 아직 모르기 때문에 모든 예외를 포괄하는 Exception으로 두고 있다.


Controller 인터페이스 내에 있는 Response processRequest(Request request); 는 요청을 처리할 최상위 메서드이다. 요청을 받으면, controller는 이를 적절한 RequiestHandler에 전달한다. 이 메서드는 제어 스택의 마지막에 해당하므로, 실행 과정 중 발생하는 모든 예외를 잡아 스스로 처리해야 한다. 


다음 소스는 상기에 명시된 인터페이스에 따라 간단히 구현된 컨트롤러 클래스이다.


DefaultController.java

package junit.ch3;


import java.util.HashMap; 

import java.util.Map;


public class DefaultController implements Controller

{

private Map requestHandlers = new HashMap(); // 핸들러를 등록할 java.util.HashMap을 선언

protected RequestHandler getHandler(Request request) // 주어진 요청에 적합한 Requesthandler를 반환하는 getHandler 추가

{

if(!this.requestHandlers.containsKey(request.getName()))

{

String message = "요청한 이름의 핸들러를 찾을 수 없습니다." + "[" + request.getName() + "]";

throw new RuntimeException(message); // RequsetHanler를 등록 않고 호출하면 RuntimeException(java.lang.RuntimeException 출력. 프로그래밍의 실수에 의해 발생한 상황

}

return (RequestHandler) this.requestHandlers.get(request.getName()); //메서드 시그너처에 명시되지 않아도 던지고 받아 처리할 수 있는 exception 

}

public Response processRequest(Request request) // 요청을 적절한 핸들러에 전달하고, 그 핸들러의 응답을 반환

{

Response response;

try

{

response = getHandler(request).process(request);

}

catch (Exception exception)

{

response = new ErrorResponse(request, exception);

}

return response;

}

public void addHandler(Request request, RequestHandler requestHandler)

{

if(this.requestHandlers.containsKey(request.getName()))

{

throw new RuntimeException("요청한 핸들러는 이미" + "[" + request.getName() + "]" + "라는 이름으로 등록되어 있습니다." ); // 핸들러 이름의 등록 여부를 확인

}

else

{

this.requestHandlers.put(request.getName(), requestHandler);

}

}


다음은 에러가 발생함을 알리는 클래스이다.


ErrorResponse.java 

package junit.ch3;


public class ErrorResponse implements Response

{

private Request originalRequest;

private Exception originalException;

public ErrorResponse(request request, Exception exception)

{

this.originalRequest = request;

this.originalException = exception;

}

public Request ghetOriginalRequest()

{

return this.originalRequest;

}

public Exception getOriginalException()

{

return this.originalException;

}


이 두 가지는 테스트를 위한 기본적인 뼈대만 만들어 둔 것임을 명시하자. 이제 자동화 테스트를 구현할 차례이다.


* 컴포넌트의 기본 요구사항에 대한 해법


 요구사항  해법
 요청 수락  public.Response processRequest(Request request)
 핸들러 선택  this.requestHandlers.get(request.getName())
 요청 라우팅

 response = getRequestHandler(request).process(request);

 오류 처리

 ErrorResponse 클래스


'개발 > TDD' 카테고리의 다른 글

Test Code 작성 규율  (0) 2012.06.27
Controller Component 작성 - 3  (0) 2012.06.11
Controller Component 작성 - 2  (0) 2012.06.11
JUnit의 개요  (0) 2012.06.07