실무 프로젝트로 배우는 Kotlin & Spring/자바 프로젝트(ToDo프로젝트) 코틀린으로 리팩토링 하기

Service 리펙토링

webmaster 2022. 11. 5. 17:55
728x90

JavaCode

@Service
public class TodoService {

    private final TodoRepository todoRepository;

    public TodoService(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    @Transactional(readOnly = true)
    public List<Todo> findAll() {
        return todoRepository.findAll(Sort.by(Direction.DESC, "id"));
    }

    @Transactional(readOnly = true)
    public Todo findById(Long id) {
        return todoRepository.findById(id)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
    }

    @Transactional
    public Todo create(TodoRequest request) {
        Assert.notNull(request, "TodoRequest is null");

        Todo todo = Todo.builder()
            .title(request.getTitle())
            .description(request.getDescription())
            .done(false)
            .createdAt(LocalDateTime.now())
            .build();
        return todoRepository.save(todo);
    }

    @Transactional
    public Todo update(Long id, TodoRequest request) {
        Assert.notNull(request, "TodoRequest is null");

        Todo todo = findById(id);
        todo.update(request.getTitle(),
                    request.getDescription(),
                    request.getDone());
        return todoRepository.save(todo);
    }

    public void delete(Long id) {
        todoRepository.deleteById(id);
    }
}

KotlinCode

@Service
class TodoService(
    private val todoRepository: TodoRepository,
) {
    @Transactional(readOnly = true)
    fun findAll(): List<Todo> =
        todoRepository.findAll(by(Direction.DESC, "id"))

    @Transactional
    fun findById(id: Long): Todo =
        todoRepository.findByIdOrNull(id) ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
    //기존에 Optional로 처리하는 것을 코틀린의 언어적인 차원에서 해결할수 있다,

    @Transactional
    fun create(request: TodoRequest?): Todo {
        checkNotNull(request) { "TodoRequest is null" }
        //null 안정성을 사용할 필요가 없다 -> checkNotNull을 통과한 이후부터는 컴파일러가 null이 아님을 알고 있기 때문
        val todo = Todo(
            title = request.title,
            description = request.description,
            done = request.done,
            createdAt = LocalDateTime.now(),
        )
        return todoRepository.save(todo)
    }

    @Transactional
    fun update(id: Long, request: TodoRequest?): Todo {
        checkNotNull(request) { "TodoRequest is null" }
        return findById(id).let {
            it.update(request.title, request.description, request.done)
            todoRepository.save(it)
        }
    }
    fun delete(id: Long) = todoRepository.deleteById(id)
}
  • Optional로 처리했던 기존 JAVA 코드를 코틀린 언어적인 문법에서 처리할 수 있다(더 이상 Optional을 사용할 필요가 없다)
    • 확장 함수로 기존에 Optional로 제공이 되었던 함수를 null을 반환하도록 CRUDRepository에서 제공하고 있다.
  • checkNotNull 함수 이후부터는 컴파일러가 해당 변수가 더 이상 null이 아님을 알 수 있기 때문에, 이후 코드부터는 ?연산자가 필요가 없다.
  • update에서는 let함수를 사용해 함수형 프로그래밍으로 코드를 작성한다.
728x90