우아한테크코스를 하면서 정말 많은 변화가 있었고 배우고 있습니다
실제 제출했던 소감문을 바탕으로 작성되었습니다
실제로 작성했던 코드는 여기에서 확인하실 수 있습니다
알게 되었던 점
1. 기능 목록은 진행 순서와 관계가 없다
2. 변경을 고려해서 추상화 해야 한다
3. 주석을 다는 작업이 생각보다 커다란 효용을 준다
4. 코드에 제약을 걸 수록 좋은 코드가 나온다
5. 모든 코드를 테스트 할 필요는 없다
1. 기능 목록은 진행 순서와 관계가 없다
1주차에는 진행 순서를 그대로 기능 목록으로 작성하려고 했었는데
그 순서대로 커밋을 하려니 진짜 너무너무 힘들고, 작성하기가 힘들었었던 경험이 있습니다
2주차 문제를 3번째로 새롭게 작성할 때 기능 목록과 진행 순서를 분리하고, 기능 목록을 작성하기 시작했는데 그 순서대로 구현할 수 있어서 정말 좋았습니다
제가 만든 기능 목록 만드는 방법입니다
- 진행 순서를 전부 나열한다
- 진행 순서에서 나올 수 있을 개념적인 것들을 모두 나열한다
예를 들면 숫자 야구게임에서 ball도 있어야 하고, strike도 있어야 하고, 입력도 있어야 하고...
조합의 기본이 되는 그 단위를 분리해야 합니다
단위를 하나의 기능으로 잡았을 때 진짜 "단위"테스트 라는 목적에 맞는 테스트 코드를 만들 수 있었습니다
Ball이라는 개념을 검증하기 위해서는 0~3까지만 그 값이 될 수 있다는 것을 검증하기만 하면 끝이니까요
필요할법한 모든 개념들을 다 분리해서 개념적인 단위로 쪼개게 된 이후에는 기능들을 조합해서 만드는 커다란 단위가 생깁니다
단위가 작다면 단위 테스트로 묶을 수 있습니다
적당히 크다면 단위 테스트가 아니라 통합 테스트를 작성할 필요가 있는지에 대해서
이런 점들을 생각하고 나니 테스트 커버리지 100%에 대해서 욕심 낼 필요 없다 단위 테스트만 적당히 만들면 된다 라고 했던 글들이 이해가 가기 시작하고 좋았습니다
2. 변경을 고려해서 추상화 해야 한다
하나의 어플리케이션이 있을 때 변경이 가장 많이 일어날 수 있을 구간은 어디일까?
라는 질문을 했을 때 계층형으로 생각을 정리할 수 있었습니다
입출력이 가장 많이 바뀌고, 도메인 로직으로 갈 수록 적게 바뀐다는 것이었습니다
UI자체의 변화가 일어나는 경우도 많고, 그럴 때마다 view가 바뀌어야 하는데
이때마다 모든 코드를 엎을 수는 없었습니다
그래서 로직이 View에 의존하지 않아야 한다는 결론이 나왔습니다
예를 들면 게임 도중에 결과 메시지를 출력해야 한다고 했을 때 System.out.println으로 직접 출력하게 되면
추후에 변경을 하기 어렵습니다. 변경하기 위해서는 모든 로직에 있는 코드를 다 고쳐야 합니다
나중에 파일로 출력을 변경한다, 네트워크로 http 요청을 날리는 것 같은 방식의 변화를 일으키기 정말 어렵다는 문제가 생깁니다
만약 출력의 형태를 outputView같은 형태로 1번 추상화 해두면 마지막 구현체를 교체하는 것만으로 모든 코드가 바뀔 수 있었습니다
실제로 출력 과정을 System.out.println에서 System.err.println으로 교체하려는 작업이 필요했을 때
에러 출력을 out으로 하면 안 될거 같다는 내용을 알게 된 이후였는데, 이때 정말 간단하게 교체할 수 있었습니다
그 클래스를 실제로 찾아다니면서 바꿀 필요가 없이 구현체를 바꾸기만 하면 끝이었습니다
파일 명을 바꾸기도 쉬웠고, 어댑터 형태로 중간에 끼워넣기도 가능했기에 다양한 시도가 가능했기에 좋았습니다
3. 주석을 다는 작업이 생각보다 커다란 효용을 준다
단순하게 코드를 추후에 확인하기 쉽게 만든다는 부분이 가장 큰 장점이긴 합니다
그것 뿐만 아니라 코드 퀄리티를 쉽게 올릴 수 있는 방법 중 하나였습니다
모든 public 메서드, 클래스에 대해서 주석을 달고 나면 이 메서드가 정말 필요한가? 라는 질문을 할 수 있게 되었습니다
이 public메서드가 정말 필요하고, 인자가 적절하고, 반환 값이 적절한 것인지를 확인하는 검증 절차로 생각해볼 수 있었습니다
이 과정을 통해서 생각보다 많은 메서드를 지울 수 있었고, 많은 부분의 가시성을 private으로 바꿀 수 있었습니다
이 과정을 통해서 상속 관계를 생각해낼 수 있었고, 더 깔끔하고 유지보수에 좋은 코드를 만들 수 있었다고 생각합니다
4. 코드에 제약을 걸 수록 좋은 코드가 나온다
정말 힘든 제약이라고 생각했던 객체지향 생활 체조 원칙 9가지를 지키려고 할 수록 좋은 코드가 나왔던 거 같습니다
- indent 1로 제한하기
- 인스턴스 변수는 2개까지만
- List를 바로 내보내지 않고 일급 컬렉션을 작성한다
- else를 사용하지 않는다
- 모든 원시값과 문자열을 포장한다
- 한 줄에 하나의 점만 찍는다
- 줄였지 않는다
- 모든 엔티티는 작게 유지되어야 한다
- 긴 메서드는 15줄을 넘기지 않는다 - getter, setter, setter를 사용하지 않는다
실제로 코드에 일급 컬렉션 1개를 제외하고 어떤 곳도 getter가 존재하지 않습니다
이 원칙을 다 지키고 나니 가독성이 훨씬 좋고, 깔끔한 코드가 나오게 되었습니다
이 원칙을 무조건 지키는 것이 좋은 코드가 되지는 않는다고 생각하기도 했습니다
실제로 점수를 계산하는 객체에서 억지로 indent를 제거하다보니 오히려 가독성이 안 좋은 것 같은 코드가 나오기도 했지만
이 책임을 하나의 클래스로 분리할 수 있었기에 훨씬 좋은 결과가 있었다고 생각합니다
정리를 하는 과정에서 원칙이 되는 무언가가 있다는 점이 생각보다 커다랗게 작용했습니다
5. 모든 코드를 테스트할 필요는 없다
객체지향적으로 잘 짠 코드의 경우 내부 구현을 알아볼 방법이 없습니다. 그렇기에 모든 부분은 감춰져있어 테스트를 작성하는 것이 불가능한건데요
유일하게 그런 코드를 테스트 하는 방법은 mock객체를 활용해서 사용하는 방법으로 다음과 같습니다
1. 객체에게 보장할 수 있는 trigger를 만든다(mock 객체로 메시지를 보낸 것을 보장한다)
2. 객체가 다시 전송하는 메시지를 mock객체를 통해서 확인한다
1,2가 모두 올바르게 작동되었다면 그 객체는 잘 작동한 것으로 가정한다
라는 public interface를 테스트 하는 방법밖에 없습니다
그렇다면 입력 부분에 대한 테스트는 어떻게 진행해야 할까요?
입력을 보장할 수 있는 trigger를 만들 수 없습니다 물론 Console.readLine()을 모킹하고, 실행할 수는 있지만, 이 자체는 그냥 모킹한 결과가 잘 돌아간다 라는 것을 설명할 뿐인거죠
실제 구현을 테스트할 수 없는 겁니다
입력을 트리거하는 Console즉 터미널쪽을 제공할 수 없기에 제대로 된 테스트를 할 수 없습니다
따라서 이 부분을 테스트하려고 하는 부분은 괜한 시간 낭비가 될 가능성이 놓다는 것을 알게 되었던 부분이 정말 좋았습니다
느낀 점
한 문제를 이렇게까지 열심히 생각하고, 수정하려고 고민했던 부분이 생각보다 큰 도움이 되었던 것 같습니다
단순히 문제를 푸는 것에만 만족했다면 얻기 힘들 정도의 변화였는데요
어떻게하면 더 깔끔하고 가독성이 좋은 코드 될까?
어떻게 하면 설계를 똑같이 할 수 있는 틀을 만들 수 있을까?
이 2가지 질문을 계속해서 고민하고 노력했던 부분이 특히 커다랗게 작용했던 거 같습니다
테스트 가능한 모든 코드를 테스트 한다는 원칙과
클래스는 단 하나의 책임만을 갖는다는 원칙을
무조건 지키려고 해본 결과 생각보다 많은 것들을 배울 수 있었습니다
얼마나 하려고 하는지, 뭘 배워야 하는 지를 아는 것이 정말 중요했습니다
번외 1. 멍청한 실수
끝나고 코드리뷰를 통해 알 수 있었던 부분이 1부터 9까지만 입력받을 수 있다는 부분이다
0을 왜 그렇게 처리했지 라는 후회가 정말정말 많이 남는 부분이었다
Readme.md에서 분명히 1부터 9까지였는데 그게 왜 해석이 안됐지? 라는 생각이 참... 너무너무 많이 들었던 순간이었다
진짜 일주일 내내 이것만 생각하고, 열심히 하는 진짜 최선을 다한 시간이었는데, 만약 떨어지게 된다면, 그리고 그 떨어진 부분에 영향이 있을 수 있다는 부분 자체가 참 마음이 아프다
예전에도 비슷하게 제대로 안 읽다가 피본 경험이 많은데 또 그런 모습이 나와서 참 아쉽다
다시 열심히 해야지 3,4주차에서 실수 하지 않을 수 있어서 다행이라고도 생각하고, 정말 돌이킬 수 없는 순간에 생각하지 않게 되어서 다행이라고 생각하고 3,4주차에 더 열심히 해야겠다
지나간 거는 되돌릴 수 없으니 앞으로 더 열심히 해서 이제부터는 진짜 후회 없이 해봐야 겠다
'우아한테크코스' 카테고리의 다른 글
우아한테크코스 프리코스 4주차 후기 (0) | 2022.11.19 |
---|---|
우아한테크코스 프리코스 3주차 후기 (0) | 2022.11.10 |
우아한테크코스 프리코스 2주차 문제 풀이 복습 (0) | 2022.11.06 |
우아한테크코스 1주차 후기 (3) | 2022.11.02 |
우아한테크코스 1주차 사전준비 (0) | 2022.10.24 |