SA-MP Forums Archive
[Tutorial] Improving your code with try/catch/finally - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+---- Forum: Tutorials (https://sampforum.blast.hk/forumdisplay.php?fid=70)
+---- Thread: [Tutorial] Improving your code with try/catch/finally (/showthread.php?tid=429381)



Improving your code with try/catch/finally - Slice - 09.04.2013

This post is for my exceptions include.

I'll start off with some example code so you'll see what this is all about.

Example code

As you can see, the code below is very intuitive and concise. It also informs the user exactly what's wrong without making a mess (huge functions, global variables).

pawn Code:
CMD:login(playerid, password[]) {
    // Enter the try statement..
    // If "throw" is executed anywhere inside the try statement,
    // it will abort what it's doing and jump to "catch".
    try {
        // Try logging in..
        LogIn(playerid, password);
    } catch (e) {
        // Something went wrong? Tell the user.
        SendClientMessage(playerid, COLOR_RED, "Failed to log in, reason:");
        SendClientMessage(playerid, COLOR_RED, e[Message]);
       
        // Don't do anything more
        return 1;
    }
   
    SendClientMessage(playerid, COLOR_GREEN, "Success!");
   
    g_IsLoggedIn[playerid] = true;
   
    return 1;
}

// The log in function
stock LogIn(playerid, password[]) {
    new name[MAX_PLAYER_NAME];
   
    GetPlayerName(playerid, name, sizeof(name));
   
    // Does the player exist in the database?
    if (!PlayerExistsInDatabase(name))
        throw new Error("The nickname is not registered.");
   
    // Does the password match?
    if (isequal(Hash(password), GetUserPassword(name)))
        throw new Error("The password did not match.");
   
    // Is the account locked?
    is (IsUserAccountLocked(name))
        throw new Error("The user account is locked.");
   
    // Everything seems OK, let's load the user data.
    LoadUserData(playerid, EscapeFileName(name));
   
    return 1;
}

// Load the user data from a file
stock LoadUserData(playerid, filename[]) {
    if (!fexist(filename))
        throw new Error("The userdata file is missing.");
   
    // Open a user file for reading (not recommended, use a database instead)
    new File:fp = fopen(filename, io_read);
   
    // Failed to open the file
    if (!fp)
        throw new Error("Unable to open the userdata file.");
   
    // <load stuff>
   
    // We will only be on this line if fp is not 0
    fclose(fp);
}
The three blocks

Error handling with exceptions generally consists of three blocks. The only required block is try.
When the server encounters a try block, it will set up a trampoline that will catch any errors falling from the code (including the code inside function calls). If an error is caught, it will execute the catch block, containing an error object (see below).
After the catch block -- regardless if an error was thrown or a return statement was encountered -- it will enter the finally block.
If you returned a value in try or catch, this value will be returned right after finally and nothing below it will be executed. Throwing errors

When you throw an error, it will fall to the first try and end up in catch (if it exists).

To throw an error, you can either create a new one or throw an existing one, example:
pawn Code:
try {
    throw new Error("Error message", ERR_CODE);
} catch (e) {
    // This catch only knows how to take care of ERR_CODE_2
    // If another error occurred, throw it. Hopefully there's another try
    // statement outside that will catch the other error.
    if (e[Code] != ERR_CODE_2) {
        throw e;
    }
}
Error codes

To avoid having multiple error codes with the same values, there's a helper to create them.

Simply do this in the outer scope (not inside a function):
pawn Code:
new UniqueErrorCode<ERR_NOT_FOUND>;

// Now you can do this:
throw new Error("Unable to find that one thing", ERR_NOT_FOUND);
If you have 100 of these in different include files, each one will still have its own unique value.

Warning! FAQ
Nothing here yet.. Ask questions and they will be added here with their answer.


Re: Improving your code with try/catch/finally - Djole1337 - 09.04.2013

Just... awesome.

Thanks.


Re: Improving your code with try/catch/finally - RajatPawar - 09.04.2013

I am guessing this doesn't work with hooking, if it does, would make includes very very user friendly !


Re: Improving your code with try/catch/finally - CrazyChoco - 09.04.2013

Indeed, Nice include.

I'll use this in my script, thanks.

+rep


Re: Improving your code with try/catch/finally - Slice - 09.04.2013

Quote:
Originally Posted by Rajat_Pawar
View Post
I am guessing this doesn't work with hooking, if it does, would make includes very very user friendly !
What do you mean? It should work just fine. After try/catch/finally, it will just carry on as usual unless a return statement was made, in which case it will be the same as just doing return outside of try/catch/finally.


AW: Improving your code with try/catch/finally - ElMelo - 13.04.2013

Nice


Re: Improving your code with try/catch/finally - Slice - 13.04.2013

Quote:
Originally Posted by ******
View Post
They are probably referring to the CallLocalFunction hook method, though that's but supplanted.

Anyway, again very nice work!
As long as CallLocalFunction is not called within a try block it should work.

I'm looking into possible solutions, but honestly sometimes I just want to replace CallLocalFunction with the one I made.

Maybe I could hook it and use the custom one if inside a try block..


Re: Improving your code with try/catch/finally - Slice - 13.04.2013

I'll update it to support that. The performance shouldn't be an issue.


Re: Improving your code with try/catch/finally - Jay_ - 14.04.2013

Excellent work! This will surely improve the look and layout of my code in the future and make error handling much more effective - cheers


Re: Improving your code with try/catch/finally - BiosMarcel - 22.07.2016

As a Java Developer i kind of missed that, even tho this is not exactly the same but still gr8 job, 5 stars


Re: Improving your code with try/catch/finally - Jack_SMalls - 23.07.2016

Quote:
Originally Posted by [Bios]Marcel
Посмотреть сообщение
As a Java Developer i kind of missed that, even tho this is not exactly the same but still gr8 job, 5 stars
Bumped quite an old thread here.

Although, it is quite an interesting idea to have that. It makes you think about error handling more, considering most don't because of the language.