Page 2 of 2 FirstFirst 12
Results 11 to 15 of 15

Thread: Error handling considerations

  1. #11

    Error handling considerations

    That's a nice idea. Having a centralized choice on the behaviour is good. What i don't like is that you still have to code the "if error then log exit" idiom on each call (in the case you're returning false instead of raising an exception).

    Btw about performance penalities for exception, are those so heavy? I don't know very well how they're lowered in the assembler, but it looks like it can be done in quite an efficent way.
    If you save your data in a proprietary format, the owner of the format owns your data.
    <br /><A href="http://msx80.blogspot.com">http://msx80.blogspot.com</A>

  2. #12

    Error handling considerations

    wow... i see there is a nice discussion going on

    There is another disadvantage of using exceptions (i guess nobody has mentioned it yet).
    When your project consists of multiple DLL's, exceptions should be handled in the DLL that raised them, otherwise it may result in some nasty AV's. And a bug in the error-handling system is a true nightmare. :evil:

    However, this is something i heard some time ago. If someone could explain WHAT EXACLTY causes the AV, please explain :razz:

    A game you want to be using as many clock cycles as possible for the game play and not coding error handling on every event.
    I think the clock-cycles are not the main isseu here... it's the time it takes to write the extra code + errorstrings, and the bloated ugly code, that makes extensive error-handling a bad thing.

    @Mirage: That's a very nice way of handling errors. Very clever. :thumbup:

    I think IMHO that the way of handling error of getItem (returning nil) is not good Smile
    First, it doesn't solve the problem of having to check every function returning something:
    I agree, but in a lot of cases, checking for NIL isn't neccesary.
    The 'GetItem' routine is (in my experience) mostly used in the following context:
    [pascal]
    for i:=0 to GetItemCount -1 do
    if GetItem(i).ProcessThisItem then
    begin
    GetItem(i).Process;
    //etc etc.....
    //......
    end;
    [/pascal]

    In this case, it is very unlikely that the index will go out of bounds, so checking for NIL would be foolish.

    More important, you get an immediate error (a more talking one than a generic AV error btw). With AV, the error can (and very often does) pop up in a completely different place:
    [pascal]

    // here i set myItem property of an object:
    myObject.myItem := getItem(x); // this raises exception instantly, with the offending line number. No need to debug
    ...
    // another unit, another thread, another caller far far away:
    yourObject.myItem.getValue(); // access violation. But who set myItem to nil? Need to debug
    [/pascal]
    I think this scenario is unlikely to happen. When you get an item from a list, you usualy want to modify it directly or get a property-vallue or something. When you just want to store it in another more global variabele, you should check whether it's NIL or not.



    I still tend to use the 'if error then exit' way, because your app doesn't get bloated. Some critical API calls do need error handling (e.g 3d Device Init, Flipping buffers or rendering). For some reason, i don't like to use exceptions (especialy in games).

    I think using error-codes (dwords) instead of booleans would be a slight improvement. Then you need to make a list of error-types e.g:

    [pascal]
    E_SUCCES = 0;
    E_FAIL = 1;
    E_INVALID_PARAM = 2; //e.g a pointer parameter that shouldn't be NIL or points to wrong data
    E_OUTOFBOUNDS = 3; //when an index is out of bounds
    E_FILE_NOT_FOUND = 4; //when a file is missing
    //etc etc....
    [/pascal]

    This way you know something about the error and you can easily narrow down the ammount of places where the error can occur.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  3. #13

    Error handling considerations

    Quote Originally Posted by chronozphere
    There is another disadvantage of using exceptions (i guess nobody has mentioned it yet).
    When your project consists of multiple DLL's, exceptions should be handled in the DLL that raised them, otherwise it may result in some nasty AV's. And a bug in the error-handling system is a true nightmare. :evil:

    However, this is something i heard some time ago. If someone could explain WHAT EXACLTY causes the AV, please explain :razz:
    Well i never heard of this problem, probably becouse i don't have the habit of subdividing the programs into multiple dll.
    It looks like it could be very possible, since exception handling is a bit triky when compiled (AFAIK).

    If one uses multiple DLL it is probably better to make some test before using exception


    I think this scenario is unlikely to happen. When you get an item from a list, you usualy want to modify it directly or get a property-vallue or something. When you just want to store it in another more global variabele, you should check whether it's NIL or not.
    The getItem was just an example.. I agree that scrolling a list usually never return nil, but in many broader case the scenarios is much more common.
    For example getting a property value, as you said, could involve dereferencing a class:

    player.target.position; // AV if target is nil!


    I still tend to use the 'if error then exit' way, because your app doesn't get bloated. Some critical API calls do need error handling (e.g 3d Device Init, Flipping buffers or rendering). For some reason, i don't like to use exceptions (especialy in games).
    Sorry but weren't you who said that the 'if error then exit' pattern bloats the code?
    If you meant instead bloating the executable binary code, i think a bloated executable is much much better than bloated code.
    What are these reason why you don't like to use exceptions?
    Maybe is it becouse you never tried them seriously? I say this becouse it is exacly the reason why i didn't used them before understanding how effective they are.

    I think using error-codes (dwords) instead of booleans would be a slight improvement. Then you need to make a list of error-types e.g:

    This way you know something about the error and you can easily narrow down the ammount of places where the error can occur.
    This is exacly how error handling was done before the invention of exceptions.
    Check some ancient C code or API (for example the socket API or the linux kernel) for some references
    If you save your data in a proprietary format, the owner of the format owns your data.
    <br /><A href="http://msx80.blogspot.com">http://msx80.blogspot.com</A>

  4. #14

    Error handling considerations

    Exceptions are a useful construct of object-oriented language, but although useful, they are generally misused.

    Exceptions are best used internally, inside a single class or module. They should not be thrown off to the user for handling (this is why I said VCL is bad designed IMHO).

    However, MSX, in the particular example you posted previously, it is a BAD USAGE of exceptions, considering that it is a bad practice in terms of Coupling and Cohesion (some recommended books are: this and this).

    List out of bounds is an internal issue of your list component. By throwing exceptions outside, user will have to know about your exception and handle it, while it is part of your system. This lowers the Cohesion and increases Coupling.

    The best practice would be to record the error and perhaps provide the user a way of checking it. However, user should not necessarily know about this and your component should work properly with any input the user may provide.

    Returning "nil" although somehow bloats the code, as you mentioned (btw, the same argument we hear about Object-Oriented Programming in general, that it increases code lines as compared to Structural Programming), but:

    1) It handles all user input without throwing errors.
    2) All its output is valid (since the output value is a pointer, "nil" pointer is perfectly valid output).
    3) It has a way of giving the end user information that the input was out of range.

    According to Jef Raskin:
    Quote Originally Posted by Jef Raskin
    The system should treat all user input as sacred.
    You may like one way of handling errors or another. My advice was based on good practices of software design and it may not be perfect.

    If you want to overuse exceptions and asserts to help the debugging and make your code shorter (hell, you can write all your code in one line, if number of lines is troubling you), it is your choice, but it may impact the quality of your products and the quality of development process, if there are more people working with you.

    Finally, this is my favorite:
    Quote Originally Posted by Jef Raskin
    When you try to write the text of error message, please, stop and alter the interface so that a condition at which this error message is called, did not arise.

  5. #15

    Error handling considerations

    Sorry but weren't you who said that the 'if error then exit' pattern bloats the code? Razz
    If you meant instead bloating the executable binary code, i thik a bloated executable is much much better than bloated code.
    What are these reason why you don't like to use exceptions?
    Maybe is it becouse you never tried them seriously? I say this becouse it is exacly the reason why i didn't used them before understanding how effective they are.
    Ghehe.... no i said that if error then LOG exit makes the code bloated.... take a look at these examples.

    [pascal]
    //this is the 'If error then exit'
    if not succeeded(ARiskyAPICall) then Exit;

    //now here the error handling code is added
    Result := ARiskyAPICall
    if not Succeeded( Result ) then
    begin
    ReportError( Result, 'A risky api call failed', Module );
    Exit;
    end;

    //now there is another case... e.g when a param is out of bounds
    if (param <0> MaxParam) then
    begin
    Result := E_OUTOFBOUNDS;
    ReportError( Result, 'The parameter was out of bounds', Module );
    Exit;
    end;

    [/pascal]

    The last two cases look quite bloated while the first one is only a single line of code.
    the second two need the 'begin end's' and those are actually bloating the code.

    If you want to use 'if error then exit', you should use it in the following context:
    [pascal]
    function MyRiskyFunction: boolean;
    begin
    Result := false;

    if Error then Exit;
    if AnotherError then Exit;

    //only return true, when the whole function is executed without errors
    Result := true;
    end;
    [/pascal]

    I will reconsider using exceptions. The big advantage is that you dont have to write all those errorchecking if's. If something goes wrong, every routine will cease execution until the exception is catched.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

Page 2 of 2 FirstFirst 12

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •