[Tutorial] Beautiful, Readable Code (Indentation, Whitespace, Comments)
#1

Beautiful, Readable Code: Version 1.


Audience


It has come to my attention that poor scripting habits lurk left and right in the SA-MP community. This isn't a surprise considering the fact that most scripters are taking their first steps on these forums to produce code which offers immediate gratification. If you have ever found yourself wondering whether or not to indent, how to structure a set of statements, how to use comments effectively, or even looking up a plugin which indents for you automatically, then this tutorial is for you.

Oh, and one more thing! I have gone ahead and underlined key points in each section of the tutorial. Even if for some reason you don't understand any part of a particular explanation, make sure you understand the underlined key point!

Benefits


Proper indentation is the groundwork for writing beautiful, readable code. Although this point may have already been stressed to you at one point or another along your journey, you should be writing your code with the intention of it being readable for someone other than yourself. Even if you never intend to show your code off or introduce someone else to it, writing readable code makes troubleshooting easier and modifications less difficult to implement. Besides, you never know when you may take a break from the project you are working on and come back a few months later. If your code isn't readable, you will find yourself frustrated and unproductive.

Indentation


Indentation is arguably the most prominent factor in writing beautiful, readable code. Do you know how to indent properly? Let's find out.

First and foremost, we need to cover the idea of "nesting." Nesting is the use of those neat braces: { } to nest one statement, argument, or function within another. Let's start out with a basic example of nesting.

For this example, I am using a popular command processor named ZCMD for the purpose of simplicity and application. An example of a nest is creating a command using ZCMD. Notice the comments next to the code.

SINGLE NEST:

pawn Код:
COMMAND:heal(playerid, params[])
{
    SetPlayerHealth(playeird, 100);// This function (SetPlayerHealth) is nested inside of the command "heal."
}
The nested area is the area where you place further arguments and then define what you wish the command to do. It is possible to have a nest within a nest, or several nests within a nest. Below I have placed an example of a nest within a nest. Notice the comments in the code.

MULTIPLE NESTS:

pawn Код:
COMMAND:heal(playerid, params[])
{
    if(IsPlayerConnected(playerid)) // Nested within the "heal" command.
    {
        SetPlayerHealth(playerid, 100); // Nested within the if statement "IsPlayerConnected."
    }
}
How does nesting apply to indentation? They are directly related! The purpose of indentation is to visually represent nesting. In order to indent properly, all you have to do is press that "tab" button (the button which introduces several spaces) every time you are placing a new nested item. If you ever ask yourself again, "Do I need to indent here?" just remind yourself that you ONLY indent when you are placing a nested item. If the item you are placing is NOT nested in another statement/argument, you do NOT need to indent.

While you may have noticed in the past that loose indentation (improper indentation) only results in warnings, it is extremely beneficial to exercise good indentation when scripting. When you need to create multiple nests within nests, you'll find it much easier to locate the certain pieces you want to change or modify at a later date if they are indented properly.

White Space


White space is your friend! For some reason an obsession with line count (the amount of lines in a script) has overcome the SA-MP community. Stop making generalizations! Line count has absolutely nothing to do with how well a script has been written or how efficiently it will perform. The only reason line count has received such a negative aura is due to the fact that MOST scripts with large amounts of lines ALSO happen to be very poorly written. It is uncommon to find a large script written well, due to the fact that most large scripts are simply edits of poorly-written older scripts. If you utilize the latest plugins, includes, and stay up to date in your methods, line count is not an issue.

Now that I have flipped your world upside down, let's talk about white space! The ability to separate chunks of code with white space is a very powerful tool for creating excellent readability. Your code does not have to be on top of itself! Make some space, allow some breathing room! A couple of lines of space in between commands, for example, can make scanning through code a much more enjoyable experience. That being said, don't go overboard. You still want to display as much code as possible on the screen at any given time. Find the right balance between white space to create separation and readability and still displaying a good amount of code on the screen.

Comments


Another trend in the SA-MP community is the use of extravagant comments to create separation. While there isn't an issue with this practice, it's also not necessary. The real reason I am mentioning comments is not to encourage you to use them for separation, but to use them for what they are meant for: commenting things! Like I mentioned in the first paragraph, you should be writing your code through the eyes of someone else viewing it. This can be hard to do if you don't adjust your thinking accordingly!

Comments are meant to explain SCRIPT-SPECIFIC content, not general concepts of scripting. I find that some scripters tend to go overboard with their comments and begin to rewrite pawn_lang.pdf in the process. For example, in the if statement below:

BAD COMMENT:

pawn Код:
if(PlayerInfo[playerid][Admin] > 0) // Checks if the player's admin level is greater than zero.
I do NOT need you to tell me that this checks if the player's "Admin" is greater than zero. I have eyes and I have cognitive abilities! Instead, use comments to describe attributes of your script which an experienced scripter would not be able to recognize without previous knowledge of this exact script. An example of this is the creation of a new, unique function.

Just remember, you don't have to reinvent the wheel in your comments. Keep them short, simple, to the point, and most importantly only utilize them when necessary. While you may think its better to err on the side of caution, really you are just destroying your productivity.
Reply
#2

LOL i always do my identations correct and leave much space but over the past days i thought that it might not be that good to leave so much space..untill i read this topic thanks!
Reply
#3

Quote:
Originally Posted by AIped
Посмотреть сообщение
LOL i always do my identations correct and leave much space but over the past days i thought that it might not be that good to leave so much space..untill i read this topic thanks!
That's great to hear. I'm glad I could clear that up for you.
Reply
#4

A few more returns may indeed be an improvement. Sometimes I see people writing a command which has a dozen prerequisite checks forced in equally as many lines. Not good.

Also your coding style may play a role in readability. I and many others use the Allman style, which is the most readable in my opinion, but some people actually do this:

pawn Код:
} else {
Ugh.
Reply
#5

Quote:
Originally Posted by Vince
Посмотреть сообщение
A few more returns may indeed be an improvement. Sometimes I see people writing a command which has a dozen prerequisite checks forced in equally as many lines. Not good.

Also your coding style may play a role in readability. I and many others use the Allman style, which is the most readable in my opinion, but some people actually do this:

pawn Код:
} else {
Ugh.
You raise an excellent point. I contemplated including a section dedicated to style, but figured because the topic is so opinionated that I would leave that choice up to the reader to research. I provided the examples in Allman, which I also believe is the most readable style. Some would make the case that the slight sacrifice in readability results in more code being viewable on the screen. Personally I can't stand K & R and its variants.

Maybe an in-depth look at different indentation styles for a future thread?
Reply
#6

Hmm..so for example if i need to check many things i do something like this;

pawn Код:
if(IsPlayerInRangeOfPoint(blablabla))
{
    if(GetPlayerState(playerid)== blabllablala)
    {
        if(GetPlayerWeaponSkill bla bla blaaah
        {
             if(blaaaaaaa )
             {
             (and so on)
             }
             else
             {
             blablabla
             }
        }
    }
}
Is it bad to have so many if's ? i try to narrow it down but mostly im not sure what is best
Reply
#7

Quote:
Originally Posted by AIped
Посмотреть сообщение
Hmm..so for example if i need to check many things i do something like this;

pawn Код:
if(IsPlayerInRangeOfPoint(blablabla))
{
    if(GetPlayerState(playerid)== blabllablala)
    {
        if(GetPlayerWeaponSkill bla bla blaaah
        {
             if(blaaaaaaa )
             {
             (and so on)
             }
             else
             {
             blablabla
             }
        }
    }
}
Is it bad to have so many if's ? i try to narrow it down but mostly im not sure what is best
There is no problem with having several if statements, but sometimes you can cut down on them by using logical operators (&&, ||) or other means of organization (such as cases). It depends on the specific scenario and whether or not you need unique results in each case.

As for your indentation, you are almost there! You properly indented all nested items except the end results. Here is the correct indentation:

pawn Код:
if(IsPlayerInRangeOfPoint(blablabla))
{
    if(GetPlayerState(playerid)== blabllablala)
    {
        if(GetPlayerWeaponSkill bla bla blaaah
        {
             if(blaaaaaaa )
             {
                (and so on)
             }
             else
             {
                blablabla
             }
        }
    }
}
Reply
#8

I do agree with you on this, I hate when I see people forgeting about indentation.. In my opinion they're part of scripting, and make you read the code easier.
Reply
#9

Nested if are another good point. Some people insist on having an if-else-return structure when checking for prerequisites. Just make out for yourself which one's more readable: http://pastebin.com/Ji50mQQN
Reply
#10

Quote:
Originally Posted by Vince
Посмотреть сообщение
Nested if are another good point. Some people insist on having an if-else-return structure when checking for prerequisites. Just make out for yourself which one's more readable: http://pastebin.com/Ji50mQQN
The real difference in those structures is the first example requires return statements but the second example does not require return statements to which one is more readable? I would go with the second example since multiple returns tend to cause code to become convoluted with multiple exit points. Now in that example is certainly not the case but when you get 100 lines with no indentation with a dozen returns it looks ugly and has no flow.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)