Bữa nay tui lôi cuốn Clean Code của uncle Bob ra đọc, sau khi đọc tới chương 3 nói về functions thì tui lôi đống code cũ ra thực hành với hai rule được đề cập là : Small và Do one thing. Và kết quả không thực sự dễ đọc hơn ban đầu. (Có thể do tui code kém).
Tuy nhiên như tiêu đề đã đề cập, việc chia nhỏ một hàm ko hề lớn cũng như không phức tạp (tui nghĩ thế) có thực là giúp ích gì không, đặc biệt nếu hàm này ít có khả năng sẽ phải modify.
Dưới đây là một filter (dispatch request từ client) có code ban đầu như sau:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
ServletContext context = httpRequest.getServletContext();
List<String> availableResources = (List<String>) context.getAttribute("AVAILABLE_RESOURCES_FOR_CLIENT_REQUEST");
Map<String, String> roadMap = (Map<String, String>) context.getAttribute("ROAD_MAP");
try {
//Improve application data security
httpResponse.setHeader("Cache-Control", "no-cache, no-store, private, must-revalidate, max-age=0, no-transform");
//Get resource
String uri = httpRequest.getRequestURI();
String contextPath = context.getContextPath();
String requestedResource = uri.substring(contextPath.length() + 1);
//Logging (not static resources in assets folder)
if (!uri.contains("/assets/")) {
log("DispatchClientRequestFilter "
+ "URI: " + uri + ", "
+ "Resource: " + requestedResource);
}
boolean isAllowed = false;
if (uri.contains("/assets/")) {
isAllowed = true;
}
if (availableResources.contains(requestedResource)) {
isAllowed = true;
}
if (!isAllowed) {
httpResponse.sendError(RESOURCE_NOT_FOUND_CODE);
}
if (isAllowed) {
//Mapping
String url = null;
if (!uri.contains("/assets/")) {
url = roadMap.get(requestedResource);
}
//Dispatch
if (url != null) {
RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(url);
dispatcher.forward(request, response);
}
if (url == null) {
chain.doFilter(request, response);
}
}
} catch (IOException e) {
log("DispatchClientRequestFilter IOEx: " + e.getMessage());
} catch (ServletException e) {
log("DispatchClientRequestFilter ServletEx: " + e.getMessage());
} catch (Exception e) {
log("DispatchClientRequestFilter Unknown: " + e.getMessage());
}
}
Và sau khi chia nhỏ:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
//Improve application data security
httpResponse.setHeader("Cache-Control", "no-cache, no-store,"
+ " private, must-revalidate, max-age=0, no-transform");
String requestedResource = getRequestedResourse(httpRequest);
boolean isAllowed = isAllowedRequest(httpRequest, requestedResource);
if (!isAllowed) {
httpResponse.sendError(RESOURCE_NOT_FOUND_CODE);
}
if (isAllowed) {
String url = mapResource(httpRequest, requestedResource);
if (url != null) {
RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(url);
dispatcher.forward(request, response);
}
if (url == null) {
chain.doFilter(request, response);
}
}
} catch (IOException e) {
log("DispatchClientRequestFilter IOEx: " + e.getMessage());
} catch (ServletException e) {
log("DispatchClientRequestFilter ServletEx: " + e.getMessage());
} catch (Exception e) {
log("DispatchClientRequestFilter Unknown: " + e.getMessage());
}
}
private boolean isAllowedRequest(HttpServletRequest request, String resource)
throws Exception {
if (isRequestForStaticResource(request)) {
return true;
}
if (isAvailableResource(request, resource)) {
return true;
}
return false;
}
private boolean isRequestForStaticResource(HttpServletRequest request)
throws Exception {
String uri = request.getRequestURI();
return uri.contains("/assets/"); //css, img, js, ...
}
private boolean isAvailableResource(HttpServletRequest request, String resource)
throws Exception {
ServletContext context = request.getServletContext();
List<String> availableResources
= (List<String>) context.getAttribute("AVAILABLE_RESOURCES_FOR_CLIENT_REQUEST");
return availableResources.contains(resource);
}
private String getRequestedResourse(HttpServletRequest request) throws Exception {
ServletContext context = request.getServletContext();
String contextPath = context.getContextPath();
String uri = request.getRequestURI();
// ContextPath/resource
String resource = uri.substring(contextPath.length() + 1);
if (!isRequestForStaticResource(request)) {
log("DispatchClientRequestFilter URI: " + uri + ", Resource: " + resource);
}
return resource;
}
private String mapResource(HttpServletRequest request, String resource)
throws Exception {
String url = null;
if (!isRequestForStaticResource(request)) {
ServletContext context = request.getServletContext();
Map<String, String> roadMap
= (Map<String, String>) context.getAttribute("ROAD_MAP");
url = roadMap.get(resource);
}
return url;
}