우아한테크코스에서 진행하는 미션을 혼자 진행해보면서 나의 생각과 배운 것을 정리하는 글
[페어매칭] 미션 제출 by changjun6518 · Pull Request #1 · changjun6518/java-pairmatching-precourse
테스트 코드 작성 MVC 패턴 객체 메세지 전달 의존관계
github.com
Course enum에 여러 변수들?을 담았는데 책임이 많아져서 문제?
public enum Course {
BACK_END("백엔드", "./src/main/resources/backend-crew.md"),
FRONT_END("프론트", "./src/main/resources/frontend-crew.md"),
;
static{
for (Course course : Course.values()) {
course.initCrews();
}
}
private String name;
private String filePath;
private Crews crews;
Course(String name, String filePath) {
this.name = name;
this.filePath = filePath;
}
private void initCrews() {
crews = CrewFileReader.readCrews(filePath);
}
}
- Course 이름 , filePath, 크루 리스트 등 과정에 속해있는 필요한 요소들을 enum안으로 다 담았는데 적절한 방법으로 사용한 건지 모르겠다
- static은 프로그램을 실행하자마자 데이터를 보유하고 있어하게끔 (캐쉬 역할을 하게) 함
Enum의 예외처리는 어떻게할까?
- 이건 검증로직이 어디에 있을까에 대한 의문인 것 같은데 enum도 클래스처럼 안에 하는게 좋겠지?
백엔드 과정 및 프론트 과정 크루 리스트 받아올때 중복 코드 어떻게 제거함?
public class CrewFileReader {
static List<String> crewsString = new ArrayList<>();
public static Crews readCrews(String filePath) {
try {
BufferedReader bufferedReader = new BufferedReader(
new FileReader(filePath)
);
String str;
Crews crews = new Crews();
while ((str = bufferedReader.readLine()) != null) {
crewsString.add(str);
crews.add(str);
}
bufferedReader.close();
return crews;
} catch (Exception e) {
throw new IllegalArgumentException("제대로 파일을 읽어올 수 없습니다!");
}
}
}
- 인터페이스로 처리해보고 싶은데 잘 모르겠음
- 매개변수로 파일경로 주입시켜줬음 -> 파일경로를 설정해주는 역할을 상위 객체로 넘김
이미 매칭되었는지 판단할때 map으로 확인하는데 String 값의 경우 객체기 때문에 포인터가 다를 것 같은데 contains를 사용했을때 같은 객체라고 판단할까?
private final HashMap<Level, List<String>> crewsByLevel;
public boolean isMatched(Level level, String crewName) {
if (crewsByLevel.containsKey(level)) {
List<String> matchedCrews = crewsByLevel.get(level);
return matchedCrews.contains(crewName);
}
return true;
}
- Heap 에 존재하는 객체들이기 때문에 같은 객체라고 판단할 것이다
- 여러 군데에 쓰여도 같은 객체를 가리키고 있다
- Key가 String이라면 equals 함수의 내부 로직이 있을거야...! 아마도
Matching - Crews - Crew 페어 매칭 이력 검사해서 이미 매칭되었는지 검증하는 함수 명을 똑같이 하는게 맞는가?
- 3개 클래스 모두 매칭되었는지 검증하는 함수명이 isMatched인데 헷갈린다
- 근데 의존관계?가 명확하면 그렇게 헷갈리지 않을 것 같기도함 -> 찾아보자
Matching 클래스를 불변객체? 로 두고 하나의 객체만 계속 사용하도록 만들면 공간효율이 좋지 않을까 생각함
public class Matching {
private final List<String> stringCrews;
public Matching(List<String> stringCrews) {
this.stringCrews = stringCrews;
}
public MatchingResult match(Level level, Crews crews) {
shuffle();
MatchingResult matchingResult = new MatchingResult();
matchingResult.match(stringCrews, level, crews);
return matchingResult;
}
private void shuffle() {
Collections.shuffle(stringCrews);
}
}
- 하지만 여러 매칭이 동시에 실행된다고 했을때 시간효율이 안좋음 + 멀티스레드 환경에서 동시 접근안됨
equals와 hashcode 재정의할때 왜 둘다해야할까?
public class MatchingInfo {
private Course course;
private Level level;
private Mission mission;
public MatchingInfo(Course course, Level level, Mission mission) {
this.course = course;
this.level = level;
this.mission = mission;
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
MatchingInfo matchingInfo = (MatchingInfo) o;
return course == matchingInfo.course &&
level == matchingInfo.level && mission == matchingInfo.mission;
}
@Override
public int hashCode() {
return Objects.hash(course, level, mission);
}
}
- 해쉬코드는 객체의 주소값을 변환하여 생성한 객체의 고유한 정수값
- 실제 객체들의 주소가 다르더라도 변환된 hashCode를 보고 같은 객체인지 판단함!
- 그래서 String 같은 경우도 문자열이 같으면 hashCode가 같다
key 결과에 따라서 Dto 보다는 matchingResult 가 저장되었으면 하는데 service에서 가져오도록 하려면 로직을 전부 수정해야함 → 잘못된 코드 아닌가
private final HashMap<MatchingInfo, MatchingResult> repository = new HashMap<>();
- 원래 MatchingResultDto 였는데 MatchingResult로 수정
- service 에서 Dto를 반환받도록 되어있어서 결과값을 수정하려면 모두 다 변경해야함
- 테스트코드를 작성하면서 진행했으면 좀 더 수월했을 것 같음!
Matching을 MatchingResult와 분리 시켰는데 MatchingResult public method 들이 불안함
- public 메소드를 어쩔수 없이 사용하는 경우 접근 제한을 어떻게 할까?
- 패키지로 접근 제한하나?
엔티티에서 Dto를 만들어서 반환할까? 아니면 service에서 get으로 엔티티 내부 변수 가져와서 Dto로 변환할까?
public MatchingResultDto convertDto() {
return new MatchingResultDto(matchingResult);
}
- getter 안쓰려면 안에서 이렇게 해줘야할 것 같다
단위 테스트 진행할때 접근제어자 public에서 private으로 변경되는 경우는 단위 테스트 진행 못하나요? (matching에서 기능들 private으로 변경해서 이전에 테스트한 것들에 에러생김)
- 굳이 private 까지 테스트를 진행할 필요가 없다고 한다...!
- private를 할 수 있는 방법은 있다
- 쓸데없는 테스트때문에 효율도 떨어지고 코드량도 많아지는 문제가 있을 것 같다
MatchingTest에서 단위 테스트 진행할때 공통되는 부분이 많다(given, when, then)
class MatchingServiceTest {
@Test
public void matchTest() {
// given
Course course = Course.BACK_END;
Level level = Level.LEVEL1;
Matching matching = new Matching(course.getStringCrews());
}
}
- 공통된 부분은 @Before 를 사용하여 setup해서 진행하자
회고
우테코 최종 코테였던 미션이다. 처음 풀때 엄청 어려웠는데 지금은 꽤나 잘 풀 수 있는 것 같다.
고민없이 공부하는 게 문제인 것 같고 어떤 방법이 더 좋은지 끊임없이 생각하고 적용해보면서 장단점을 체화하는게 좋은 것 같다. 더 나아가서 이유에 대해서 논리적으로 설명할 수 있으면 좋겠다.
끝.
'프로그래밍 > 우테코' 카테고리의 다른 글
[우테코] level 1 로또 미션 회고 - 2 (0) | 2022.02.13 |
---|---|
[우테코] level 1 로또 미션 회고 - 1 (0) | 2022.02.04 |