Skip to main content

김주엽

1. 📌 핵심 개념 정리

✅ 요약하기

  1. 적절한 행 길이를 유지하라
    소스 코드의 세로 길이는 얼마나 길어야 적당한가?
    • Junit, FitNesse, testNG, Time and Money, JDepend, Tomcat 등 프로젝트 조사 결과 평균 파일 크기는 약 65줄이다. 프로젝트에서 가장 긴 파일은 400줄이고 짧은 파일은 6줄이다. 여기서 JUnit, FitNesse, Time and Money는 상대적으로 파일 크기가 200줄 정도로 작았다.
    • 코드 길이 200줄 정도로도 커다란 시스템 구축이 가능하다.
    • 코드 길이에 대해서 엄격한 규칙이 있는 것은 아니지만 이해하기 쉽도록 작은 길이를 유지하자.

  1. 개념은 빈 행으로 분리하라
    모든 코드는 왼쪽에서 오른쪽으로 위에서 아래로 읽힌다.
    각 행은 수식이나 절을 나타내며 행 묶음은 완전한 개념 하나를 표현하므로 개념 사이에는 빈 행을 넣어야 한다.

    • 개선 전

      @WebServlet("/api/youtube/*")
      public class YoutubeController extends Controller {
          private final YoutubeService youtubeService;
          public YoutubeController() {
              ServletContext servletContext = CustomServletContextListener.getServletContext();
              youtubeService = (YoutubeService) servletContext.getAttribute("YoutubeService");
          }
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
              if (pathInfo != null) {
                  routeGetMethod(req, resp);
                  return;
              }
              List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
              responseYoutubeListAsJson(resp, gameItemList);
          }
          private void responseYoutubeListAsJson(HttpServletResponse resp, List<GameItem> gameItemList) throws IOException {
              resp.setContentType("application/json");
              resp.setCharacterEncoding("UTF-8");
              resp.getWriter().write(JsonUtil.toJson(gameItemList));
          }
          private void routeGetMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
              String[] pathParts = pathInfo.split("/");
              if (pathParts.length < 3) { // 올바른 요청이 아닐 경우
                  resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid API request format.");
                  return;
              }
              String type = pathParts[1];
              String value = pathParts[2];
              switch (type) {
                  case "title" -> requestTitleAPI(resp, value);
                  case "theme" -> requestThemeAPI(resp, value);
                  default -> resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid endpoint.");
              }
          }
      }
      

      개선 전 코드의 경우 각 행을 분리하지 않아 코드를 읽고 해석하기 어렵다.

    • 개선 후

      @WebServlet("/api/youtube/*")
      public class YoutubeController extends Controller {
          private final YoutubeService youtubeService;
          public YoutubeController() {
              ServletContext servletContext = CustomServletContextListener.getServletContext();
              youtubeService = (YoutubeService) servletContext.getAttribute("YoutubeService");
          }
      
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
      
              if (pathInfo != null) {
                  routeGetMethod(req, resp);
                  return;
              }
      
              List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
              responseYoutubeListAsJson(resp, gameItemList);
          }
      
          private void responseYoutubeListAsJson(HttpServletResponse resp, List<GameItem> gameItemList) throws IOException {
              resp.setContentType("application/json");
              resp.setCharacterEncoding("UTF-8");
              resp.getWriter().write(JsonUtil.toJson(gameItemList));
          }
      
          private void routeGetMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
              String[] pathParts = pathInfo.split("/");
      
              if (pathParts.length < 3) { // 올바른 요청이 아닐 경우
                  resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid API request format.");
                  return;
              }
      
              String type = pathParts[1];
              String value = pathParts[2];
      
              switch (type) {
                  case "title" -> requestTitleAPI(resp, value);
                  case "theme" -> requestThemeAPI(resp, value);
                  default -> resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid endpoint.");
              }
          }
      }
      

      행 분리 후 메서드에 대한 구분을 이해하기 쉬워진 것을 볼 수 있다.


  1. 변수 및 함수 선언
    • 지역 변수는 사용하는 위치에 최대한 가까이 선언한다.
    • 멤버 변수는 클래스 맨 처음에 선언하고 변수 간에 세로로 거리를 두지 않는다.
    • 종속 함수는 호출하는 함수를 호출되는 함수보다 먼저 배치하고 가까이 배치한다.
      • 종속 함수: 함수에서 다른 함수를 호출할 때 종속 관계에 놓여져 있다고 볼 수 있다.
    • 가장 중요한 개념을 가장 먼저 함수로 작성한다.

  1. 들여쓰기
    블록 단위로 이뤄진 계층을 표현하기 위해서 들여쓰기를 사용한다.
    때로는 간단한 if문, 짧은 while문, 짧은 함수에서 들여쓰기를 무시하는데 이는 피하도록 하자.

    • 개선 전

      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String pathInfo = req.getPathInfo();
      
      if (pathInfo != null) {routeGetMethod(req, resp); return;}
      
      List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
      responseYoutubeListAsJson(resp, gameItemList);}
      
    • 개선 후

      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          String pathInfo = req.getPathInfo();
      
          if (pathInfo != null) {
              routeGetMethod(req, resp);
              return;
          }
      
          List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
          responseYoutubeListAsJson(resp, gameItemList);
      }
      

2. 🤔 이해가 어려운 부분

🔍 질문하기

책을 읽으며 이해하기 어려웠던 개념이나 명확하지 않았던 내용을 정리합니다.

  1. 종속 함수
    • 어려웠던 부분
      처음 봤을 때 단어가 생소한 단어여서 이해하는데 어려움이 있었다.
    • 이해한 점
      • 종속 함수는 다른 함수에 직접적으로 의존하여 독립적으로 동작할 수 없는 함수를 의미한다.
      • 함수 간의 종속성이 강하면 코드의 유지보수성이 낮아지고 재사용성과 테스트가 어려워진다.

3. 📚 참고 사항

📢 논의하기

관련된 자료가 있다면 공유하고, 더 깊이 논의하고 싶은 아이디어나 의견을 정리합니다.

  1. 관련 자료 공유
    • 추가 자료
      [우아한 테크 세미나 - 리팩터링 정리# 1. 📌 핵심 개념 정리

✅ 요약하기

  1. 적절한 행 길이를 유지하라
    소스 코드의 세로 길이는 얼마나 길어야 적당한가?
    • Junit, FitNesse, testNG, Time and Money, JDepend, Tomcat 등 프로젝트 조사 결과 평균 파일 크기는 약 65줄이다. 프로젝트에서 가장 긴 파일은 400줄이고 짧은 파일은 6줄이다. 여기서 JUnit, FitNesse, Time and Money는 상대적으로 파일 크기가 200줄 정도로 작았다.
    • 코드 길이 200줄 정도로도 커다란 시스템 구축이 가능하다.
    • 코드 길이에 대해서 엄격한 규칙이 있는 것은 아니지만 이해하기 쉽도록 작은 길이를 유지하자.

  1. 개념은 빈 행으로 분리하라
    모든 코드는 왼쪽에서 오른쪽으로 위에서 아래로 읽힌다.
    각 행은 수식이나 절을 나타내며 행 묶음은 완전한 개념 하나를 표현하므로 개념 사이에는 빈 행을 넣어야 한다.

    • 개선 전

      @WebServlet("/api/youtube/*")
      public class YoutubeController extends Controller {
          private final YoutubeService youtubeService;
          public YoutubeController() {
              ServletContext servletContext = CustomServletContextListener.getServletContext();
              youtubeService = (YoutubeService) servletContext.getAttribute("YoutubeService");
          }
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
              if (pathInfo != null) {
                  routeGetMethod(req, resp);
                  return;
              }
              List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
              responseYoutubeListAsJson(resp, gameItemList);
          }
          private void responseYoutubeListAsJson(HttpServletResponse resp, List<GameItem> gameItemList) throws IOException {
              resp.setContentType("application/json");
              resp.setCharacterEncoding("UTF-8");
              resp.getWriter().write(JsonUtil.toJson(gameItemList));
          }
          private void routeGetMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
              String[] pathParts = pathInfo.split("/");
              if (pathParts.length < 3) { // 올바른 요청이 아닐 경우
                  resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid API request format.");
                  return;
              }
              String type = pathParts[1];
              String value = pathParts[2];
              switch (type) {
                  case "title" -> requestTitleAPI(resp, value);
                  case "theme" -> requestThemeAPI(resp, value);
                  default -> resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid endpoint.");
              }
          }
      }
      

      개선 전 코드의 경우 각 행을 분리하지 않아 코드를 읽고 해석하기 어렵다.

    • 개선 후

      @WebServlet("/api/youtube/*")
      public class YoutubeController extends Controller {
          private final YoutubeService youtubeService;
          public YoutubeController() {
              ServletContext servletContext = CustomServletContextListener.getServletContext();
              youtubeService = (YoutubeService) servletContext.getAttribute("YoutubeService");
          }
      
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
      
              if (pathInfo != null) {
                  routeGetMethod(req, resp);
                  return;
              }
      
              List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
              responseYoutubeListAsJson(resp, gameItemList);
          }
      
          private void responseYoutubeListAsJson(HttpServletResponse resp, List<GameItem> gameItemList) throws IOException {
              resp.setContentType("application/json");
              resp.setCharacterEncoding("UTF-8");
              resp.getWriter().write(JsonUtil.toJson(gameItemList));
          }
      
          private void routeGetMethod(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              String pathInfo = req.getPathInfo();
              String[] pathParts = pathInfo.split("/");
      
              if (pathParts.length < 3) { // 올바른 요청이 아닐 경우
                  resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid API request format.");
                  return;
              }
      
              String type = pathParts[1];
              String value = pathParts[2];
      
              switch (type) {
                  case "title" -> requestTitleAPI(resp, value);
                  case "theme" -> requestThemeAPI(resp, value);
                  default -> resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid endpoint.");
              }
          }
      }
      

      행 분리 후 메서드에 대한 구분을 이해하기 쉬워진 것을 볼 수 있다.


  1. 변수 및 함수 선언
    • 지역 변수는 사용하는 위치에 최대한 가까이 선언한다.
    • 멤버 변수는 클래스 맨 처음에 선언하고 변수 간에 세로로 거리를 두지 않는다.
    • 종속 함수는 호출하는 함수를 호출되는 함수보다 먼저 배치하고 가까이 배치한다.
      • 종속 함수: 함수에서 다른 함수를 호출할 때 종속 관계에 놓여져 있다고 볼 수 있다.
    • 가장 중요한 개념을 가장 먼저 함수로 작성한다.

  1. 들여쓰기
    블록 단위로 이뤄진 계층을 표현하기 위해서 들여쓰기를 사용한다.
    때로는 간단한 if문, 짧은 while문, 짧은 함수에서 들여쓰기를 무시하는데 이는 피하도록 하자.

    • 개선 전

      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String pathInfo = req.getPathInfo();
      
      if (pathInfo != null) {routeGetMethod(req, resp); return;}
      
      List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
      responseYoutubeListAsJson(resp, gameItemList);}
      
    • 개선 후

      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          String pathInfo = req.getPathInfo();
      
          if (pathInfo != null) {
              routeGetMethod(req, resp);
              return;
          }
      
          List<GameItem> gameItemList = youtubeService.readAllYoutubeItem();
          responseYoutubeListAsJson(resp, gameItemList);
      }
      

2. 🤔 이해가 어려운 부분

🔍 질문하기

책을 읽으며 이해하기 어려웠던 개념이나 명확하지 않았던 내용을 정리합니다.

  1. 종속 함수
    • 어려웠던 부분
      처음 봤을 때 단어가 생소한 단어여서 이해하는데 어려움이 있었다.
    • 이해한 점
      • 종속 함수는 다른 함수에 직접적으로 의존하여 독립적으로 동작할 수 없는 함수를 의미한다.
      • 함수 간의 종속성이 강하면 코드의 유지보수성이 낮아지고 재사용성과 테스트가 어려워진다.

3. 📚 참고 사항

📢 논의하기

관련된 자료가 있다면 공유하고, 더 깊이 논의하고 싶은 아이디어나 의견을 정리합니다.

  1. 관련 자료 공유