정보 은닉을 위해 필드를 private로 숨겨놓고 Getter와 Setter를 사용한다면 정보 은닉의 효과를 볼 수 없기에 1주 차 때도 사용하지 않았고 2주 차 때도 마찬가지로 사용하지 않고 진행하기로 했습니다. 그렇기 위해서는 Tell, Don’t Ask(TDA) 원칙을 지키면서 코딩을 진행해야 했습니다. 두 개의 클래스 사이에서 TDA 원칙을 지키는 것은 어렵지 않았지만 3개 이상의 클래스 사이에서는 로직이 복잡해지고 너무 빙 돌아간다는 느낌을 받았습니다.
따라서 메서드의 개수도 많아지게 되었고 테스트하는 과정도 어려워졌습니다.
캡슐화도 지키고 싶고 로직도 효율적으로 구현하고 싶었기에 계속해서 고민하고 학습했습니다. 그러다가 요구사항이 ‘자동차의 이동 거리를 보여줘야 한다’는 내용이었다는 것을 생각했고 이 뜻은 이동 거리에 대한 캡슐화를 지킬 수 없는 것이 아닌가? 라고, 생각하게 되었습니다.
그렇다면 이동 거리를 나타내주는 필드에 대해서는 getter를 사용해도 무방한 것입니다.
이렇게 Getter가 사용되어야 하는 곳이 있기에 잘 판단해서 당당하게 사용해야겠다고 생각했고 후에 getter를 이용해서 이전보다 더 효율적이고 깔끔한 코드를 구현할 수 있게 되었습니다. 2주 차 진행 중에 가장 많은 시간을 투자하였지만, 가장 많은 것을 알게 되었던 뜻깊은 과정이었습니다.
기능을 구현하면서 그 기능에 맞는 테스트 코드를 작성하였습니다. 테스트 케이스를 하나씩 직접 생성해서 테스트했기 때문에 메서드의 길이가 길어지고 중복되는 부분이 너무 많이 존재했습니다. 그래서 이러한 경우를 해결할 방법은 없는지 학습하던 중 @ParameterizedTest 어노테이션이라는 것을 사용해서 하나의 테스트 방법에 여러 개의 파라미터에 대해서 테스트할 수 있다는 것을 알게 되었습니다. 이 어노테이션을 사용해서 리팩토링을 진행했고 테스트할 값들을 외부에서 불러오게 되니 메서드의 길이가 크게 줄어들었고 중복 또한 제거할 수 있어서 가독성이 크게 향상했습니다.
2주 차 문제를 해결하면서 ‘어떻게 메서드를 구현할 것이고 어떤 객체를 사용해서 구현할지’와 같은 생각을 하며 오랜 시간을 사용했었습니다. 물론 이처럼 더 효율적인 방법은 없는지 생각하는 것은 나쁘지 않다고 생각합니다. 하지만 저의 문제는 코딩을 진행하지 않고 오랜 시간 동안 생각만 한다는 것입니다. 결국 이런 습관 때문에 시간에 쫓기게 되었고 초조한 마음은 코딩하는 과정을 더 힘들게 하였습니다. 그래서 저는,
등 과 같은 나만의 규칙을 정해서 생각하지 말고 따를 수 있게 한다면 코딩에 더 많은 시간을 사용할 수 있다는 것을 알게되었습니다.
1주 차를 끝내고 처음으로 코드 리뷰를 작성하고 받아봤습니다. 처음으로 리뷰를 작성해 보는 것이라 설레기도 했지만, 리뷰한 내용이 틀린 내용이면 어떡하냐는 생각에 걱정되는 부분도 있었습니다. 하지만 저는 틀린 부분이 있다면 이 리뷰를 통해서 학습하게 되는 계기가 된다고 생각하고 마구마구 리뷰하기 시작했습니다. 리뷰를 받은 부분에 대해서 학습하면서 성장하는 것으로 알고 있었는데 신기하게도 저는 리뷰를 달면서 더 학습하게 되었습니다. 혼자 코딩할 때는 놓쳤던 부분을 다른 사람의 코드를 보면서 알게 되었던 점이 많았고 코드 내용에 대해 서로 토론하는 활동도 너무 많은 도움이 되었습니다. 어느 순간 코드 리뷰에 재미를 느끼고 흥미가 붙어버린 저는 리뷰 스터디를 만들어서 성장하고 있습니다.
1주 차를 진행할 때는 List> names처럼 사용했던 코드에 일급 컬렉션으로 포장해 보면 어떠냐는 리뷰를 받았고 일급 컬렉션을 학습해야겠다고 생각했습니다. 알고 보니 객체지향 생활체조에서 권장하는 내용이었고 ‘비즈니스의 종속적인 자료구조’, ‘불변성 보장’, ‘상태와 행위를 한 곳에서 관리’, ‘이름있는 자료구조’ 등의 장점을 갖고 있다는 것을 알게 되었습니다.
‘이름있는 자료구조’를 생성할 수 있다는 장점을 이용해서 이번 미션에 적용하였고 이전보다 가독성을 향상하게 시킬 수 있었습니다. 아직 일급 컬렉션 사용에 대해 부족함을 느꼈고 확실하게 학습해서 3주 차 미션에는 일급 컬렉션의 다양한 장점들을 적용해 봐야겠다고 생각했습니다.
다른 분들의 코드를 리뷰하던 중 문득 of, from 함수가 많은 사람들에게서 사용되고 있다는 것을 알게 되었습니다. 그러던 중 1주 차 코드 부분에서 가지고 오는 인자에 따라서 다르게 생성시키는 생성자를 구현했던 부분에 대해 정적 팩토리 메서드를 사용해 보라는 리뷰를 받았습니다. 학습하던 중에 많은 분들이 사용했던 of, from 함수가 정적 팩토리 메서드를 의미하는 것이라는 것을 알게 되었습니다.
와 같은 장점들에 대해서 배울 수 있었고, 이번 미션을 진행하면서 생성자 대신에 정적 팩토리 메서드를 사용해서 이름을 지정해 주었고 new()를 사용했을 때보다 향상된 가독성을 경험할 수 있었습니다.
커밋 메시지를 의미 있게 작성
커밋 메시지를 보고 작업한 내용을 이해할 수 있도록 작성
Git을 통해 관리할 자원에 대해서도 고려
굳이 git으로 관리하지 않아도 되는 파일이 존재할 수 있기에 확인
이름을 통해 정확한 의도를 드러내자
나 자신, 다른 개발자와의 소통을 위해 가장 중요한 활동 중의 하나가 좋은 이름 짓기이다. 변수 이름, 함수(메서드) 이름, 클래스 이름을 짓는데 시간을 투자하라.
축약하지 않는다
네이밍이 길어진다고 해서 축약을 하게되면 혼란을 야기할 수 있다.
하지만 예를 들어서 Order라는 클래스에 shipOrder 메서드 이름은 필요가 없다 ship이라고 작성해도 order.ship()이라고 호출되기에 간결하게 가능하다.
공백도 코딩 컨벤션
if, for, while문 사이의 공백도 코딩 컨벤션이다.
이부분은 조금 더 공부가 필요한 부분같다.
확실히 이해하고 넘어가자
의미 없는 주석을 달지 않는다
주석으로 의미를 나타내기 보다는 네이밍을 통해서 의미를 전달할 수 있게 작성해보자
Java에서 제공하는 API를 적극 활용한다
내가 현재 구현하고있는 기능이 Java API로 존재하지 않는지를 확인하고 구현한다.
확인하고 없다면 구현한다.
코드를 리뷰하면서 신기했던점은 평소에 코드를 작성할 때는 몰랐던 부분을 확인할 수 있었다. 예를 들어서 함수명이나 변수명, 클래스 명에서 의미를 파악해서 자연스럽게 이어지고 읽어지는지가 중요했고 이러한 것들이 가독성을 높여주는 요소가 된다고 생각하게되었다.
코딩능력과 리뷰는 다르다는 것을 알게되었다.
정적 팩토리 메서드란 객체 생성의 역할을 하는 클래스 메서드
생성자 대신 정적 팩토리 메서드를 고려하라
private static final String VALIDATE_LADDER_HEIGHT_MESSAGE = "사다리의 최소 높이는 1이상이어야 합니다.";
->
private static final int MINIMUM_LADDER_HEIGHT = 1;
private static final String VALIDATE_LADDER_HEIGHT_MESSAGE = "사다리의 최소 높이는 " + MINIMUM_LADDER_HEIGHT + " 이상이어야 합니다.";
-매직 리터럴 처리
System.out.println("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
이런 부분을 3을 상수로 처리하고 나머지 부분을 message로 처리 후 합치는 방식 사용
문자열 또한 가독성을 힘들게 만들 수 있다. 상수로 처리해보자
-조건문 중첩은 코드의 의도 파악 및 유지보수가 힘들고 가독성이 떨어진다
입력에 대한 테스트
getter를 쓰지 않는것
this 의 용도
코드 리뷰의 중요성
클래스 정렬을 위한 Comparable
comparable, Comparator 차이
comparable - 나와 상대를 비교
comparator - 두 객체를 비교
-dto와 엔티티 차이
getter, setter 최소한 줄이기
객체에게 명령을 내린다
스트림 알아보기
Collection이나 조건에 사용해보자
정적 팩토리 메서드
객체 생성에 이름을 붙일 수 있다
Predicate란
boolean값을 리턴하는 함수형 인터페이스
람다로 접근가능
클린코드 다시 공부
일급 컬렉션으로 포장하기(불변성)
리팩토링
Getter 를 쓰면 왜 안 되는가?
캡슐화의 의미가 없어진다. private으로 필드를 선언해놓고 getter로 아무 곳에서나 값을 꺼내올 수 있다면 상태 정보가 그대로 노출되는데 private을 굳이 선언한 의미가 없어진다.
입력을 받기위해 생성했던 CarNames가 나중에 다시 재사용되는 경우를 보았다!
"테스트를 위해 구현 설계가 변경될 수 있다.
테스트 코드는 구현의 보조적인 수단이 아니며, 같은 레벨로 봐야한다.
좋은 디자인으로 구현된 코드는 대부분 테스트 하기가 쉽다.
테스트 하기 어렵게 구현 되었다면, 코드 확장성 / 의존성 등 코드 디자인, 설계가 잘못되었을 확률이 굉장히 높다."
의존성 : 유지보수 시점에 같이 변환되는지 안되는지
해당 요구조건이 변경 되었을때에 어디를 수정할 것인가! 을 생각해서 해당 기능이 어느 역할의 기능인지 판단
이미 요구사항이 은닉하지 말것을 요구하고 있다, 때문에 getter의 사용으로 캡슐화가 깨어졌다고 말하기 힘들다ㅏ!!!!
분명하게 getter 사용해야 되는 곳이 있고,
분명하게 사용해야 되는 곳이있다.
아주 좋은 설명
나만의 규칙을 정하는 것
기능만 보고 구현하는 것이 아닌 기능을 보고 어떤 객체들이 필요할지를 생각한 후에 진행
테스트의 중복을 줄이기위한 @ParameterizedTest 사용
입출력 테스트
디미터의 법칙
무작정 .의 개수를 줄이는 것이 아닌 연속적으로 . 을 사용했을때의 내부구조가 드러나는 것을 막는 것이다.
때문에 Stream같은 체이닝은 예외다.!