인프런 워밍업 클럽 백엔드 스터디 2기 | 2주차 발자국과 중도하차 회고
박우빈 님의 Readable Code: 읽기 좋은 코드를 작성하는 사고법 을 듣고 작성한 게시글입니다.
KPT
Keep: 앞으로 지속하고 싶은 부분
🌿 인프런 노트
전부 기록하는 것보다 인프런 노트를 활용하는게 확실히 더 빠르게 정리할 수 있었다. 그림 자료 같은 건 체크만 해 놓으면 나중에 다시 확인할 수 있어서 좋은 것 같다.
미션 수행
미션을 열심히 수행했다! 스터디 카페 이용권 선택 시스템 리팩토링이었는데, 강의를 들을 땐 이해되던 내용이 막상 적용하려니 막막하게 느껴졌다. 마음속으로 나름의 기준을 정하고 시작하는게 도움이 됐는데, 내가 가장 중요하게 생각한 부분은 중복을 줄이자였다.
그 외에 박우빈 님의 조언대로 고려했던 포인트는 다음과 같다.
- 추상화 레벨
- 하나의 세계 안에서는 추상화 레벨이 동등해야 한다.
- 너무 구체적인 것을
if
문 안에 담지는 않았는지? - 코드가 매끄럽게 읽히는지?
- SRP: 책임에 따라 응집도 있게 객체가 잘 나뉘어져 있는지
- 하나의 객체가 하나의 관심사만을 가지고 있는지?
- 관심사가 잘 분리되어 있는지?
- DIP: 의존관계 역전을 적용할 만한 곳은 없는지?
- 상위 수준의 모듈이 하위 수준의 모듈에 의존하지는 않는지?
- 두 모듈 모두 의존할 수 있는 추상 객체를 만들 수 있는지?
- 일급 컬렉션
- 컬렉션을 의미가 있는 클래스로 담을 수 있는지?
자세한 코드와 각 리팩토링 포인트별 자세한 설명은 Github README.md에 작성해두었다.
Problem: 아쉬웠던 점
구현이 먼저다
중간쯤 오니까 내 기본기가 발목을 잡았다. 어느 순간부터 아무 생각 없이 설명을 듣고 코드를 따라 치게 되는게 느껴졌다.
직접 리팩토링을 해야하는 미션도 꽤 어렵게 느껴졌고.. 강의를 따라가기가 벅차다는 생각이 들었다.
이전에 누군가 커뮤니티에 올려주신 개발바닥 유튜브 - 클린코딩 하는데 구현을 못하는 개발자를 본 기억이 났다.
영상을 보기 전에 처음부터 설계를 단단하게 하고, 클린 코드를 지켜가며 프로그래밍하는게 맞지 않나 하는 생각이 있었는데.. 실제로 프로젝트를 진행해보면서 절대 쉬운 일이 아니라는 점을 깨달았다.
가장 큰 문제점은.. 기능 하나하나 구현하는 데 시간이 너무 오래 걸린다😢
돌아가는 쓰레기 코드를 만들고 유지보수 한 경험이 있을 때 리팩토링의 중요성이 더 와닿을 거고, 그 때가 클린 코드와 테스트 코드를 배울 준비가 된 때라는 걸 깨달았다.
너 아직 아무것도 모르잖아.. 왜 자꾸 남들 좋다는거 따라해보려고 하는데
그래도 워밍업 클럽을 신청했던 걸 후회하진 않는다. 오히려 워밍업 클럽 덕분에 내 실력이 부족하다는 걸 객관적으로 알 수 있었고, 다시 돌아가 기본기를 깎아야 겠다는 생각이 들었다.
그리고 스스로에 대한 자신감이나 용기도 조금 얻을 수 있었다. 왜냐하면, 작년 우아한테크코스 프리코스에 참여했을 때에 비해 알아들을 수 있는 내용이 많아졌다는 걸 체감했기 때문이다. 예를 들어, 예전에 작성했던 RacigCar
프로젝트의 코드 일부를 발췌해보겠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class RacingCarGame {
private List<Car> cars = new ArrayList<>();
private Integer iterNumber = 0;
public void gameStart() {
RacingCarInputView racingCarInputView = new RacingCarInputView();
String names = racingCarInputView.carNameInput();
createCars(names);
if (Validator.validateNames(names)) {
createCars(names);
}
String number = racingCarInputView.carNumberInput();
if (Validator.validateNumber(number)) {
iterNumber = Integer.parseInt(number);
}
return;
}
이 코드도 당시에는 나름 최선의 리팩토링이었다고 생각했다. 지금은 배운 내용을 토대로 다음과 같이 더 리팩토링 해볼 수 있지 않을까? 라는 생각이 든다.
일급 컬렉션 사용하기
1
private List<Car> cars = new ArrayList<>();
위 코드는 Car
객체를 담고 있는 컬렉션이기 때문에, Cars
라는 이름의 일급 컬렉션으로 만들어 관리해주면 좋겠다는 생각이 들었다.
Validate
는 각 객체의 생성자나 메서드로 넘겨주기
1
2
3
4
5
6
7
if (Validator.validateNames(names)) {
createCars(names);
}
String number = racingCarInputView.carNumberInput();
if (Validator.validateNumber(number)) {
iterNumber = Integer.parseInt(number);
}
현재는 Validator
객체에 존재하는 메서드들을 사용해 레이싱 카의 이름과 입력받은 숫자를 검증하고 있다. 따라서 이 결과를 처리할 또 다른 로직이 필요하게 된다. 차라리 검증 객체에 넘겨주어 처리해준다면 낫겠지만, 적어도 RacingCarGame
에 존재하기엔 추상화 레벨이 너무 낮다.
각 객체가 생성될 때 입력 값을 인자로 받아 검증을 진행하면 어떨까?
마찬가지로, iterNumber
는 현재 코드에서 검증이 완료된 number
를 반복 숫자로 받기 위해서만 사용되고 있다. 이 부분도 iterNumber
를 필요로 하는 실질적인 게임 진행 로직이 있는 객체로 빼버리는 게 괜찮을 것 같다.
이런 식으로 사고의 확장이 가능해졌다는게 체감됐다. 조금은 성장한 느낌이 들어 뿌듯했다!
Try: Problem을 해결하기 위해 시도해볼 점
다시 되돌아갈 용기
다시 되돌아가서 기본기를 닦고, 진행하던 프로젝트 tiffy
를 마저 해보려 한다.
시간은 가고 공백기는 길어지고 있으니 마음이 급해지는데.. 먼저 기본을 갖춰야 기회가 찾아온다는 걸 계속 계속 생각해야겠다. 물론 완벽한 준비란 세상에 없지만, 적어도 스스로 부끄럽지 않은 사람이 되기로 해야지.