SFML community forums

General => General discussions => Topic started by: zorexx on March 31, 2012, 11:37:25 am

Title: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on March 31, 2012, 11:37:25 am
Hello everyone,

Since SFML 2 will be released soon, and with the change in the naming convention, I thought this would be a good time to update all my 3 SFML projects - SFMLTheora, sfMod, and sfMidi.

Of course, I will have to change the code to reflect the changes in SFML 2, I will also change my naming convention to follow SFML2.

Aside from that, there are few changes I'm considering, mostly general stuffs which has nothing specific to any of the 3 libraries.


1. Exception handling:
I used to hate these try-catch stuffs since they were a hassle and can get really messy and meddlesome at times, but recently after programming in C# and Java, I find that they aren't that bad at all, and can be really handy at times.

Currently, the 3 libraries handle errors by simply returning false. I've definitely faced some design problems since constructors can't have a return value, but those were somewhat solved without much problem. (I did know that exceptions could easily solve my problem, but as I mentioned above, I didn't like exceptions at that time).

The drawback to this is that I can't get more info on the error (i.e. why it failed). While this may not be a problem for most case, I do think it will prove to be very useful for debugging purposes. (I debug by placing std::cout<<123 or std::cout<<"lol"; at suspicious places all this time  ;))

I'm not too sure about this, but with exceptions, the code on the user-end would probably look much cleaner and organized (at least I hope it will be).
However, it will also, at the same time, make your code longer:
Code: [Select]
if (!vid.Load("video.ogg"))
  return 1;
will become
Code: [Select]
try {
  vid.Load("video.ogg")
}
catch (exception ex) {
  // handle exception
}

So, tell me which do you prefer (and would like to see in the next version of the 3 libraries above, as well as any future SFML projects I may write) by voting above, and if possible, tell me your reasons, or at least say something about it.  :D


2. Namespace
Currently, the namespaces I use for each projects are their respective project names, SFMLTheora for SFMLTheora, sfMod for sfMod, sfMidi for sfMidi.

I've been thinking of changing SFMLTheora to something shorter, and might as well shorten the other 2 as well (or are they good enough as is?)

Here are what I currently have in mind:
- sfth for SFMLTheora
- sfmo for sfMod
- sfmi for sfMidi

Another alternative for sfMod and sfMidi would be sfmod and sfmidi respectively, which do you prefer?

Edit: Another suggestion by Nexus for the namespace of SFMLTheora: sftheora
If I decide to go with sftheora, I will most probably change the project name to sfTheora as well, to match the namespace and the other 2 libraries.

It would be great if I can hear some opinions on this as well, especially for sfmo and sfmi.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: eXpl0it3r on March 31, 2012, 11:53:25 am
I'm still not convinced by exceptions so I'd vote against them.
And shorter namespaces are always appreciated!  :)
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Nexus on March 31, 2012, 12:05:40 pm
If using exception means that every call that might throw is surrounded by try-catch, the concept is misunderstood. Exceptions are great precisely because they needn't be handled directly but can be propagated to a higher-level function instead. That is, a function might load several videos just like this:
video1.load(...);
video2.load(...);
video3.load(...);
And in another function there is a try-catch clause. If you derive your exceptions from std::runtime_error, one can even abstract this away and check for general errors.

But error codes also a possibility if you want your library to be similar to SFML in terms of usability. But as you mention, it's difficult to specify more about the error. SFML uses the sf::err() stream to output error description. However that's only suitable for debugging purposes, you cannot react on a specific error.

Concerning the namespace, I think sfmod and sfmidi are okay, for SFMLTheora an option might also be sftheora (it's still long, but better than SFMLTheora, also because of the case). But as I'm currently also having a namespace problem (http://en.sfml-dev.org/forums/index.php?topic=7330.msg48459#msg48459), I'm probably not the best to give advice :P
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on March 31, 2012, 12:17:13 pm
Thanks for your opinions.

@eXpl0it3r: Is there any specific reason that you're not convinced by exceptions?


@Nexus: Regarding the exception issue, yes, that's the main benefit I was trying to explain (but failed to >.<).
Rather than having to make sure everything is alright after each load call or constructor, I can just throw them all into a try block and handle any exceptions in the catch block(s).

Thanks for your suggestion on sftheora, I'll add it to the first post, I guess if I were to choose sftheora, I might as well just change the project name to sfTheora to match sfMod and sfMidi.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Klaim on March 31, 2012, 01:00:20 pm
I good way to make everyone happy:

 - use exceptions
 - have a macro that deactivate the throws, assert & crash instead
 - have an other macro that deactivate the asserts and do nothing but return.

Also, as you should use exception only in cases that are really impossible to handle in your code, not because you need to provide some infos that somethnig is not possible to do, then I assume that some functions will return some kind of state, while some exceptions might occur in some really hard cases.

So, allowing to turn exception off, is useful only if you need the extra boost in performance and don't wish to manage the exceptions anyway. In this case, assertions are far more helpful.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on April 01, 2012, 04:15:40 pm
Currently, after thinking about it and doing some little research on exceptions (C++ exceptions, and also usage in games/real-time application), I'm leaning towards returning a boolean value now.

The 3 main reasons are the (slight) performance overhead, troubles with RAII, and majority of the people (working with games) don't favor exceptions.

About the RAII, just in case it may sound confusing, I meant that, if I were to allow everything to be loaded in the constructor (which will be made possible with the next version to make things even simpler than it already is), and decide to use exceptions at the same time, I will end up having to force the end-user to put everything that reference to the video in a try-catch block, or use the heap.

So for now, unless someone convinces me to do otherwise, I will return false in case of any error, and set an error string, which will be accessible with getError().
I will also provide another function, hasError(), to make things look cleaner, basically what hasError() does is just check if the error string is empty or not.
clearError() will allow the user to clear the error string in case if the user decides that there is no need to terminate the application or delete the instance, and will reuse the same instance.
This way, the constructor problem is automatically solved, call the constructor with the filename as a parameter, and check if the video is loaded properly later with hasError().  :D

Thanks for all your opinions and votes.  :)
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Nexus on April 01, 2012, 04:38:53 pm
(slight) performance overhead
In exceptional situations, performance is usually not important.

majority of the people (working with games) don't favor exceptions.
Is that true? I'd like to learn about the backgrounds, have you read that somewhere or is it rather your general impression?

About the RAII, just in case it may sound confusing, I meant that, if I were to allow everything to be loaded in the constructor [...], and decide to use exceptions at the same time, I will end up having to force the end-user to put everything that reference to the video in a try-catch block, or use the heap.
I don't understand that, why does one need the heap? I see however that exceptions make it more difficult to ignore a loading failure and to continue the normal program flow -- but that's by design (you must react and can't accidentally ignore an error). Whether you see that as advantage or disadvantage depends on the expected use cases of your library.

This way, the constructor problem is automatically solved, call the constructor with the filename as a parameter, and check if the video is loaded properly later with hasError().  :D
The problem with this approach is that you have objects which aren't operational. You can't rely on a valid object state, which makes ugly validity checks necessary. And you need to define semantics for an unloaded object -- what should video.play() do if it the video has not been loaded?

The additional issue with hasError() is, that it has global state and needs to be invoked directly after each constructor in order to find out which one failed. Same with getError(), it only reports the last error.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on April 01, 2012, 05:43:31 pm
majority of the people (working with games) don't favor exceptions.
Is that true? I'd like to learn about the backgrounds, have you read that somewhere or is it rather your general impression?

I've read it in various places, you can google c++ exception handling in games.
The results, of course, consists of those who support that idea, and those who are against that idea.
And after reading those, especially the discussion-types (rather than articles), I find that most people seem to recommend against using it (for my situation).

Also, most libraries I've came across with don't use exceptions, so maybe there's a bit of general impression in my statement above as well.

SFML doesn't use exceptions (for now), but if it does (SFML 3?), I will probably change mine to use it too, I will explain why below.

I don't understand that, why does one need the heap?
For example, this code:
sftheora::Video testVid("video.ogg");
if (sftheora::hasError())
  // Handle error
 
Will have to translate into either 1 of these 3 if I decided to use exceptions:
try {
  sftheora::Video testVid("video.ogg");

  // Main loop << Forces user to put main loop here
}
catch (exception) {
  // Handle exception
}
 
or
sftheora::Video* testVid;

try {
  testVid = new sftheora::Video("test.ogg"); // Forces user to use heap
}
catch (exception) {
  // Handle exception
}

// Rest of code
 
or
sftheora::Video testVid;

try {
  testVid.load("test.ogg");
}
catch (exception) {
  // Handle exception
}
 

However, if Laurent decides to use exceptions for SFML, I will switch to it as well, since if that's the case, the user will probably have most of his (initialization) code in try-catch blocks anyway, so I'll just make use of that.

The problem with this approach is that you have objects which aren't operational. You can't rely on a valid object state, which makes ugly validity checks necessary. And you need to define semantics for an unloaded object -- what should video.play() do if it the video has not been loaded?

The additional issue with hasError() is, that it has global state and needs to be invoked directly after each constructor in order to find out which one failed. Same with getError(), it only reports the last error.

Currently, I leave the responsibility of checking whether the object is valid after loading it to the user.
Just like if creating an object on the heap, if you don't null-check it and it unexpectedly returns a null (probably due to bad allocation), the program will crash (ugly, indeed).
I follow that "rule" as well, if you don't check if it's valid after loading it, you risk having your program crashed.

Also, hasError() does not have a global state, the error string is just another (private) variable of each instance. It is different from std::cerr or sf::err(). It is more like an optional explanation of what went wrong, in addition to the boolean value.
While it only reports the last error, why would you need it to report any other previous errors?
In exceptions, you only get the exception once, and that's it, it's the same for this, just that you have to manually clear the error if you decide to continue using that same instance.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Nexus on April 01, 2012, 06:11:07 pm
Thanks for the explanations!

As already mentioned, exceptions are the wrong approach if every call that might throw is directly surrounded by a try-catch clause. For that scenario, error codes are indeed the better choice. Exceptions are interesting because the loading code can be kept clean, while error handling is outsourced to a higher scope.

Just like if creating an object on the heap, if you don't null-check it and it unexpectedly returns a null (probably due to bad allocation), the program will crash (ugly, indeed).
Interestingly, new throws std::bad_alloc :)

But I understand what you mean. It might however occur often that new users forget to check for errors, since it's not clear that a constructor needs to be followed by a hasError() call. Unlike a bool load() function, which is a more widespread idiom (and also used in SFML). So you'll see who reads the documentation ;)

(By the way, I haven't voted)
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on April 01, 2012, 06:54:03 pm
As already mentioned, exceptions are the wrong approach if every call that might throw is directly surrounded by a try-catch clause.

Yeap, which is why I said I will most probably switch over to exceptions if Laurent decides to do so with SFML.

Interestingly, new throws std::bad_alloc :)

Yeah, I'm aware of that.  :)
I was trying to relate to the consequences of not null-checking - an ugly crash, which is what happens if you don't check the video for errors.

It might however occur often that new users forget to check for errors, since it's not clear that a constructor needs to be followed by a hasError() call. Unlike a bool load() function, which is a more widespread idiom (and also used in SFML). So you'll see who reads the documentation ;)

I agree on this, too.
Of course, I'm not omitting the load function, there will still be a bool load() function, I'm just making it possible to load directly from constructor to give the user a choice to do so.

I'll probably put both ways of loading a video in the "short tutorial", which will be shown on the project page (like how it is right now). It's pretty much the only thing that qualifies as a documentation for the projects as of now, maybe I should write a proper documentation of all the features, which aren't many actually.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Klaim on April 03, 2012, 02:12:32 pm
About exceptions forbidden in most video game industry shop, it's true. See my answer there : http://programmers.stackexchange.com/questions/113479/are-there-any-real-world-cases-for-c-without-exceptions/113481#113481


But I think indie game devs don't really care (if they don't target smartphones).
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on April 03, 2012, 05:43:52 pm
Wow, I actually read that before I decided to not use exception, didn't realize that was you.  :P
Well, thanks for your opinion.  ;D
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Silvah on April 04, 2012, 01:16:04 pm
(slight) performance overhead
In exceptional situations, performance is usually not important.
That's right, assuming you have zero-cost exceptions. If you don't - which is the case with most compilers on 32-bit Windows, GCC with DWARF2 unwinding is probably the only major compiler there that has zero-cost exceptions - you pay for using exceptions even in the hot path. And paying in the innermost loop for something not used anywhere (in a healthy program) stinks.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Nexus on April 04, 2012, 03:49:11 pm
Advocatus Diaboli, thanks for the addition.

Klaim and A.D., you're making an assumption that is wrong in my opinion, namely that the presence of exceptions implies bugs in the program. In my opinion, exceptions should mainly be used for runtime errors that are even possible at a correctly written program (e.g. user input, resource loading, ...), while assertions can be used for logic errors. And Klaim, you're also saying that exceptions require a complex error management strategy -- and error codes don't? It might be even more complex to implement for error codes because error handling needs to be part of the erroneous code itself, and the errors don't propagate automatically to a higher level function. Apart from that, some arguments are only relevant for consoles.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Rosme on April 04, 2012, 05:28:45 pm
(slight) performance overhead
In exceptional situations, performance is usually not important.
That's right, assuming you have zero-cost exceptions. If you don't - which is the case with most compilers on 32-bit Windows, GCC with DWARF2 unwinding is probably the only major compiler there that has zero-cost exceptions - you pay for using exceptions even in the hot path. And paying in the innermost loop for something not used anywhere (in a healthy program) stinks.
Or not, see here, no cost if no exception are being thrown. http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c#307716 (http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c#307716)
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Silvah on April 04, 2012, 08:01:43 pm
Klaim and A.D., you're making an assumption that is wrong in my opinion, namely that the presence of exceptions implies bugs in the program.
I don't make this assumption. A healthy program to me means a program that operates in an environment sane enough to never get into the error handling code path. As such, healthiness is more a property of a given run of a program in specified environment, rather than the program itself. Therefore, my point about the exceptional code never being used anywhere in a healthy program still stands.

Or not, see here, no cost if no exception are being thrown. http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c#307716 (http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c#307716)
You missed the point, the link you provided shows precisely the zero-cost exception handling I've been talking about.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Rosme on April 04, 2012, 08:18:26 pm
Then I read that wrong. Sorry!
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: zorexx on April 05, 2012, 08:30:03 am
Klaim and A.D., you're making an assumption that is wrong in my opinion, namely that the presence of exceptions implies bugs in the program.
I don't make this assumption. A healthy program to me means a program that operates in an environment sane enough to never get into the error handling code path. As such, healthiness is more a property of a given run of a program in specified environment, rather than the program itself. Therefore, my point about the exceptional code never being used anywhere in a healthy program still stands.

If, when you say error, you mean unexpected error, then yes, the program should never get into the error handling code path.

However, if you meant any error, then imagine this situation: At some point, you would like to let your user select a video to play, if he selects an invalid or corrupted file, and the program is unable to load it, there you go, an error.
Does this mean that it isn't a healthy program? I don't think so.
Imagine this situation: A user downloaded your program, which includes some data files, the user accidentally deleted 1 of the data file, your program tries to load it, and error. Is it the program's fault?

In conclusion, there are errors that we should "expect", or at least not assume that it won't happen, and this is where the error code vs exceptions come in.

On a side note: sfTheora, sfMidi, and sfMod have just been released, I went with "return boolean", along with an error string. You can retrieve the error string with a function, getError(), or check if there's any error with hasError(). Since it still returns false when it fails, the only time you really have to use get/hasError() (if you don't want any unhandled errors) is after the constructor.
Title: Re: Suggestions for SFMLTheora, sfMod, and sfMidi (Exceptions?)
Post by: Klaim on April 05, 2012, 03:14:22 pm
Nexus, In the link I didn't say it was my advice, but I precise that it's the reasons why the traditional game companies working with consoles forbid (or are not able to use) exceptions.
I partially agree with a lot of those reasons but I think it's a case by case basis so I do use exceptions as last resort "i don't know at all what to do here" error message, and most exceptions I handle I only log them.

But that's because I have control over the project, my projects are not cpu-bound (yet), and I'm targetting PC, not low-memory, poor latency consoles.

Now, people often say that if you compare error checking with exception, you will have the same cost, but it's beside the points: in most console games you MUST NOT have errors, you just have inputs that are predictable and you cannot allow any show-stopper problem to be perceptible by the user. The only way to do that is to have a "correct" applcation, that is really hard to do. So instead of havig the program checking errors, the programmers do it (with a QA) and the final result have no checking at all (on consoles at least).

Also, know that having exception does have a cost without even throwing anything in your program. That you want or no to pay the price of using exception is up to your specific case. When I have choice, I do, but on some hardware I can understand that it's a problem.


Finally, I suggested in the beginning of this thread to have some macro that allow the library both to provide exception and/or asserts. That way the user choose for his specific case.

Someone (I dont remember if it's in this thread or even in this forum) noticed that the new standard libraries does provide error checking as well as exceptions, because sometimes you want to check, sometimes you want to crash, and sometimes you want to never get in this case, even if it's possible.

Let the user choose. It's easy to do with macros actually.