//////
Search
📓

10/21 회고록

생성일
2022/10/21 08:16
태그

김기헌

Strategy pattern을 적용하여 Refactoring

기존 코드
public class UserDao { public void add(User user) { Map<String, String> env = System.getenv(); try { // DB접속 (ex sql workbeanch실행) Connection c = connectionMaker.connectionMaker(); // Query문 작성 PreparedStatement pstmt = c.prepareStatement("INSERT INTO users(id, name, password) VALUES(?,?,?);"); pstmt.setString(1, user.getId()); pstmt.setString(2, user.getName()); pstmt.setString(3, user.getPassword()); // Query문 실행 pstmt.executeUpdate(); pstmt.close(); c.close(); } catch (SQLException e) { throw new RuntimeException(e); } } public void deleteAll() throws SQLException { Connection c = connectionMaker.connectionMaker(); PreparedStatement ps = c.prepareStatement("delete from users"); ps.executeUpdate(); ps.close(); c.close(); } }
Java
복사
UserDao Strategy pattern 적용
public class UserDao { private ConnectionMaker connectionMaker; public void add(User user) { //add 적용 try { jdbcContextWithStatementStrategy(new AddStrategy(user)); } catch (SQLException e) { throw new RuntimeException(e); } } public void deleteAll() throws SQLException { //delete 적용 jdbcContextWithStatementStrategy(new DeleteAllStragegy()); } public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException{ Connection c = connectionMaker.connectionMaker(); PreparedStatement ps = stmt.makePreparedStatement(c); ps.executeUpdate(); ps.close(); c.close(); } }
Java
복사
interface
public interface StatementStrategy { PreparedStatement makePreparedStatement(Connection connection)throws SQLException; }
Java
복사
AddStrategy 구현체
public class AddStrategy implements StatementStrategy{ private User user; public AddStrategy(User user){ this.user=user; } @Override public PreparedStatement makePreparedStatement(Connection connection) throws SQLException { PreparedStatement ps = connection.prepareStatement("INSERT INTO users(id, name, password) VALUES(?,?,?);"); ps.setString(1, user.getId()); ps.setString(2, user.getName()); ps.setString(3, user.getPassword()); return ps; } }
Java
복사
DeleteAllStrategy 구현체
public class DeleteAllStragegy implements StatementStrategy{ @Override public PreparedStatement makePreparedStatement(Connection connection)throws SQLException{ return connection.prepareStatement("delete from users"); } }
Java
복사

Strategy 패턴 적용 후 변경점

deleteAll, add 메소드의 삭제, 추가 행위를 DeleteAllStrategy class와 AddStategy makePreparedStatement 메소드에 넘겨줌으로써 deleteAll, add 메소드의 책임을 한 가지 줄였다
메소드마다 있던 공통로직 connection과 statement의 선언을 jdbcContextWithStatementStrategy 메소드로 분리하여 코드의 반복을 줄였다

김상호

이가현

알고리즘 괄호

메소드 만들때 먼저 생각해야 할 것

1.
반환타입을 어떤것으로 할지!
2.
매개변수로 어떤 값을 넣을지

stack 사용 안하고 괄호 문제 풀기

메소드 디자인
반환타입은 괄호가 남아있으면 false, 없으면 true
매개변수는 괄호는 문자이니깐 String 타입의 괄호를 입력받을 것
replacereplaceAll
replace([기존문자], [바꿀문자])
replaceAll([정규식],[바꿀문자]
강사님이 만났던 문제 → replaceAll의 첫번째 인자로는 정규식을 받기 때문에 정규식으로 작성해야 한다!
indexof
특정 문자나 문자열이 앞에서부터처음 발견되는 인덱스를 반환하며 만약 찾지 못했을 경우"-1"을 반환
Replace로 풀 경우 속도
O(N^2)
정규식이란?
코드

stack으로 풀기

스택을 사용안하고도 할수 있는 방법은 있지만 출력하는데 시간이 너무 오래걸리기 때문에 stack으로 푸는게 가장 좋은 방법!
단, 처음 값이 ‘)’일 경우를 위해 예외처리를 필수 적으로 해야한다.
EmptyStackException이 나는 경우
스택 쓰는 경우 연산 속도
O(N^2)  –> O(N)
코드
test

스프링

복습하기

전날 복습
1.
deleteAll(), .getCount()추가 – 166p
2.
deleteAll(), .getCount() 테스트 추가
3.
@BeforeEach 적용하여 테스트코드 개선 – 182p
4.
findById()메소드에서 user == null인 경우 Exception처리 – 175p
5.
try / catch / finally 처리 – 213p
참고 . 강사님 유튜브 강의

JDBC try/catch/finally 코드의 문제점

토비의 스프링 p.216
Human 에러 가능성 : 리팩토링, 테스트를 하는 이유
추상화를 해서 리팩토링을 해야함.

분리와 재사용을 위한 디자인 패턴 적용

토비의 스프링 (p.222)
전략 패턴 (strategy 패턴) : interface를 의존(사용)하게 해서 구현체를 필요에 따라 선택할 수 있게 설계하는 디자인 패턴
같은 기능(interface) 이지만 서로 다른 전략(구현 class)
전략 패턴의 장점
코드 중복 방지
런타임시에 타겟 메소드 변경
확장성, 알고리즘 변경이 용이
지금까지 수업시간에 적용했던 Strategy 패턴들
클래스이름
Context
전략
선택 전략
ReadLineParser
ReadLineParser
Parser
HospitalParser PopulationStatisticsParser
UserDao
.add(), .findById()
ConnectionMaker
AwsConnectionMaker LocalConnectionMaker TeacherConnectionMaker
DeleteAll
.deleteAll()
StatementStrategy
DeleteAllStrategy AddStrategy …

DeleteAllStrategy구현,사용

구현
statement를 전략 구조로 설계하기 위해서 인터페이스 생성
public interface StatementStrategy { PreparedStatement makeStatement(Connection connection) throws SQLException; }
Java
복사
인터페이스를 구현한 클래스 DeleteAllStrategy 생성
public class DeleteAllStrategy implements StatementStrategy{ @Override public PreparedStatement makeStatement(Connection connection) throws SQLException { return connection.prepareStatement("delete from user"); } }
Java
복사
사용
public void deleteAll() throws SQLException { Connection c = null; PreparedStatement ps = null; try { c = connectionMaker.makeConnection(); ps = stmt.makeStatement(c); //DeleteAllStrategy 사용 ps.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { } } if (c != null) { try { c.close(); } catch (SQLException e) { } } } }
Java
복사

공통로직 jdbcContextWithStatementStrategy분리

connection과 preparedStatement부분이 공통으로 들어가기 때문에 메서드로 분리
public void jdbcContextWithStatementStrategy(StatementStrategy stmt) throws SQLException { Connection c = null; PreparedStatement ps = null; try { c = connectionMaker.makeConnection(); ps = stmt.makeStatement(c); ps.executeUpdate(); } catch (SQLException e) { throw e; } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { } } if (c != null) { try { c.close(); } catch (SQLException e) { } } } }
Java
복사
deleteAll()에서 공통 부분 추출했더니 코드가 간결해짐.
public void deleteAll() throws SQLException { jdbcContextWithStatementStrategy(new DeleteAllStrategy()); }
Java
복사

AddStrategy 추가

구현
deleteAll()과 차이점
User클래스의 객체를 생성해서 사용해야한다는 점
RreparedStatement에 인자 3개를 받아와야한다는 점
deleteAll()과 공통점
같은 기능을 하는 인터페이스(StatementStrategy)를 가짐
public class AddStrategy implements StatementStrategy{ User user; // User 선언 // 생성자를 통해서 User클래스 받아오기 public AddStrategy(User user) { this.user = user; } @Override public PreparedStatement makeStatement(Connection connection) throws SQLException { PreparedStatement pstmt = connection.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; } }
Java
복사
사용
public void add(User user) throws SQLException { AddStrategy addStrategy = new AddStrategy(user); jdbcContextWithStatementStrategy(addStrategy); }
Java
복사

임학준

전략패턴

UserDao의 메소드에서 .close()를 처리하기 위해try catch문을 사용했다
메소드들의 예외처리 구간이 길고 중복되는 부분이 많아 따로 관리할 필요가 있다.
UserDao의 메소드

전략패턴의 적용

각 메소드에서 변하지 않는 부분(Connection선언, try/catch문…)들은 Context에 해당한다
공통 부분을 제외한 변하는 부분(ex = prepareStatement("delete from users"))을 Strategy에 놓고 각 메소드에 해당하는 부분을 상속받아 ConcreteStrategyA,ConcreteStrategyB에 넣는다 이때 ConcreteStrategy를 선택전략이라 한다
이 구조는 ConnectionMaker인터페이스에서 AwsConnectionMaker와 LocalConnectionMaker를 구현해서 사용하는 방식과 같다

1. 전략

UserDao에서 공통된 부분을 제외한 변하는 부분을 전략(인터페이스)으로 정한다
public interface StatementStrategy { public PreparedStatement makePreParedStatement(Connection connection) throws SQLException; }
Java
복사

2.선택전략

변하는 부분을 선택전략으로 각 메소드에 맞게 구현한다
public class DeleteAllStrategy implements StatementStrategy{ @Override public PreparedStatement makePreParedStatement(Connection connection) throws SQLException { return connection.prepareStatement("delete from users"); } }
Java
복사
public class AddStrategy implements StatementStrategy{ private User user; public AddStrategy(User user) { this.user = user; } //user를 파라미터로 받는 메소드 add는 User타입 오브젝트를 받을수 있도록 생성자를 이용한다 @Override public PreparedStatement makePreParedStatement(Connection c) throws SQLException { PreparedStatement ps = c.prepareStatement("INSERT INTO users(id,name,password) values(?,?,?)"); ps.setString(1, user.getId()); ps.setString(2, user.getName()); ps.setString(3, user.getPassword()); return ps; } }
Java
복사

3.컨텍스트 코드

public void jdbcContextWithStatmentStrategy(StatementStrategy stmt) { Connection c = null; PreparedStatement ps = null; try { c = connectMaker.makeConnection(); ps = stmt.makePreParedStatement(c);//이부분에 선택전략이 들어간다 ps.executeUpdate(); } catch (SQLException e) { } finally { if (ps != null) { try { ps.close(); } catch (SQLException e) { } } if (c != null) { try { c.close(); } catch (SQLException e) { } } } }
Java
복사
전략패턴적용후 UserDao의 메소드

조국현

최아영

괄호풀기

Replace로 괄호풀기
Stack으로 괄호풀기

Strategy 패턴

실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다.
StatementStrategy 인터페이스 생성
DeleteAllStrategy
AddStrategy
공통로직 분리