5
\$\begingroup\$

I have something like that:

  1. My custom exception class:

    public class SolvableException extends RuntimeException {
    
        protected boolean solved = false;
    
        public SolvableException(String message) {
            super(message);
        }
    
        public void setSolved() {
            this.solved = true;
        }
    
        public boolean isSolved() {
            return this.solved;
        }
    }
    
  2. Class for some very specific calculations which in some unpredictable cases throws my exception:

    class VerySpecificCalculator {
        public void makeSomeSpecificCalculations(double someParameter){
            // make some actions...
            // Now I have to make some specific calculations, but sth wrong happend and I do know what to do with it in this place...
            throw new SolvableException("Something wrong happend... Problem with XYZ");
        }
    }
    
  3. My very specific calculator is used in other class and provides some part of its logic:

    class Calculator {
        public void makeSomeCalculations(double someParameter){
            // Some variuos calculations...
            VerySpecificCalculator calc = new VerySpecificCalculator();
            try {
                calc.makeSomeSpecificCalculations(4.34);
            } catch (SolvableException e){
                // I know what to do here, so I'm fixing a bug on this level:
                // some fixing code, some rollback whatever...
                e.setSolved();
                // But I want to inform, that the fixing process took place...
                throw e;
            }
        }
    }
    
  4. I use the entire stuff as follows:

    class Test {
        public static void main(String[] args) {
            Calculator calculator = new Calculator();
            try {
                calculator.makeSomeCalculations(344.47);
            }catch (SolvableException e){
                if(e.solved){
                    System.out.println("Ok, there was a problem but it has been solved... You can display some JOptionPane to inform a user if you want...");
                } else {
                    System.out.println("Buuu, there was a problem an it's still not solved... Action is interrupted ");
                    return;
                }
            }
        }
    }
    

Is this approach reasonable? I mean, is it ok to rethrow an exception if the problem has been already solved, and rethrowing plays only some informative role like in my example?

Let's consider such a situation (without rethrowing):

public void f(){
        try {
            methodCausingException();
        } catch (SolvableException e) {
            // fixing code...
        }
        //
        // Code executed when problem is fixed...
        //
    }

But with rethrowing I need to duplicate my code:

public void f(){
        try {
            methodCausingException();
        } catch (SolvableException e) {
            // fixing code...
            e.setSolved();
            //
            // Code executed when problem is fixed...
            //
            throw e;
        }
        //
        // Code executed when problem is fixed...
        //
    }

I can use a finally block, but I don't find this place as good for business logic code.

\$\endgroup\$
7
\$\begingroup\$

Especially if you expect these exceptions to occur (relatively) often, I think that using exceptions is a bad idea here. Exceptions should not be used for regular flow of control, this applies to Java as well. Creating and throwing exceptions is among the most costly operations there is in many programming languages.

One comment especially that caught my attention was: "Now I have to make some specific calculations, but sth wrong happend and I do know what to do with it in this place..." If you know what to do with it, then why are you throwing an exception? If you look in the dictionary an exception is:

special case, departure, freak, anomaly, inconsistency, deviation, quirk, oddity, peculiarity, irregularity" (+ exclusion, omission, objection).

Is your case really an anomaly? (Doesn't sound like it but I can't make this decision for you)

Instead, consider creating a CalculationResult class, which can be returned from your methods. The class can contain your solved variable (possibly among other things). Then when a method has returned a CalculationResult to it's caller, you can read the CalculationResult and decide what to do with it.

\$\endgroup\$
  • \$\begingroup\$ Being more specific: The problem causing an exception is solved deep in the model... Simply if some values are to high, they are reduced apropriately. But I want to inform about the fact of reducing some values in the view layer. That's why I'm rethrowing an exception with flag "solved". I know that it is probably not a perfect solution... I need simply something like that in this case... I do not want to show message dialogs in model layer (I'm working with swing). I consider your solution as well, thanks. \$\endgroup\$ – guitar_freak Nov 26 '13 at 12:11
  • \$\begingroup\$ @guitar_freak Then it sounds like you should pass the CalculationResult to the view. Rethrowing exceptions itself is OK, but I don't think you should use exceptions here. If some values are too high, then modify them without throwing an exception - just change some information in the CalculationResult. \$\endgroup\$ – Simon Forsberg Nov 26 '13 at 12:18
  • \$\begingroup\$ Other than that, you can alternatively Log a Warning, in case you have some logging mechanism in place ;) \$\endgroup\$ – Vogel612 May 12 '14 at 19:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.