우테코 5기 프리코스 웹 백엔드 공통 피드백 자료를 받아보았다. git commit convention에 대한 내용과 code convention 등에 대한 내용들이었는데, 그중에서 함수 관련한 피드백이 많이 와닿았다.
한 함수가 한 가지 기능만 담당하게 한다
함수 길이가 길어진다면 한 함수에서 여러 일을 하려고 하는 경우일 가능성이 높다. 아래와 같이 한 함수에서 안내 문구 출력, 사용자 입력, 유효값 검증 등 여러 일을 하고 있다면 이를 적절하게 분리한다.
private List<Integer> userInput() {
System.out.println("숫자를 입력해 주세요: ");
String userInput = Console.readLine().trim();
List<Integer> user = new ArrayList<>();
for (char c : userInput.toCharArray()) {
user.add(Character.getNumericValue(c));
}
if (user.size() != 3) {
throw new IllegalArgumentException("[ERROR] 숫자가 잘못된 형식입니다.");
return user;
}
}
함수가 한 가지 기능을 하는지 확인하는 기준을 세운다
만약 여러 함수에서 중복되어 사용되는 코드가 있다면 함수 분리를 고민해 본다. 또한, 함수의 길이를 15라인을 넘어가지 않도록 구현하며 함수를 분리하는 의식적인 연습을 할 수 있다.
학교에서 진행하는 팀 프로젝트 중에 자바 Swing으로 구현한 프로그램에서 서버와 HTTP 통신을 해야하는 일이 있었다. 자바의 HttpURLConnection
클래스를 사용하여 구현하는데, API 호출 메서드마다 지저분하고 긴 호출부를 구현했었다.
public class MemberApi {
private static ObjectMapper mapper = new ObjectMapper();
private final static String HOST = Host.getHost();
public static void signUp(Member member) {
try {
String hostUrl = HOST + "/user/signup";
HttpURLConnection conn = null;
URL url = new URL(hostUrl);
conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(3000);
conn.setRequestProperty("Content-Type", "application/json; utf-8");
conn.setDoOutput(true); //POST
String jsonType = mapper.writeValueAsString(member);
System.out.println(jsonType);
OutputStream os = conn.getOutputStream();
os.write(jsonType.getBytes(StandardCharsets.UTF_8));
os.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String response = br.readLine();
System.out.println("응답 메시지 : " + response);
br.close();
int responseCode = conn.getResponseCode();
if (responseCode == 400) {
System.out.println("400 : 명령 실행 오류");
} else if (responseCode == 500) {
System.out.println("500 : 서버 에러");
} else {
System.out.println(responseCode + " : 응답 코드");
}
} catch (ProtocolException e) {
System.out.println("ProtocolException");
throw new RuntimeException(e);
} catch (MalformedURLException e) {
System.out.println("MalformedURLException");
throw new RuntimeException(e);
} catch (IOException e) {
System.out.println("IOException");
throw new RuntimeException(e);
}
}
}
위의 코드가 ‘회원가입’ 한 가지 기능의 메서드였다. 이 지저분한 코드들이 각 기능별로 각각 다 들어가 있었던 것이다. 회원가입을 구현하고, 로그인 구현할 때 복사해서 붙여넣고, 다음 기능에서도 복사 붙여넣기의 연속이었다.
그러다 학교 선배님과 얘기를 나누다가 ‘API 호출하는 부분이 너무 하드코딩이다. 똑같은 거 계속 붙여넣기 하고 있다.’라고 말씀드렸던 적이 있다. ‘그럼 너가 그 부분을 모듈화 해 봐’. 선배님이 이 말을 하셨을 때 머리를 한 대 맞은 것 같았다. 왜 나는 그렇게 할 생각을 못 했을까.. 난 바보다. 그동안 너무 생각없이 구현하는 데 급급했던 것 같다.
그렇게 refactoring을 거치고 아직은 부족하지만 이 전보다는 훨씬 깔끔하고 더 나은 코드가 되었다.
“우리가 지금 겪고 있는 모든 현상들은 지금 보면 부족할지 몰라도, 그게 어제의 최선이었다.”
우아한형제들 CEO 김범준
오늘 유튜브를 돌아다니다가 어쩌다 보게 된 영상에서 듣게 된 말이다. 너무 멋진 말 같아서 기록해 두고 싶었다.
예전의 내 코드가 아무리 형편없고 문제투성이일지라도, 그게 그때의 나에게는 최선이었고 더 배우고 성장해서 좋은 코드를 작성할 수 있을 것이라고 생각한다. 처음부터 잘하는 사람은 없으니까