Jump to content
  • Advertisement
Sign in to follow this  
justkevin

[java] Choosing an exception to throw

This topic is 3211 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

In my game, a map is a large but finite 2D space where game entities exist. If an entity leaves the legitimate boundaries of the map an exception should be thrown. Maybe the entity gets destroyed, maybe it gets wrapped around to the far side, I haven't decided yet. Question: What kind of Exception should it throw? I'm currently throwing a custom IllegalPositionException that extends Exception, but adds no functionality. This lets the code that handles movement specifically deal with this type of exception, but somehow creating a subclass with no code seems a bit... wrong. What would you throw, and more generally, how do you decide what kind of Exceptions to throw?

Share this post


Link to post
Share on other sites
Advertisement
This strikes me as a really bad use of exceptions. For starters, the situation is in no way unexpected to occur: the map size is finite, and units will exceed the map boundaries on a regular basis. For another thing, you really don't want stack unwinding in the middle of your update loop.

Consider implementing a callback or observer instead, to notify the controlling system if a unit exits the map.

Share this post


Link to post
Share on other sites
In the design, wandering off the map is possible, but still would be an unusual condition. The game is set in space and the map represents where all the interesting stuff is and then some. But if someone turns on the afterburners and goes to bed, eventually they're going off the map. Even if there were no map, their coordinates would either have an integer overflow or reach a point where floats/doubles provided insufficient resolution.

So with that in mind, would you still say that exceptions are bad here?

Share this post


Link to post
Share on other sites
How is the caller going to handle this error? What can it do when it catches the exception?

A better idea might be to compromise. Yes, this situation can present itself, but its unusual so no need to work hard to handle it. For example, you could simply clamp the players position to the map boundary, preventing them escaping. Another option would be to slow them as the reach the boundary, again this will prevent escape. Or let integer under/over flow teleport the player =)

Share this post


Link to post
Share on other sites
There are several ways to handle the situation, but I'm not overly fixated on that at the moment. Rather, I thought this was a good concrete example of a question I have about exceptions: It's an exceptional case, the method will be unable to fill its contract unless I change the contract, and it's something that can be recovered from.

Of course, "This is not an appropriate usage of exceptions" may still be a valid answer. I think swiftcoder's objection was primarily based on performance concerns, but if people still feel that throwing an exception here is bad, I'd like to know it (and why).

Share this post


Link to post
Share on other sites
I don't feel this is a good use of exceptions, because the subsystem responsible for doing the throwing could just as well (correctly) handle the situation itself, and thus shouldn't need to throw it. Exceptions here would just be an abusive method of flow control.

Share this post


Link to post
Share on other sites
I also agree with what others have said. This is a case for either ignoring it or handling it yourself. It might be an unusual state for the player, but it's a completely normal state for your program. I would use exceptions (which are about as heavyweight an operation as we have in Java) only when there is some unusual state in the program itself, more so if it cannot be dealt with adequately. The most frequent case is acessing resources external to your program, like a game server or a data file. And in those cases, since I can't recover even with user input, this being a game, I usually throw a custom RuntimeException - whether this itself is acceptable practice is questionable, though.

Share this post


Link to post
Share on other sites
It seemed like a good case to throw an exception for the reasons I listed, but since several people have shot it down and no one has agreed, I'll assume I'm wrong.

Since my main reason for asking (and I'm glad I did) was to improve my usage and understanding of Java exceptions, can you give an example of a scenario where you would throw a checked exception?

Share this post


Link to post
Share on other sites
Operations on an object should not invalidate class invariants. In this case, class should be designed so that object cannot fall outside of bounds, either via bounds check or through wrapping - it simplifies management a lot.

If a class invariant cannot be preserved, an exception could be thrown. If, for example, you allowed user to place a unit on map, and the coordinates are invalid, that would violate class invariant, with map class unable to solve it.

At the same time, the are more robust or simpler ways to handle the whole problem. One is to have a method boolean add(int x, int y, Unit u), which returns false if coordinates are invalid. This makes sense, since result of operation is well known in advance.

Exceptions in general can be problematic since they often indicate the program, or large part of it cannot continue. If you load the map from file, and a unit coordinate is invalid - what now? User cannot do anything. Throwing an exception would cause the map to fail to load, which might be desirable. What if map class can adjust the position, how would it do that? Simply pick a random location? Edge of the map? What if that puts your crucial unit into enemy base, causing you to lose the game in two seconds.

But what if such an exception is thrown? What could the caller of the method do more than map class itself could?

One way is to use spawn points. Instead of placing units on map, define set of spawn points. When a new unit is needed, use Unit u = spawn.get(i).makeUnit(). This leaves map free to adjust the location as needed. Of course, then you merely need to make sure that spawners are always valid, but that can be done by designating map tiles to act as spawners, making them implicitly valid - a tile can never be outside of map, solving the problem of invalid map as well.

The problem with Java's standard library is simply that it loves exceptions and throws them all over the place, even if not needed. While not a problem in itself, it does set a bad precedent.

Share this post


Link to post
Share on other sites
Quote:
Original post by justkevin
can you give an example of a scenario where you would throw a checked exception?

For instance, you are writing a parser for your own binary file format but it fails because the file is malformed or whatever. I think working with external resources would be one of the few times you might want to throw (or catch) one, but if there's never gonna be anyone higher up the hierarchy who can do something meaningful to recover, then there's not really any point to it. One thing you can do is let the unchecked exceptions bubble up (or, like I do, if it's fatal, catch the checked exception and re-throw as unchecked) to the top, where you log them and exit gracefully (or try to).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!