오늘 한일

ATDD Q&A 4단계 피드백 반영

일급콜렉션

일급콜렉션 원칙으로 추출할만한 도메인은 답변목록, 삭제이력 정도가 있었다. 삭제이력은 특별한 로직이 없기 때문에 굳이 일급콜렉션으로 구현하지는 않았다.

@Embeddable
public class Answers {

    @OneToMany(mappedBy = "question", cascade = CascadeType.ALL)
    @Where(clause = "deleted = false")
    @OrderBy("id ASC")
    private List<Answer> answers = new ArrayList<>();

    public List<DeleteHistory> delete(User writer) throws CannotDeleteException {
        List<DeleteHistory> deleteHistories = new ArrayList<>();

        for (Answer answer : answers) {
            deleteHistories.add(answer.delete(writer));
        }

        return deleteHistories;
    }

    boolean allOwner(User writer) {
        return answers.stream()
                .allMatch(answer -> answer.isOwner(writer));
    }

    public void add(Answer answer) {
        answers.add(answer);
    }

    public int size() {
        return answers.size();
    }

    public boolean allDeleted() {
        return answers.stream()
                .allMatch(answer -> answer.isDeleted());
    }

    public List<Answer> getAnswers() {
        return Collections.unmodifiableList(answers);
    }
}

Question에서 Answer 컬렉션으로 하던 작업(답변 추가, 삭제, 삭제 확인)을 일급콜렉션에서 수행한다.

DeleteHistoryRepository에서 findAllByContentTypeAndContentId, findAllByContentType 메소드가 필요한 이유는? 이 메소드 없이 구현해 본다.

findAllByContentType를 추가한 이유는 인수테스트에서 RANDOM_PORT로 동작하기 때문에 트랜잭션 롤백이 적용되지 않아 테스트가 제대로 동작하지 않기 때문이었다.

피드백을 반영하기 위해 질문/답변 삭제 -> 히스토리 추가 로직은 서비스에서만 테스트하도록 변경했다.

AcceptanceTest가 Repository와 의존하는 것은 좋은 접근 방식은 아님. Repository에 대한 의존관계를 최소화하면서 구현해 본다.

테스트 데이터 제공을 위해 AcceptanceTest에서 모든 repository를 의존하기 때문에 문제가 되는 듯 하다.

// ApiQuestionAcceptanceTest
private Question selfQuestion() {
    return selfQuestion(questionRepository);
}

public static Question selfQuestion(QuestionRepository questionRepository) {
    return questionRepository.findById(SELF_QUESTION_ID).get();
}

private Question anotherQuestion() {
    return anotherQuestion(questionRepository);
}

public static Question anotherQuestion(QuestionRepository questionRepository) {
    return questionRepository.findById(ANOTHER_QUESTION_ID).get();
}

각 Api 테스트 클래스에서 테스트용 데이터를 제공하도록 변경했다.

삭제 이력 관리를 위해 언제 삭제를 했는지를 남기기 위해 createDate를 가진 것임. 삭제한 이유는?

DeleteHistory의 생성자에서 createDate를 삭제한 이유는 @EntityListeners와 @CreatedDate를 추가하면 자동으로 생성일자가 저장되기 때문이었다.

nextstep 5주차 수업 참여 (마지막)

클린코드 마지막 강의 날. 이력서 작성과 면접에 대한 수업을 들었고, 쫑 파티를 했다. 피자와 맥주를 먹으면서 리뷰어, 교육생들과 대화를 나누는 시간이었는데, 아직 이런 자리는 너무 어색하다 ㅠㅠ..

오늘 느낀점

쫑 파티에서 여러 조언을 해주셨다. 원래 취업을 좀 여유롭게 할 생각이었는데, 너무 안일한 생각이었다는 것을 알게 됐다.

  • 면접에서 공백 기간을 가진 이유가 그저 쉬고 싶어서라고 대답하면 당연히 부정적인 인상을 주게 된다.
  • 아무리 반복되는 업무라고 해도 실무에서 접하는 경험이 결코 부질없지 않으니, 일단 어디서든 일을 하는 것이 중요하다.
  • 해외의 추세에 따라 국내 유명 기업들이 취업을 닫는 추세이다.

발표에서는 "회사 입장에서 직원을 뽑는 것은 물건을 사는 것과 같다" 가 가장 기억에 남는다.

내일 할일

  • s사 온라인 코딩 테스트 (대기업 아님)
  • 플러터 1/4/7/14 앱 기능 설계