<aside> 💡 기존 코드
@Data
@Entity
@Table(name = "tester")
@NoArgsConstructor
public class Tester extends BaseTime {
...
}
해당 문제가 발생하는 가장 큰 이유는 @Data를 적용했기 때문입니다. @Data를 제거하고 Entity를 변경해야 한다면 명시적인 메서드를 이용해서 변경하도록 하겠습니다.
<aside> 💡 기존 코드
@Service
@RequiredArgsConstructor
public class MakerAuthServiceImpl implements MakerAuthService {
@Override
@Transactional
public PatchTestResponse patchTest(
UUID makerId,
UUID testId,
@RequestBody PatchTestRequest request
) {
Maker maker = makerRepository.findById(makerId)
.orElseThrow();
Test test = testRepository.findById(testId)
.orElseThrow();
long beforePoint =
((long) test.getReward() * test.getParticipantCapacity());
String symbolImageRoot =
FileHandler.saveProfileFileData(request.getSymbolImage());
test = request.toEntity(test, symbolImageRoot);
long needPoint =
(long) test.getReward() * test.getParticipantCapacity();
if (maker.checkAvailableCreateTest(needPoint - beforePoint)) {
maker.setPoint(maker.getPoint() - (needPoint - beforePoint));
return new PatchTestResponse(test.getId());
} else {
throw new MakerRevertTestFailException("수정하기 위한 잔여 Point가 부족합니다.\n 필요한 Point: " + (needPoint - beforePoint) + ", 잔여 Point: " + maker.getPoint());
}
}
...
}
해당 문제는 단일 책임 원칙을 위반하고 있어 발생합니다. Service에서 Entity에 들어갈 값을 직접 다루다 보니 Entity의 값 위반에 대한 예외도 Service에서 처리하게 됩니다. 그리고 만약 등록할 때, 수수료가 든다는 등, 추가적인 요구사항이 발생하면 Service에 있는 모든 등록하는 Method를 수정해야합니다.
이 문제를 해결하기 위해서는 Entity를 수정하는 경우, 책임을 Entity에 두고 메서드 형태로 Service가 사용하도록 해야합니다. 이 외에도 대부분의 로직이 Service에서 Entity 값을 직접 변경하는 형태로 작성되었는데, 이를 수정하도록 하겠습니다.
<aside> 💡 기존 코드
@Repository
public interface TestRepository extends JpaRepository<Test, UUID> {
...
@Query(value = "select t.id,t.title,t.participant_capacity,t.register_time,t.content," +
"t.reward,t.symbol_image_root,t.modify_time,t.maker_id," +
"t.recruitment_time_start,t.recruitment_time_limit," +
"t.duration_time_start,t.duration_time_limit " +
"from test t, apply_information a " +
"where a.test_id = t.id and t.recruitment_time_limit >= now()" +
"group by t.id order by count(t.id) desc limit 4", nativeQuery = true)
List<Test> getTop4Test();
@Query(value = "select * from test t, " +
"(select test.id from test where test.recruitment_time_start <= now() and test.recruitment_time_limit >= now() " +
"EXCEPT select t.id from test t, apply_information a " +
"where t.recruitment_time_start <= now() and t.recruitment_time_limit >= now() and t.id = a.test_id and a.tester_id = ?1) " +
"as tt where t.id = tt.id order by t.recruitment_time_limit - now();", nativeQuery = true)
List<Test> findAllByTestByDeadLineExceptApply(UUID tester_id);
...
}
</aside>