samba
samba

Reputation: 3091

What is a better way to handle a RuntimeException in a method?

I've heard that it's not always a good practice to handle runtime exceptions. I've implemented a method that takes a product rating as an argument and if the current product object has this rating, it returns a ProductDTO object. The only way I found to make the method work as expected is with the use of a Runtime exception. But according to Joshua Bloch it is a very bad idea to use exceptions for control flow.

Is there a way to improve the logic of the method?

public ProductDTO findByRating(int productRating) {
    ProductDTO productDTO = new ProductDTO();
    if (productRating == this.avgRating()) {
        productDTO.setProductName(productName);
        productDTO.setProductsLeftForSale(productsLeftForSale());
        productDTO.setAvgRating(avgRating());
        productDTO.setTotalVotes(reviews.size());
        return productDTO;
    } else {
        throw new RuntimeException(String.format("No Product found with the rating: %s", productRating));
    }
}

.

List<ProductDTO> productDTOList = new ArrayList<>();    
        int rating = 5;
        for (BaseProduct product : products) {
            try {
                ProductDTO productDTO = product.findByRating(rating);
                if (productDTO != null) {
                    productDTOList.add(productDTO);
                }
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }

Upvotes: 0

Views: 78

Answers (1)

sergey
sergey

Reputation: 498

Maybe it looks a little better:

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

...

public Optional<ProductDTO> findByRating(int rating) {
    return this.avgRating() == rating ? Optional.of(createDTO()) : Optional.empty();
}

private ProductDTO createDTO() {
    ProductDTO productDTO = new ProductDTO();
    productDTO.setProductName(productName);
    productDTO.setProductsLeftForSale(productsLeftForSale());
    productDTO.setAvgRating(avgRating());
    productDTO.setTotalVotes(reviews.size());
    return productDTO;
}

public List<ProductDTO> findProductsByRating(int rating) {
    return products.stream()
            .map(product -> product.findByRating(rating))
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collectors.toList());
}

Upvotes: 2

Related Questions