[LIKELION] 221021

고관운·2022년 10월 21일
0

회고

😄 느낀점

  • 중복되는 코드를 클래스와 메소드를 생성하여 재사용할 수 있다는 것을 배웠다.
  • 인터페이스 도입을 하면서 헷갈릴만한 것들이 많은데 원리를 생각하며 공부해야한다.

😁 목표

  • jdbcContextWithStatementStrategy, AddStrategy 적용까지 복습 ~228

[멋쟁이사자처럼] 5주차 - Spring 입문

알고리즘(괄호 풀기)

replace로 풀기

  1. s.indexOf("()") : 해당 문자열이 있으면 해당 인덱스, 없다면 -1 리턴
  2. ()의 위치를 찾은 후 공백으로 변환
  3. s의 길이가 0이라면 올바른 괄호이므로 true 리턴
public boolean solution(String s) {
        // Stack 쓰지않고 괄호 풀기
        while(s.indexOf("()") >= 0){
            s = s.replace("()", "");
        }
        return s.length() == 0;
    }

split으로 풀기

  1. s.indexOf("()") : 해당 문자열이 있으면 해당 인덱스, 없다면 -1 리턴
  2. ()을 기준으로 split
  3. 공백으로 다시 묶으면 ()이 사라짐
  4. s의 길이가 0이라면 올바른 괄호이므로 true 리턴
public boolean solution1(String s) {
        // Stack 쓰지않고 괄호 풀기
        while(s.indexOf("()") >= 0){
            String[] splitted = s.split("\\(\\)");
            s = String.join("", splitted);
        }

        return s.length() == 0;
    }

Stack으로 풀기

  1. s를 차례대로 가져옴
  2. 가져온 값이 (면 push를 이용하여 stack에 넣기
  3. 가져온 값이 )면, Stack이 비어있다면 올바르지 않은 괄호이므로 false 리턴, 남아있는 것이 있다면 pop
import java.util.Stack;

public class SolveBracket02 {
    // Stack으로 괄호 풀기
    private Stack<Character> stack = new Stack<>();

    boolean solution(String s) {
        for (int i = 0; i < s.length(); i++) {
            if('(' == s.charAt(i)){
                stack.push(s.charAt(i));
            } else if (')' == s.charAt(i)) {
                if(stack.isEmpty()) return false;
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}

Stack으로 풀면 장점
연산속도 : O(N^2) ➡ O(N)

Spring

Spring 복습

에러
Communications link failure : 재빌드 후 환경변수 재설정 후 해결

과정

  1. deleteAll, getCount 추가
  2. deleteAll, getCount 테스트
  3. User 객체를 따로 생성하여 테스트 보완
    (User selectedUser = userDao.findbyId(user1.getId());
    assertEquals(user1.getName(), selectedUser.getName());)
  4. findbyId 예외처리(찾는 Id가 없을 경우)
  5. 테스트 코드 개선(BeforeEach 추가, Autowired에 변수 선언)
  6. deleteAll 예외처리(비정상적인 서버 종료로 close가 안될수도)

try catch 의문사항

  • try안에 return이 있을시 : return은 try에서 하고 finally까지 실행
  • try와 finally안에 return이 있을씨 : try 실행 후 finally까지 실행하고 finally에서 리턴

오늘 배운 내용

현재 문제점

  1. try/catch/finally 문제 : 너무 반복이 심함
    ➡ 익숙해지면 복붙하면서 빠르게 할 수 있지만
    ➡ Human에러의 가능성
    ➡ 따라서 리펙토링, 테스트를 해야함

  2. UserDao의 메소드 : 몇 부분만 다르고 나머지는 동일
    StatementStrategy 인터페이스 도입

개선 과정

  1. StatementStrategy 인터페이스 생성
    🟢 Connection을 매개변수로 받고 PreparedStatement을 리턴하는 메소드 생성
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public interface StatementStrategy {
    PreparedStatement makePreparedStatement(Connection conn) throws SQLException;
}
  1. DeleteAllStrategy() 생성(인터페이스 의존)
    🟢 Connection을 받아 users의 데이터를 삭제하는 prepareStatement 리턴
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DeleteAllStrategy implements StatementStrategy{

    @Override
    public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
        return conn.prepareStatement("DELETE FROM users");
    }
}
  1. UserDao의 deleteAll 수정(인터페이스를 의존하여 다형성)
변경 전
ps = conn.prepareStatement("DELETE FROM users");
변경 후
StatementStrategy strategy = new DeleteAllStrategy();
ps = strategy.makePreparedStatement(conn);
  1. UserDao에 jdbcContextWithStatementStrategy 생성 후 deleteAll의 내용 복사 붙여넣기
    🔴 StatementStrategy(인터페이스) 매개변수를 받음
    🔴 해당 변수를 ps = stmt.makePreparedStatement(conn);로 사용하여 원하는 preparedStatement를 불러옴
public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException, ClassNotFoundException {
        Connection conn = null;
        PreparedStatement ps = null;

        try{
            conn = connectionMaker.getConnection();
            ps = stmt.makePreparedStatement(conn);
            ps.executeUpdate();
        } catch (SQLException e) {
            throw e;
        } finally {     // error가 나도 실행되는 블럭
            if(ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                }
            }
        }
    }
  • deleteAll 메소드는 DeleteAllStrategy() 객체를 jdbcContextWithStatementStrategy() 메소드의 매개변수에 넣어 간소화
public void deleteAll() throws SQLException, ClassNotFoundException {
        jdbcContextWithStatementStrategy(new DeleteAllStrategy());
    }
  1. add도 deleteAll과 똑같이 간소화 가능
    🔴 AddStrategy는 DeleteAllStrategy과 다르게 User 객체가 필요하기 때문에 정의
    🔴 add 역시 jdbcContextWithStatementStrategy에 AddStrategy 객체를 넣어서 간소화
import likelion.domain.User;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class AddStrategy implements StatementStrategy{
    User user;

    public AddStrategy(User user) {
        this.user = user;
    }

    @Override
    public PreparedStatement makePreparedStatement(Connection conn) throws SQLException {
        PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users(id, name, password) VALUES (?, ?, ?)");
        pstmt.setString(1, user.getId());
        pstmt.setString(2, user.getName());
        pstmt.setString(3, user.getPassword());

        return pstmt;
    }
}

🔴 add() 메소드 개선

    public void add(User user) throws SQLException, ClassNotFoundException {
        AddStrategy addStrategy = new AddStrategy(user);
        jdbcContextWithStatementStrategy(addStrategy);
    }

0개의 댓글