Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Exceptions in SFML 3 ?  (Read 37110 times)

0 Members and 1 Guest are viewing this topic.

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Exceptions in SFML 3 ?
« Reply #30 on: October 14, 2013, 12:49:31 am »
We are getting rather distracted with the Image part of this, streams like for sound do add some complexity...hmm. I find it funny this was literally an aside-comment of mine, and it's turned into a debate alongside the exception one >.< Makes me feel guilty.

I definitely agree if any library did go this way, it would be useful to provide a facade to hide the complex innards that are unneeded for the basic use-cases. But I would expect that facade to need to be be nothing more than a few line long negotiator between the existing classes/functions.

I don't really see the problem with loadFromMemory/loadFromStream.  I never felt they were "straying from the way SFML wants you to do these things."

Yeah, I didn't like my wording of that so I removed it from the post right after I clicked "post" xD Guess you saw the old version >.<
« Last Edit: October 14, 2013, 12:54:49 am by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Exceptions in SFML 3 ?
« Reply #31 on: October 14, 2013, 12:52:36 am »
Here's another thought.

If you REALLY want lower level control than SFML gives you, shouldn't you be looking at the libraries that SFML is built on?  OpenGL, OpenAL, stb_image, etc?  If you want to muck around with stuff as low-level as manual memory management or adding your own decoders, it seems like you'd have to work with those libraries or reimplement parts of those libraries or better yet, submit your new decoders to those libraries (and use your own custom build for a little while until the patch makes it downstream).

I guess this doesn't apply for archive files, but for those you probably want to link some other library (doesn't 7zip allow that?), write a function to use it and then just use loadFromMemory.  Is there anything SFML could do to make that any simpler, other than adding some loadFromArchive functions?
« Last Edit: October 14, 2013, 12:55:56 am by Ixrec »

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: Exceptions in SFML 3 ?
« Reply #32 on: October 14, 2013, 12:55:57 am »
Correct me if I'm wrong, but the Music class seems the only thing that is really profiting from streaming. All other things including short sounds should be small enough they can easily be loaded at once and you can't use half an Image or half of a Font file or half of a Shader.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Exceptions in SFML 3 ?
« Reply #33 on: October 14, 2013, 12:59:45 am »
I'm pretty sure InputStream is never used unless you call loadFromStream, so I don't really see your point there.

Silvah

  • Guest
Re: Exceptions in SFML 3 ?
« Reply #34 on: October 14, 2013, 09:51:36 am »
(…)
Could you calm down, please? I really didn't mean to offend you.

I am familiar with the sources you've linked to. I also agree with them for the most part, i.e. regarding all points except the one about throwing across foreign frames. And even then, assuming the foreign code you're throwing across either doesn't need much cleanup or is specifically written to handle sudden changes of what piece of code is executed right now (given the amount of backwards compatibility hacks Windows has, I wouldn't be surprised if Windows API callbacks belong to the latter category), they're also right.

My claim refers to the situation where the foreign code doesn't satisfy this requirement. If you really want a credible source for that, you can download GCC sources and read libgcc/unwind-sjlj.c and see how it behaves, and that its behavior is more or less in line with what I described, that is, that it blindly longjmps to the most recently registered handler with little regard to anything.

You can even write a sample program and see the behavior for yourself. Say, a C DLL compiled by MSVC that's called from GCC/sljl-generated C++ code and that calls a callback and right after it performs some "cleanup" code (a printf is more than enough for a sample program), where the called back function is that C++ code and it throws an exception.

claiming that branching on error code before throw is slow except you didn't provide any evidence for your claim whatsoever
All branches can be slow, for the very same reason, i.e. branch mispredictions. You probably can find credible evidence in Intel or AMD optimization manuals. For example, the Intel optimization manual from April 2012 says, in 3.4.1, "Eliminate branches whenever possible" at the beginning of a chapter that contains a lot of information about why branches are the way they are.

At any rate, isn't "code that doesn't exist runs faster than code that does" a common sense?


Anyway, can we just agree to disagree and carry on?



FRex and Silvah: Can we now return to a normal discussion and leave your personal feelings completely aside? You can still fight each other on your own private messages, but this near childish behavior and calling names won't help you, nor us, nor the discussion. Thank you!
I don't really see any name-calling. Yes, people can and do get passionate about some issues, but this merely shows they care. Perhaps they care a bit too much, but that's real-world people for you.
Moreover, disagreement is an important part of discussion, after all, why discuss at all if we all already agree?

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: Exceptions in SFML 3 ?
« Reply #35 on: October 14, 2013, 01:34:13 pm »
Heys guys,

at first: nice discussion. Like someone else said I'm happy to see that people around SFML are highly interested in core issues. It's one of the things I really love about SFML and its community.

Enough picnic, back to the serious side of life. :o

Exceptions, error codes or both: I'm with eXpl0it3r. SFML is a C++ library, so C++ techniques, practices and workflows should apply. If that requires CSFML to try/catch exceptions and forward them to the target-language's error mechanisms, then that's the way to go in my opinion.

Yes, this might be annoying for the binding writer (repeating code) and add another thin layer between the call and the execution in the library, but if that's required to reach a proper C++ way of doing things in a C++ library, well, then it's the cost. And unless someone can prove with a profiler and good tests that performance is really lacking, then I'm sure there are options that can be tried out.

Just look at how the bindings themselves are doing it: They change function names, implement event loops on top of SFML etc., just to make the binding fit to the target language. This is good, as nothing is worse than code that feels alien in a language (and does not make use of its security features especially!).

If your only argument against exceptions is that bindings are harder to do, then I guess that it's not valid. If SFML uses exceptions, then CSFML won't, because it's C. Since bindings are already using CSFML, I don't see any problems here. At least that's what my impression is, correct me if I'm wrong (it has been some time since I had been adjusting the Python binding).

It's not like exceptions are only a fancy way of doing error reporting. They greatly enhance security.

Splitting loading/saving routines: I like this. It's indeed an OOD thing mostly, but personally I think it's logical.

The biggest argument I can bring to the table (or: which is high priority for me) is modularity and security.

If sf::Image, for example, only contains the data, then the external loading mechanisms have to use the image's public interface, which makes sf::Image more robust due to encapsulation. Side effects are reduced, and transparency at the user increased.

Enhancing the image loading is easy as well: Just add another function/class that uses sf::Image. And this will not look alien/confusing to the user. Just compare these:

sf::Image image;

// First version, using internal loading routines:
image.loadFromFile( "foo.png" );
image = PerlinNoiseImage::generate();

// Second version, using external loading routines:
image = sf::ImageAdapter::load( "foo.png" );
image = PerlinNoiseImage::generate();

The second version is more intuitive for extensions, because if you are using an extension or not, the handling is the same (in fact SFML's "built in" loading routines would behave like an extension as well).

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Re: Exceptions in SFML 3 ?
« Reply #36 on: October 14, 2013, 02:04:20 pm »
Splitting loading/saving routines: I like this. It's indeed an OOD thing mostly, but personally I think it's logical.

I won't say that's an illogical way of doing things, but... this second version seems just to add some factory classes/methods – which can already be done on the user site. In fact, it removes some flexibility in the user code style.

When Laurent removed most of the inheritance in SFML it was, among other things, to let the user decide if he wanted to use or not use inheritance for his custom transformable / drawable entities.

It seems the question is again on the table:

Should SFML force the user to use exception? I would say «yes», see Tank's and eXpl0it3r's arguments to which I agree. Also, there were some suggestions to use overloads and error codes so we can have both exception and "errno".

Should SFML force the user to use factories? I don't think so. There are too many design out there to force the user to use X (where X is not that much linked to C++ style like exceptions are).

« Last Edit: October 14, 2013, 02:06:05 pm by Hiura »
SFML / OS X developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Exceptions in SFML 3 ?
« Reply #37 on: October 14, 2013, 02:25:55 pm »
I don't mind SFML supporting exceptions, as already said "it is the C++ way". C++ code shouldn't really have to care about what other languages support and don't support. If they want to interact with C++ code, they should be the ones taking the initiative and not the other way around.

As for the inheritance, I can say personally that whenever I design systems I tend to end up with really really deep inheritance hierarchies. Is this what I wanted? Not really. But until I figure out a better way of doing things, I'll just have to put up with myself :P. Just as a side note, deep inheritance hierarchies used to be the "in thing" back in the day when OOP theory showed up on the market, as we move further into the future, less and less people support having too many useless layers of abstraction. However, until that is what they teach new programmers learning OOP, you will probably keep seeing deep hierarchies (thanks Java ::)). A guideline in the design of C++ standard libraries is also to keep hierarchies shallow, probably also to keep compile time and overhead down since we don't want really fat classes polluting our objects when we use containers for example.

Maybe SFML should try to adopt some (but not all) of the guidelines at: http://isocpp.org/std/library-design-guidelines
Not only would it make SFML more modern, but as hard as it is to believe, I think it would actually make the library easier to learn if you are already an established C++ programmer. As for the non-established C++ programmers.... that is a story for another time :).
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Exceptions in SFML 3 ?
« Reply #38 on: October 14, 2013, 04:06:40 pm »
Quote
However, until that is what they teach new programmers learning OOP, you will probably keep seeing deep hierarchies (thanks Java ::)).
Coincidentally I just had Java loving doctor teach me OOP last year and one of the rules to pass it was to have, in final assignment project, at least 15 classes in a single rooted, single inherited hierarchy with at least 3 inheritance levels and to never write any free functions(writing them Java way if you really need them). :P
Back to C++ gamedev with SFML in May 2023

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Exceptions in SFML 3 ?
« Reply #39 on: October 14, 2013, 04:50:49 pm »
Quote
break of encapsulation through friendship
Does it really? BS says It doesn't: http://www.stroustrup.com/bs_faq2.html#friend
friend is better than making the members public, but worse than using the public interface. It still creates a cyclic dependency between two classes: The class granting friendship must know the name of the accessing class, and the latter must know the former's definition. This can be partially mitigated by an intermediate access class, but that again makes code more complex.

Correct me if I'm wrong, but the Music class seems the only thing that is really profiting from streaming.
The other classes benefit as well, especially if loading is slow. Consider cases like an encrypted and compressed file archive, resources that are received via network, and so on. When you have to wait until the whole resource is ready before processing it further, you may experience a significant slowdown.

Streaming is definitely something we have to take into account when designing a new API.

The biggest argument I can bring to the table (or: which is high priority for me) is modularity and security.

If sf::Image, for example, only contains the data, then the external loading mechanisms have to use the image's public interface, which makes sf::Image more robust due to encapsulation. Side effects are reduced, and transparency at the user increased.
As I already asked MorleyDev earlier, could you be more concrete here? It sounds all very theoretical. Sorry for nitpicking, but if the API should be changed to something possibly more complex, I find it very important to have a clear view about the concrete, actual advantages rather than nice OOD terms.

How is sf::Image more robust? Since there will be more code with two classes, more maintenance and testing is required. On the other hand, a separate class doesn't simplify the implementation anywhere.

What side effects do you mean, and why is the code more transparent for the user?

You proposed
image = sf::ImageAdapter::load( "foo.png" );
what about
image = sf::Image::load( "foo.png" );
? It would not tear the implementation needlessly apart, yet provide a way to have uniform factories. And it would be simpler to use since no separate class is involved.

By the way, these factory functions require C++11 move semantics -- recommended for all resources, mandatory for non-copyable ones. As a consequence, Laurent would have to drop C++03 support in SFML 3. If he won't, then we can directly forget about the factories ;)
« Last Edit: October 14, 2013, 05:02:15 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Exceptions in SFML 3 ?
« Reply #40 on: October 14, 2013, 05:18:07 pm »
Doesn't friend just require forward declaration of class that is giving access?
And it's using members because it knows what it's doing, so it's as a class was now split into two parts, one core that touches members and other that touches members AND files, so core class doesn't know what files are but it remains encapsulated so user can't break it, because he is not friend.
Back to C++ gamedev with SFML in May 2023

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Exceptions in SFML 3 ?
« Reply #41 on: October 14, 2013, 05:28:57 pm »
Doesn't friend just require forward declaration of class that is giving access?
Assuming you mean "class that is accessing": yes, that's why I said "must know the name".

The implications of friend are pretty obvious: One class depends on implementation details of another one. Thus, when you change the implementation, you have to adapt code outside the class. That's breach of encapsulation (by definition), however in a controlled way. I'm not saying there are no appropriate use cases for friend, but it should be used with care, and avoided when possible.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Exceptions in SFML 3 ?
« Reply #42 on: October 14, 2013, 06:25:44 pm »
In my experience, the most common solution to situations where a deep inheritance tree or "friends" are starting to form is usually that if X needs to know about an underlying part of Y, then that is not truly an underlying part of Y but a separate Z waiting to be extracted.

Usually if you need friend, it's because there's a third class sitting in there somewhere, a dependency to extract that can marry the two. Extract it, make it it's own beast, and then inject it where needed.

But this kind of thing is much easier to do in languages with good refactoring toolage. C++ is not one of those languages, the available refactoring tools are limited and rather primitive compared to a lot of other languages. It's why I'm eagerly watching JetBrain's upcoming C++ IDE. They provide some of the best tools for developing in Java and C#, and to add C++ to that list? Gives me goosebumps.

The logic goes that the less an individual class/function does by itself whilst still fulfilling the duty given to it, the better because it means that each class/function is easier for the programmer/user to understand, to comprehend and to use effectively and efficiently, and so by reducing the complexity the possible mistakes and bugs in any given part of the system are reduced.

The more something does, the more complex it becomes, the more difficult it is to grasp it conceptually in it's entirety at any given moment. Quite simply, the more something can do the more you have to remember could be done to it and with it, the more difficult it is to use and maintain.

You have to remember more ways it can be manipulated and consider when those manipulations could happen and what their effects would be, and it makes coding in it more difficult, because you have to remember more ways it can be manipulated and how that could change the internals of the class and how the externals interact with it. It's more of a cognitive burden.

It also helps that having many small tools often brings greater flexibility by allowing for the composition of those small tools to achieve a wider variety of results with less effort.
« Last Edit: October 14, 2013, 07:28:57 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Exceptions in SFML 3 ?
« Reply #43 on: October 14, 2013, 07:37:40 pm »
In my experience, the most common solution to situations where a deep inheritance tree or "friends" are starting to form is usually that if X needs to know about an underlying part of Y, then that is not truly an underlying part of Y but a separate Z waiting to be extracted.
But it is not always appropriate to make Z part of the public API. Often, it is a tiny implementation detail, hardly worth outsourcing. Extracting the functionality in its own module may add flexibility, but it may as well decrease it, because the implementation is bound to the existing modules and loses the freedom to operate across similar, but now separated functionality. As long as one class is solely responsible for a task, it may exploit its complete knowledge for simplifications or optimizations -- when you try the same for several classes, each of them requires a big interface and a lot of boilerplate code for their interaction.

But this kind of thing is much easier to do in languages with good refactoring toolage. C++ is not one of those languages, the available refactoring tools and are primitive.
The possibilities are indeed limited, but do you know Visual Assist X for example? What level of refactoring do you exactly have in mind? I wouldn't expect tools for C++ that are able to perform high-level refactoring tasks (except for simple Java-style cases), simply because it's too difficult to implement them. Just look at overloading resolution, templates, name resolution and ADL -- not even compilers handle all those rules 100% correctly.

The logic goes that the less an individual class/function does by itself whilst still fulfilling the duty given to it, the better because it means that each class/function is easier for the programmer/user to understand, to comprehend and to use effectively and efficiently.
The less something does, the worse because there is more boilerplate code, more communication overhead, which in turn requires more development, maintenance, testing and debugging time.

The more something does, the more complex it becomes, the more difficult it is to grasp it conceptually in it's entirety at any given moment. Quite simply, the more something can do the more you have to remember could be done to it and with it, the more difficult it is to use and maintain.
The less something does, the more trivial it becomes, the more difficult it is to grasp the high-level concept in its entirety at any given moment. Quite simply, the less something can do, the more different classes/functions you have to remember and with it, the more difficult the project is to use and maintain.

Just to show you the other side, the truth is somewhere in the middle. But seriously, we need a less idealistic and more pragmatic view. There's always a tradeoff, and you should keep in mind that SFML aims to be simple, which conflicts with multiplying the number of classes to perform ordinary tasks.

I think we are meanwhile lost a bit in details. Maybe let's go back and ask ourselves how a simple-to-use yet powerful API would look like -- from user perspective, also taking into account beginners. And in particular, what is wrong with the current design (so far, the opinion seems to favor exceptions over bool values, anything else?).
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Exceptions in SFML 3 ?
« Reply #44 on: October 14, 2013, 07:53:03 pm »
Oh yes, it's always a trade-off that calls for pragmatism. I like and encountered most the phrase "Diminishing Returns" to describe it. Stop when the returns start to become diminishing, and continue again the next time you need to go to that code and the returns have become undiminishing again. It'd say it's more something it's good to strive towards.

But for a library I guess a degree more up-front design must be done than other projects which can limit the ability to be iterative.

For tools, Visual Assist X is a good start. I use it, it's good for exploring but the actual code modification tools are still a little limited. But it's C++, and comes with the territory. Still gonna miss the one-button "Extract Class" option xD

The solution to things that shouldn't be 'public api' but are by nature of the language..., well the cowboy in me says if it's not documented, don't count on it continuing to exist. But that's probably not a good attitude, hence why I call it "Cowboy Me".  The most common way I see usually involves a detail namespace in C++. SFML seems to take the "put those internals into the CPP files and compile them in" approach.

*sigh* I'm going more into general design approaches now because this is something I just find generally interesting, and straying away from the main SFML topic.
« Last Edit: October 14, 2013, 08:43:17 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.