RavinProject / ProjetoRavin

Projeto de aplicativo para controle de restaurante, utilizado para prática de desenvolvimento Java no Programa +Devs2Blu 2023
5 stars 0 forks source link

Exceção customizada: EntidadeNaoEncontradaException #34

Closed regis-amaral closed 1 year ago

regis-amaral commented 1 year ago

Métodos de classes que disparam intencionalmente a exceção NoSuchElementException devem declarar uma throws para que quem as chamar seja informado (o ideal era ser obrigado) a tratar a exceção:

Controller como deveria ser: Image

Interface como deveria ser: Image

Chamada do método atualmente: Image

Como a chamada deve ser tratada: Image

Precisamos ajustar isso na classe ClienteController e combinar de utilizarmos nas demais implementações de código que lançarem excessões sempre que um objeto não for encontrado;

Infelizmente a NoSuchElementException é uma exceção não verificada, o que não obrigada quem chamar o método a implementar o tratamento da exceção. Logo, o dev terá sempre que se lembrar, e isso não é o melhor cenário quando se sabe que uma exceção será lançada sempre que um objeto não for encontrado na pesquisa.

Exceções verificadas, as que obrigam o dev a implementar o tratamento ou repassar para frente usando throws, não podem ser lançadas como as não verificadas: throw new NoSuchElementException("...");

Minha sugestão seria criar uma exceção verificada para nosso caso em particular, exemplo:

public class FulanaException extends Exception {
    public FulanaException(String mensagem) {
        super(mensagem);
    }
}
tiagospeckart commented 1 year ago

Pelo que entendi do problema, bastaria implementar o throws NoSuchElementException no final de cada método das Interfaces de controllers que lidam com buscas de objetos individuais. Coisas como getById, getByName ou getByCodigo.

Assim a implementação da exceção fica obrigatória pelo contrato das interfaces com as Classes que as implementam.

Não entendi a necessidade da criação de classes novas para lidar com erros

regis-amaral commented 1 year ago

É que essa solução não é obrigatória, não deixa claro para o dev que ele deve tratar a excessão. Ela pode ser ignorada e acabar estourando na execução do programa como está acontecendo ao buscar por um cliente com cpf inexistente.

tiagospeckart commented 1 year ago

Como eu não tenho muita experiência com error handling, joguei pro Gepeto dar o seu parecer também. Segue a conversa pra referência:

https://chat.openai.com/share/2b55d53f-c2df-4f92-abf2-437cd3c7a0e6

Basicamente, explicou em outras palavras a sua solução, e consegui entender melhor o contexto. Gostei também da sugestão de nomear a Classe de erro de uma maneira mais abstrata, para que possa ser usada por vários Controllers diferentes.

Segue um trecho da conversa:


Por exemplo, você poderia criar uma exceção EntityNotFoundException, que poderia ser usada em qualquer método que busca uma entidade (como um Cliente, um Produto, etc.) e que pode não encontrar o que está procurando.

public class EntityNotFoundException extends Exception {
    public EntityNotFoundException(String message) {
        super(message);
    }
}

Então, em seus métodos de busca, você poderia lançar essa exceção quando uma entidade não for encontrada:

public Cliente getClienteById(int id) throws EntityNotFoundException {
    // Tenta encontrar o cliente
    // Se o cliente não for encontrado, lança a exceção
    if (!clienteRepository.existsById(id)) {
        throw new EntityNotFoundException("Cliente com ID " + id + " não encontrado.");
    }
    // Se o cliente for encontrado, o retorna
    return clienteRepository.findById(id);
}

Em qualquer lugar onde você chama getClienteById, você seria então obrigado a tratar a EntityNotFoundException.

try {
    Cliente cliente = getClienteById(123);
    // Faz algo com o cliente
} catch (EntityNotFoundException e) {
    // Faz algo em resposta à exceção (por exemplo, loga o erro e/ou retorna uma mensagem de erro ao usuário)
}
tiagospeckart commented 1 year ago
tiagospeckart commented 1 year ago

Classe já adotada na main, agora é preciso apenas garantir a sua adoção quando for apropriado

tiagospeckart commented 1 year ago

Enquanto estava testando algumas views, várias requisições de recursos, quando poderiam ser nulas, agora só estão lançando a Exception e interrompendo a execução do aplicativo:

Por exemplo, no CadastrarReservaView

public class CadastrarReservaView {
    static void cadastrarReserva(IReservaController reservaController, IClienteController clienteController, IMesaController mesaController) {
        Reserva reserva = new Reserva();
        Cliente cliente;
        try {
            String cpfCliente = solicitaEntradaDeDado("Informe o CPF do cliente:");
            cliente = clienteController.recuperarPorCpf(cpfCliente);
            if (cliente == null) {
                exibeDialogo("Cliente não encontrado! Vamos cadastrá-lo agora.");
                cadastrarCliente(clienteController);
                cliente = clienteController.recuperarPorCpf(cpfCliente);
                if (cliente == null) {
                    exibeDialogo("Ocorreu um erro ao tentar cadastrar o cliente. Tente novamente.");
                    return;
                }
            }

Quando tentei por uma rota de criação caso cliente fosse nulo, a Exception impossibilita esse tipo de feature Caused by: org.ravin.utils.exceptions.EntidadeNaoEncontradaException: Cliente não encontrado para o CPF: 3423

Proposta

Como em breve esse sistema irá se tornar uma API, e as Exceptions serão respostas HTTP, não precisamos redesenhar nossa lógica de Exceptions, mas por enquanto vamos ter isso em mente caso sejam criadas interfaces que possam lidar com valores nulos