Some recommendations

Started by Evert B, July 06, 2010, 15:08:12

Previous topic - Next topic

Evert B

Hi all! I'm just getting to know LWJGL (comparing it to JOGL currently). Pretty quickly I came across two things I think could be improved:

1) Why not use unchecked exceptions (i.e. anything that extends from RuntimeException)? As opposed to checked exceptions, the compiler doesn't force you to handle them, and really in almost all scenario's there isn't much you can do about them anyway except to terminate the app (and print/log/display them, but since they normally end up on stderr anyway that's not really necessary either). Have a look at most demo's of this project, all they usually do in their exception handling is print the error. Using unchecked exceptions would spare us a lot of so called "boiler plate" code, especially for simple short demo apps. Do a quick search on google, this subject has been talked about a lot in other areas of the Java industry (see "Professional J2EE Design and Development", by Rod Jonson, the creator of the Spring Framework). A quick and painless way to introduce this into LWJGL is to simply make LWJGLException extend from RuntimeException in stead of just Exception. The great thing is this won't break any existing code!

2) Why not make GL21 extend GL20, GL20 extend GL15, GL15 extend GL14, etc...? If you have a card capable of GL30 it is capable of all previous version too, so why doesn't the API reflect this? It would make things easier and cleaner. Or is there a good reason for this?

I hope these ideas may be of some help. I apologize if ever this has been answered before (I did a quick look around but didn't find any) or if this is not the best place to post such things...

best regards,
Evert.

Fool Running

1) I understand what you are saying and it makes some sense, but forcing users of LWJGL to think about what they need to do if something goes wrong is very good. When creating commercial applications using LWJGL, its better to know what exceptions might be thrown and when. When they are thrown you can try handle them gracefully (even if its just telling the user that something really bad happened and the application will be shut down). Forcing, at compiler time, the programmer to deal with exceptions is actually something I like about Java very much. If an exception is fairly common I want to know about it, and I think LWJGL uses that feature well.

2) This has been discussed before: http://lwjgl.org/forum/index.php/topic,2599.0.html and http://lwjgl.org/forum/index.php/topic,3204.0.html
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

Evert B

1) In fact, ideally for the exceptions to be really useful, there should be a diversification into different types of exceptions which tell you more precisely exactly what has gone wrong (unsupported display mode, unsupported GL extension, etc). Now there is basically only LWJGLException, which doesn't give you much to go on. As such the only reasonable way I can think of of responding to such an exception is to inform the user and bail out. Now the code that does this kind of stuff you want to typically write only once at a high level of your application (e.g. right in your main method) as a sort of catch-all chute. You DON'T want to do that a zillion times all over your code because LWJGLException happens to be checked.

In general, recoverable exceptions (i.e. your application can find another way to keep running) should be checked and unrecoverable exceptions should be unchecked. This is what many people have come to agree on. Have a look at http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html and aforementioned sources.

And by the way, if you're building a commercial grade app, I think you'll want to carefully read the docs anyway and not merely rely on the compiler to tell you when you should consider certain exceptions. You can still write "throws SomeUncheckedException", so JavaDoc will pick them up.

2) Thanks for those links, guess I didn't look hard enough.. I read through both but none could give me a valid reason why these classes don't extend each other. If you want to aim for a particular GL version, you also expect to (and need to) have all features from all previous versions. Inheritance doesn't affect distribution size (and even if it did, who cares about some 100 extra bytes...). Some posters mentioned that inheritance was actually there at some time, but it was removed. So there must be a sound reason, what is it?

Agreeably, you would need something different for GL 3+ since so much has been deprecated and it wouldn't be clean to keep all the old methods around. So maybe a separate class is the right way to go there, but it would still need e.g. glEnable from all the way back to GL 1.0 (I guess). It would be easier and cleaner to if you could use multiple inheritance (i.e. interfaces in Java), but since LWJGL is designed in a very procedural way with all the static methods, that's pretty much out of the question. Now, I do perfectly well understand why that particular choice was made, so I won't challenge that ;)

kappa

you can always use java's static import to get rid of teh GLXX. part the beginning of the all the LWJGL methods.

Evert B

Quote from: javalwjgl on July 08, 2010, 08:25:24
you can always use java's static import to get rid of teh GLXX. part the beginning of the all the LWJGL methods.
Sure i know, but my point is you shouldn't have to import static GL11, GL12, GL13, GL14, GL15 and GL20 if you just need GL 2.0 functionality. Unless there really is no other way because of some limitation. Still waiting to hear what that might be?...

In the meanwhile, I stumbled upon something else:

3) Why are there a multitude of overloads of glTexImage2D (and likely other such methods) for each separate buffer type (i.e. ByteBuffer, IntBuffer, FloatBuffer, etc) while there could be just one method simply taking the more general parent class Buffer? The GL type parameter already tells you the data type doesn't it? A quick look at the source code learns me there is no need for this, except that BufferChecks.checkBuffer doesn't accept Buffer either but rather has the same number of overloads for all different buffer types. But there too, all overloads do exactly the same, so I don't see why these are needed either.

For example, I have a piece of code that transfers an AWT image into a GL texture. These images can have all kinds of data types. So I have to needlessly check (again) their exact type just to provide LWJGL with a Buffer parameter of the correct subclass, writing a whole bunch of if blocks which look almost the same. If LWJGL were to just accept Buffer, I could reduce that to a single line of code.

bobjob

Quote
Sure i know, but my point is you shouldn't have to import static GL11, GL12, GL13, GL14, GL15 and GL20 if you just need GL 2.0 functionality. Unless there really is no other way because of some limitation. Still waiting to hear what that might be?...
On the 1 point, in regards to GLXX backwards compatability:
I dont know why the guys decided to do it this way. But for what its worth I have learnt alot about OpenGL (how it works/history and such) purely because of the way LWJGL handles it. By trying to understand why I cant just use any GL class (yes I have the bad habbit of taking short cuts in learning when there presented :P). I guess it might make it user friendly for people to have it backwards compatible. But as someone who uses it, Iv noticed benefits in it being this way. and once your down the track enough to feel confident with the library, importing the Classes as static is a bonus.

Fool Running

Quote from: Evert B on July 07, 2010, 19:14:25
1) In fact, ideally for the exceptions to be really useful, there should be a diversification into different types of exceptions which tell you more precisely exactly what has gone wrong (unsupported display mode, unsupported GL extension, etc). Now there is basically only LWJGLException, which doesn't give you much to go on. As such the only reasonable way I can think of of responding to such an exception is to inform the user and bail out. Now the code that does this kind of stuff you want to typically write only once at a high level of your application (e.g. right in your main method) as a sort of catch-all chute. You DON'T want to do that a zillion times all over your code because LWJGLException happens to be checked.

In general, recoverable exceptions (i.e. your application can find another way to keep running) should be checked and unrecoverable exceptions should be unchecked. This is what many people have come to agree on. Have a look at http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html and aforementioned sources.

And by the way, if you're building a commercial grade app, I think you'll want to carefully read the docs anyway and not merely rely on the compiler to tell you when you should consider certain exceptions. You can still write "throws SomeUncheckedException", so JavaDoc will pick them up.
Most of the LWJGLExceptions that are thrown are recoverable (e.g. Display.create() failed. Try without the stencil buffer.). However, I will definitely agree that it would be nice to have different exceptions instead of all of them being a LWJGLException.

It is also true that its a good idea to look at the documentation, but some people don't always do that (like me :P).
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D