짧 주의
문제 상황: swift 처럼 callback함수를 통해 코딩하고 싶었는데 어떻게 할 방법이 없었음, 그래서 Function<T,R>이라는 함수를 사용했는데 다음과 같은 문제점이 있었음
1. callback에서 직접 throw를 처리해야함. 즉 callback에서 throw를 넘기지 못하는 문제가 발생ㅎ
2. 너무나 많은 try - catchblock때문에 정신없음
As is
실제 어지럽게 작성한 코드. Function<R,S>로 어거지로 해결하려다가 가독성 및 제대로 수행하지 못하고 에러가 난 모습을 볼 수 있습니다.
private <T> T createPreparedStatement(String sql, Function<PreparedStatement, T> executor) throws SQLException {
try (
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
PreparedStatement prstmt = conn.prepareStatement(sql)
) {
return executor.apply(prstmt);
} catch (SQLException e) {
e.printStackTrace();
throw e; // 필요 시 사용자 정의 예외로 변환 가능
}
}
// CREATE
public boolean addTodo(CreateTodoRequest dto) {
String sql = tableType.insertTodoSQL(dto.userId(), dto.title(), dto.content());
// Function 정의: PreparedStatement에서 execute()를 실행
Function<PreparedStatement, Boolean> executeFunction = preparedStatement -> {
try {
return preparedStatement.execute();
} catch (SQLException e) {
System.err.println("Failed to execute SQL: " + preparedStatement);
e.printStackTrace();
return false; // 실패 시 안전하게 false 반환
}
};
// 메서드 호출 및 예외 처리
try {
return createPreparedStatement(sql, executeFunction);
} catch (SQLException e) {
System.err.println("Failed to add todo: " + e.getMessage());
return false;
}
}
To be
@FuncationInterface를 통한 코드 Result Type과 <T> T를 정의해줘서 깔끔하게 리턴하는 모습을 볼 수 있습니다.
// Custom functional interface to remove try-catch from executor
// For
@FunctionalInterface
interface PreparedStatementExecutor<T> {
T execute(PreparedStatement prstmt) throws SQLException;
}
private <T> T createPreparedStatement(String sql, PreparedStatementExecutor<T> executor) throws SQLException {
try (
Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
PreparedStatement prstmt = conn.prepareStatement(sql);
) {
return executor.execute(prstmt);
}
}
// CREATE
public boolean addTodo(CreateTodoRequest dto) {
String sql = tableType.insertTodoSQL(dto.userId(), dto.title(), dto.content());
try {
// Directly propagate SQLException
return createPreparedStatement(sql, PreparedStatement::execute);
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}