耦合性 (Coupling)
Posted by Bruce Tsai
狀況:在 service / facade / dao / util 等實作中直接呼叫取值
- 案例
- 未考慮流程及生命週期問題,同時對環境或套件的耦合性過高,在多執行緒作業或測試上將發生錯誤
直接透過 spring framework 取得 request 物件
// 在非 http request 生命週期時,將發生錯誤
ServletRequestAttributes sra =
(ServletRequestAttributes)RequestContextHolder.
getRequestAttributes();
HttpServletRequest req = sra.getRequest();
直接透過 struts 取得 request 物件
// 在非 http request 生命週期時,將發生錯誤
HttpServletRequest req = ServletActionContext.getRequest();
正確做法
- 透過替代的界面取得 HttpServletRequest / HttpSession,減少對套件的耦合性
- 由外部傳入 HttpServletRequest / HttpSession 中所需要的值
定義一個替代 HttpServletRequest 的介面:
public interface IHttpServletRequestService
extends IServletRequestService {
/**
* 同{@link HttpServletRequest#getAuthType()}
*
* @return
*/
String authType();
/**
* 同{@link HttpServletRequest#getCookies()}
*
* @return
*/
List<Cookie> cookies();
/**
* 同{@link HttpServletRequest#getDateHeader(String)}
*
* @param name
* @return
*/
long dateHeader(String name);
/**
* 同{@link HttpServletRequest#getHeader(String)}
*
* @param name
* @return
*/
String header(String name);
/**
* 同{@link HttpServletRequest#getHeaders(String)}
*
* @param name
* @return
*/
Enumeration headers(String name);
/**
* 同{@link HttpServletRequest#getHeaderNames()}
*
* @return
*/
Enumeration headerNames();
/**
* 同{@link HttpServletRequest#getIntHeader(String)}
*
* @param name
* @return
*/
int intHeader(String name);
/**
* 同{@link HttpServletRequest#getMethod()}
*
* @return
*/
String method();
/**
* 同{@link HttpServletRequest#getPathInfo()}
*
* @return
*/
String pathInfo();
/**
* 同{@link HttpServletRequest#getPathTranslated()}
*
* @return
*/
String pathTranslated();
/**
* 同{@link HttpServletRequest#getContextPath()}
*
* @return
*/
String contextPath();
/**
* 同{@link HttpServletRequest#getQueryString()}
*
* @return
*/
String queryString();
/**
* 同{@link HttpServletRequest#getRemoteUser()}
*
* @return
*/
String remoteUser();
/**
* 同{@link HttpServletRequest#isUserInRole(String)}
*
* @param role
* @return
*/
boolean userInRole(String role);
/**
* 同{@link HttpServletRequest#getUserPrincipal()}
*
* @return
*/
Principal userPrincipal();
/**
* 同{@link HttpServletRequest#getRequestedSessionId()}
*
* @return
*/
String requestedSessionId();
/**
* 同{@link HttpServletRequest#getRequestURI()}
*
* @return
*/
String requestURI();
/**
* 同{@link HttpServletRequest#getRequestURL()}
*
* @return
*/
StringBuffer requestURL();
/**
* 同{@link HttpServletRequest#getServletPath()}
*
* @return
*/
String servletPath();
/**
* 同{@link HttpServletRequest#getSession(boolean)}
*
* @param create
* @return
*/
HttpSession session(boolean create);
/**
* 同{@link HttpServletRequest#getSession()}
*
* @return
*/
HttpSession session();
/**
* 同{@link HttpServletRequest#isRequestedSessionIdValid()}
*
* @return
*/
boolean requestedSessionIdValid();
/**
* 同{@link HttpServletRequest#isRequestedSessionIdFromCookie()}
*
* @return
*/
boolean requestedSessionIdFromCookie();
/**
* 同{@link HttpServletRequest#isRequestedSessionIdFromURL()}
*
* @return
*/
boolean requestedSessionIdFromURL();
}
定義一個替代 HttpSession 的介面:
public interface IHttpSessionService {
/**
* 同{@link HttpSession#getId()}
*
* @return
*/
String id();
/**
* 同{@link HttpSession#getCreationTime()}
*
* @return
*/
long creationTime();
/**
* 同{@link HttpSession#getAttributeNames()}
*
* @return
*/
Enumeration attributeNames();
/**
* 同{@link HttpSession#getLastAccessedTime()}
*
* @return
*/
long lastAccessedTime();
/**
* 同{@link HttpSession#getMaxInactiveInterval()}
*
* @return
*/
int maxInactiveInterval();
/**
* 同{@link HttpSession#getAttribute(String)}
*
* @param name
* @param <T>
* @return
*/
<T> T attribute(String name);
/**
* 同{@link HttpSession#setAttribute(String, Object)}
*
* @param name
* @param value
*/
void attribute(String name, Object value);
/**
* 同{@link HttpSession#getServletContext()}
*
* @return
*/
ServletContext servletContext();
/**
* 同{@link HttpSession#setMaxInactiveInterval(int)}
*
* @param interval
*/
void maxInactiveInterval(int interval);
/**
* 同{@link HttpSession#removeAttribute(String)}
*
* @param name
*/
void removeAttribute(String name);
/**
* 同{@link HttpSession#invalidate()}
*/
void invalidate();
/**
* 同{@link HttpSession#isNew()}
*
* @return
*/
boolean isNew();
}
透過介面存取資料
IHttpServletRequestService request;
IHttpSessionService session;
@Override
public String execute(int time) {
// 透過介面存取
String key = request.attribute("key");
String account = session.attribute("account");
// more code here
}