The right usage of exception throwing

Hey there,

I’ve got a question about exception throwing (c#). I’m working on a multiplayer game right now, and I’m trying to clean up my code right now / make it more maintainable. My question now is, if it is appropriate to use exceptions for problems that can occur more often. For example, if a user wants to log in. What code would be more appropriate:

Version 1:

public string LogIn(int playerID) {
  if(players.Contains(playerID) {
    players[playerID].LoggedIn = true;
    return "Player logged in";
}
  return "Player not found";
}

Version2:

public void LogIn(int playerID) {
  if(players.Contains(playerID) {
    players[playerID].LoggedIn = true;
  } else {
    throw new ApplicationException("Player not found");
  }
}

Simple example, but I think it illustrates my problem rather well. Consider, that the user has control over the input, so he/she can alter the data sent to the sever. Is it in this case valid to throw an exception. And how about a method, which communicates with the client, but the user has no influence of the input, so an exception would only be thrown, if the client is outdated, or someone tries to penetrate the system with their own created messages.

What’s best practice here?

Best regards
Johannes

The key is in the word itself - Exception.

Only use them for exceptional circumstances. e.g.: This value should never be null, but I’m going to check it anyway because I might have made a stupid mistake, and if it is null? Exception.
In your example, I wouldn’t make it an exception. Why? Because people mistype stuff all the time. You expect it to happen. So it’s not exceptional.

Some other thoughts:

  • User input and associated checks should never generate an exception, because cats walk across keyboards all the time.
  • Networks go down all the time, no exceptions when they do. You should plan for it and recover from it.
  • Malformed packets could be a sign of network issues, or someone trying to penetrate. I don’t know if I’d throw an exception as much as I’d just throw it out and ignore it.

Note that these rules are what I would use in Game development. At my day job where I write web apps, I throw exceptions for someone sneezing too loud. :slight_smile:

3 Likes

You can throw exceptions for this. Just make sure you catch them.

According to the docs an exception should be thrown if a class can’t successfully do what it was designed to do.

For a log in screen performance is hardly going to matter.

1 Like

I am going to advise against using exceptions to control your flow of logic, which is something you are basically doing. You should not throw an exception during validation of user input. You specifically have designed the system to allow users to input whatever they want, so you should be able to naturally handle whatever the user types into there (without exceptions).

Exceptions should be used to handle the cases you do not anticipate. Their purpose is to gracefully recover from the unexpected error (so your application does’t just crash), and provide you with the means of debugging the error (Stack traces!). Exceptions should not be a regular occurrence in your program at all.

Thank you for your valuable inputs!

I thought, that exceptions would be convenient way of transporting more information. For example, if the Login Function should also check the password, it would be possible to tell whether the player logged in or not, and also receive a string with a message for the user. But I guess it is cleaner to return a Class with a string and a boolean if it was successful.
I agree with you, BoredMormon, the performance isn’t really the issue here, I’m looking more for maintainable clean code.

I’m still not sure about the methods where the user doesn’t have influence over (or only with altered packages). My gut tells me, that they should throw an exception, but on the other hand it would be also just fine to use Debug.LogWarning to get information about the problem.

Warnings should be for things that don’t actually break your code. Things like you are using an old version of a method. Or there is an argument missing, I’m going to give it a default value.

If your code can’t continue at all then it’s a justification for an exception.

The advice that an invalid login is part of normal code flow, and not exceptional, is probably good.

Right, but I can build methods in a way, that they don’t try to handle anything except the normal case, and otherwise they throw exceptions. That’s mostly the way I’m used to from Java and my computer science studies. It also doesn’t break the code, if the exception handling is done right. The other way is to handle altering cases in the method itself… I guess it is just a different paradigm on how to build code.

Anyway, it seems to me, like c#, other than java, uses the paradigm to handle altering cases in the method itself. I assume this due to the missing “throws” information in the method head. Am I right with the assumption or is it that game development differs from normal software development? I just don’t want to adopt to wrong paradigms.

Most of my advice is from a game vs non-game perspective. In a game engine a lot of your code could end up being called during the primary game loop. Throwing and catching exceptions in that context is a lot of wasted cycles. Just return an error value if you want to notify the caller. Liberally throwing exceptions is fine for a web app or a desktop CRUD-based enterprise app, but I try to avoid them except in extreme circumstances when working on a game.

2 Likes

Valid point, thanks for the explanation! I guess this is sufficient for me, thank you all for taking the time to share your thoughts :slight_smile: