-3

Here is my issue, and I'm surprised to not have found it asked before. Essentially, in faked code, here is my situation:

try
{
    User user = currentUser(); //Throws UnauthenticatedException if not logged in.
    //Do stuff with the user.
}
catch (UnauthenticatedException e)
{
    //Do nothing, it's perfectly fine to not do the above code
    //if the user isn't logged in.
}

I'm not asking about how to handle this specific situation really, I just thought an example would be helpful. My general question is, is there an elegant way to handle cases where an Exception being thrown warrants no further action? That empty catch block hurts my brain to think about, it's so inelegant.

Tim M.
  • 518
  • 4
  • 15
  • 2
    If you use exception for program flow, then a `try-catch` statement is required. Either don't use exception for program flow, or soak your brain in aloe to soothe it. See "[Why not use exceptions as regular flow of control?](https://stackoverflow.com/q/729379/5221149)" and "[Are exceptions as control flow considered a serious antipattern? If so, Why?](https://softwareengineering.stackexchange.com/q/189222/202153)" – Andreas Jul 21 '17 at 18:32
  • My question wasn't meant to be "What is bad about this avowedly bad code?", it was "What is a better alternative to this avowedly bad code?". – Tim M. Jul 21 '17 at 18:41
  • That being said, the situation which triggered my asking of this question was a result of me misunderstanding the `currentUser()` method. The reason it throws an `UnauthenticatedException` if the user isn't logged in is that it should never be called when the user isn't logged in, and that would typically be the case for any time a method throws an exception, so I suppose I'll delete this question as I don't really know when it would ever be useful. – Tim M. Jul 21 '17 at 18:46
  • Or rather, I guess I will leave it alone, so that if someone else is confused by the same thing I was, maybe this can help them out. – Tim M. Jul 21 '17 at 18:52
  • I flagged this question as "Primarily opinion based," which is evident based on the opposing answers. This question may be a better fit on "code review" stack exchange and perhaps warrants a move rather than a close, though even there it will still be primarily opinion based and is an argument-worthy (and indeed, argument-generating) topic. – Loduwijk Jul 24 '17 at 13:00
  • @Aaron, Honestly, is there really any value to this question? The StackOverflow message when I first tried to delete it scared me away from doing so, but I'm not opposed to deleting it necessarily. It really probably isn't useful. – Tim M. Jul 24 '17 at 13:05
  • Actually, I can't delete it, which is too bad. I honestly think now that it is a useless question. – Tim M. Jul 24 '17 at 13:13
  • "Any value?" Yes, there is value. The arguments that this topic often generates are valuable if debated properly, as it is controversial. However, StackOverflow is not for that type of thing, and anyone stumbling onto your answer may take that as _*the*_ answer and say "Oh no, I'm doing it wrong!" Code review SE necessarily has a higher tolerance of opinion-based Q&A by definition, so it is a better fit there - even so, it may spark a fire there as well. Still, if it's left it should at least be migrated. – Loduwijk Jul 24 '17 at 13:15
  • In fact, at Code Review StackExchange, if it is well enough received and does not spark negative arguments about the uses and merits of exception-handling, then it may well even be taken as a good question, get back into positive score, and leave you happier with the response. – Loduwijk Jul 24 '17 at 13:19
  • Fair enough, I suppose the actual question posed has potential value if it can be separated from my specific situation. In my situation this question would not help, but there probably are times when you may not want to perform any action to handle an exception, which is what my question generally asked. I suspect the true answer to my question, as it was asked, is "no, if a checked exception can be thrown, you always have to catch it", but it may as well be debated. I do hope it gets moved off of StackOverflow, though, it doesn't belong here. – Tim M. Jul 24 '17 at 13:33
  • Can somebody please close this question? I didn't think it through enough before asking it. Its only real value now is in people seeing it and possibly realizing that they also didn't think their respective situations through, or by proxy, as a ground for debate over error handling for control flow, which it really shouldn't be. It has no business being an active question, and I'm tired of still being downvoted over a bad question I shouldn't have asked, which I learned my lesson about half a year ago. – Tim M. Feb 06 '18 at 19:40

5 Answers5

1

It is pretty simple: situations where you really do want an empty catch block are almost non existent!

Take your example: if login fails... 10 times - don't you think your code should do something about that? So instead of having an empty catch you could

  • log the failure so you later understand when and how often that user attempted to log in
  • count failures (for example to suspend that user at some point)
  • and most obvious - don't you think you should provide a meaningful message to the user

Even if your code is just an example - as you can see it is super easy to come up with arguments against having that empty catch!

Beyond that: when an operation is fine to fail - is it really appropriate to throw an exception then?! Meaning: when that empty catch is possible - why is the code designed to throw at all? What is the point of throwing when catching seems pointless?

GhostCat
  • 127,190
  • 21
  • 146
  • 218
  • Thanks for the comprehensive answer. Actually, I did truly not want to handle the Exception, because the method I was calling didn't trigger a login, it only fetched the authenticated user. – Tim M. Jul 21 '17 at 18:48
  • The obvious problem being if there was no authenticated user, there would be nothing to return, thus the exception. – Tim M. Jul 21 '17 at 18:49
  • And thus the two downvotes on the question, because it turns out I was using the method wrong and it's kind of a dumb question. – Tim M. Jul 21 '17 at 18:49
  • Glad you liked it. Although it is going in an probably unwanted direction - is there anything I can do to make my answer upvote worthy? As I a need just one more to hit the daily limit :-) – GhostCat Jul 21 '17 at 18:50
  • Sometimes even strange questions lead to interesting thoughts. – GhostCat Jul 21 '17 at 18:51
0

Probably, you can add a method to currentUser returning a boolean like this:

currentUser.isLogged()

You can also return null if there is no current user, so testing the user instead of catching exception

JFPicard
  • 4,659
  • 3
  • 16
  • 38
0

You can throw the Exception. However if the user is not logged in the exception will be thrown and the program will end.

public void valid() throws UnauthenticatedException{
    User user = currentUser(); //Throws UnauthenticatedException if not logged in.
}

Normally, Exceptions should be thrown from a method when that method is incapable of resolving the exception on its own.

For the sake of "Elegant Code" this method looks better but may not have the desired out come you want. When it comes down to it, just warm up to try and catching :-)

Ryan
  • 1,979
  • 2
  • 20
  • 34
0

The empty catch is fine. They are not usually empty, but it is fine for them to be so. It is not uncommon for exceptions to make better control flow than if statements. In fact, that was the reason exceptions were introduced in the first place, to collect your error handling into a better location. Before exceptions, it could get quite messy, especially if you had to jump stack frames.

Take the following example:

public void mainLoop()
{
    while(true)
    {
        try
        {
            Thread.sleep(1000);
            f();
        }
        catch (InterruptedException ex)
        {
            // Don't care; this thread expected to not die when interrupted
        }
    }
}

Sometimes, that really is the best way to handle it.

And as for the "exceptions should not be used for control flow" argument...

Also, sometimes it is convenient to collect all of what you consider your error cases to be into one place, and if they all share the same logic then you can even use a multi-catch.

public void verifyInput()
{
    try
    {
        int n = Integer.parseInt( txtInput.getText() );

        if(n < minimum || n > maximum)
            throw new MyDataInvalidException("data out of bounds");

        sendFormData();
    }
    catch (NumberFormatException | MyDataInvalidException ex)
    {
        // Don't care. Each widget on the form is already set up to display
        //   information about invalid input, so if you press "enter" in
        //   this state just ignore it
    }
}

Now, the above code sample has the added benefit that if, later on, you get a new requirement to handle bad input differently, you can maintain this quickly and easily.

For example, you get complaints that each GUI widget showing its invalid state is not enough, "Please, if I press enter show me a dialog with 'Invalid data: please check all fields.' to let me know I need to scroll up to see the text field's "X blah blah error message"" Now you just replace that comment with a message box popup, perhaps.

Or, if it needs to be handled higher up the stack, change verifyInput to use throws.

Loduwijk
  • 1,852
  • 1
  • 15
  • 26
-3

Answering my own question here, to explain how I misunderstood, and hopefully if others misunderstand in the same way this will set them straight.

The very reason exceptions get thrown is that if you encounter them, your program has done something that should not have happened. In my case, I was accessing the current user and attempting to basically use the error as the false case of if (user is logged in), which was completely at odds with the design of the method. The method threw an error if no user was logged in because it was specifically designed to never be called if the user wasn't logged in.

The true solution to the issue, at the very least in my case, and, I suspect, in the case of many others who are trying to do what I was doing before I realized the problem, is "Don't do that." Just use the method as it was intended, don't try to hack it.

Tim M.
  • 518
  • 4
  • 15
  • You have provided no evidence to suggest (especially not in the question) that this is "at odds with the design" or "designed to never be called if..." or that it was being used not as intended. The idea to never use exceptions for normal control flow and only use them for serious, unforeseen failures is one that some people share but which is certainly _*NOT*_ accepted as an industry best practice. Many of us will tell you that using exceptions for control flow is fine. – Loduwijk Jul 21 '17 at 19:39
  • @Aaron I've worked with proponents of Exception-Driven Development and it's been a huge headache. It adds a whole new layer of complexity to code analysis, usually unnecessarily. – shmosel Jul 21 '17 at 19:57
  • @shmosel I do not know why you would think it increases complexity; it is just another (and sometimes better) way to handle errors, and errors need not always be fatal. I have worked with "don't use exceptions except for fatal errors" proponents and *that* has been a huge headache. It's annoying when someone says "Don't catch NumberFormatException; create a regex that matches number format and check" because that not only reduces readability, it also degrades maintainability: maybe your regex doesn't match `Integer.parseInt` perfectly (maybe it did but doesn't now), where to store regex, etc. – Loduwijk Jul 21 '17 at 20:18
  • @Aaron, my fault for not wording it right in the question I guess. I didn't mean you should only use exceptions for fatal errors in general. When I said "has done something that should not have happened", I meant "something irregular has happened". That covers situations like invalid user input, there's no problem with catching a NumberFormatException. My point was that Exceptions aren't designed to be used the way I postulated in my question, as a glorified "if". It seems to me that any time you have an empty catch statement, you could probably find a better way to accomplish your task. – Tim M. Jul 21 '17 at 22:17
  • As to how I know I was using the method incorrectly, that's sort of self-evident from the problem I was having. The reason my code was coming across as convoluted was because it was being incorrectly used. The method was named `currentUser` because it was designed to provide the currently authenticated user, and nothing more. There was never any reason for me to think I could always reliably determine whether a user was logged in based on Exceptions, because the method never claimed to have that functionality. – Tim M. Jul 21 '17 at 22:27
  • And if that doesn't convince you about the correct way to use the method, I can still absolutely confirm it, because I actually wrote the method myself some time ago, and it struck me after I'd written this question that I'd disregarded my own purpose of the original method when I'd implemented it in this way. – Tim M. Jul 21 '17 at 22:29