11.12.2016, 16:42
(
Последний раз редактировалось BiosMarcel; 11.12.2016 в 18:23.
)
Hello Community,
I am making this tutorial because i most of the time am browsing the section "Scripting Help", there are a lot of beginners that want help, but their code is just not nice to read or edit. I hope i can influence at least some peoples scripting habbits by making this tutorial.
Through the whole tutorial we will use this code and try to make it a little bit better:
Part 1: Indentation
As ylou might have noticed already, every line starts at index 0 (line beginning), but that just doesn't read very well, because your mind can't seperate the code blocks that easy, even though you have the brackets.
So, i recommend to always indent your code after every opening bracket, it should(could) look like this:
Each time you use a bracket to open a code block, you should increase the indentation level:
Since our code is indented now, you can easily see there are 3 levels. It's up to you, how you indent, as long as it is consistent. You can use a specific amount of either spaces or tabs. Most people use a single tab per level (like I just did). Choose whatever works best for you!
Part 2: Whitespace
Now, let us divide the code even more by using whitespace, for that, we will now look at Level 1:
There are diffrent things happening in level 1, let's have a closer look:
1: Sending a client message
2: printing something onto the console
3: retrieving the players name
4: entering an if-statement(level 2)
As you can see, we have 4 diffrent tasks at level 1, now we seperate each of them with an empty line:
Part 3: Redundant Code
Doubling code just bloats your .pwn files and makes it harder to read the code, because you have to read more, it is like having to read the same function over and over, but every time you read the function, something might have changed. If you were to change the code, you'd have to change it at more than one place, this will most likely lead to mistakes.
As you can see in our code, we have two variables where we store player names in,
and
and we call GetPlayerName(...) two times.First, you don't need two name variables, you can just reuse the first one. Second, do we really want to call GetPlayerName twice? We do have 3 diffrent input parameters, which is a potential error risk.
So, we create a function instead:
Don't put 'stock' infront if your functions unless it is inside of an include file or not in use (in which case you should comment it out)!!!
Part 4: Defines
In PAWN you have the option to use defines, those are constants that are replaced on compiletime, which means they make no difference in performance but they higher your codes maintainability. Whenever you use a string or a number more than once (or you change it very often), you should probably use a define instead. Looking at our code, we can see us using the number '24' three times. In our case there is already an existing definition, called MAX_PLAYER_NAME and it defines the maximum length of a players name.
Let's use it:
If SA-MP would now cut the player names to a size of 10, our script would automatically adapt as soon as we recompile the script.
Part 5: Variable Names
Variable names are very important, if a variable is called 'tree' for example, you would probably think it has todo something with trees, but what if that's not true because someone called it 'tree' just because he felt like it? So, you should always give your variables proper names which describe what they are there for.
Looking at the function that we created, where we just called the variable, that we use to store the players name in, 'VARIABLE', which is complete crap. So, what if we call it 'NAME' instead? Hmmm nah still not good. But why is 'NAME' not good? Well, usually there is two types of variables, cosntants(variables that stay the same) and "normal" variables. our constants are the defines and the const variables and our "normal" variables are the ... variables. But how do we know if a variable is a constant or a variable?? Naming conventions are the key, if we simply use uppercase letters only for our constants and camel case naming for our normal variables, we always know what type it is.
So we will call our variable 'playerName':
But we still have the name variable at the top of our script and that's where the next topic comes in handy.
Part 6: Variable Visibility
Every variable has a scope where it is visible(useable), in our case, we can use
everywhere in our script, other than
which we can only use inside of the
function.
So what do we do?
We will try not to make a global variable as long as it is not neccessary:
Since the visibility of the former
variable is now within
, we can name it just as we did in the
function, because we will not get a naming conflict this time.
Part 7: Documentation
In addition of making the code itself readable, you can also document the code, so people don't have to read the actual code of a function to know what it is doing.
As an exmaple, let us document our function:
If you now read the comment above the function, you instantly know what the function is doing, in addition to that, you can document the single lines / blocks of the function.
END
I hope you learned something, i'll gladly accept any feedback. Also, i know there are already other topics like this, but i kind of wanted to make my own, since it is something based on opinion (mostly).
greetings Marcel
I am making this tutorial because i most of the time am browsing the section "Scripting Help", there are a lot of beginners that want help, but their code is just not nice to read or edit. I hope i can influence at least some peoples scripting habbits by making this tutorial.
Through the whole tutorial we will use this code and try to make it a little bit better:
PHP код:
new PLAYERNAME[24];
new PLAYERNAME2[24];
public onPlayerConnect(playerid)
{
GetPlayerName(playerid,PLAYERNAME2,24);
if(strlen(PLAYERNAME) >= 20)
{
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent");
print("Isn't that beautiful?");
GetPlayerName(playerid,PLAYERNAME2,24);
if(strlen(PLAYERNAME2) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
}
}
Part 1: Indentation
As ylou might have noticed already, every line starts at index 0 (line beginning), but that just doesn't read very well, because your mind can't seperate the code blocks that easy, even though you have the brackets.
So, i recommend to always indent your code after every opening bracket, it should(could) look like this:
PHP код:
new PLAYERNAME[24];
new PLAYERNAME2[24];
public onPlayerConnect(playerid)
{
GetPlayerName(playerid,PLAYERNAME2,24);
if(strlen(PLAYERNAME) >= 20)
{
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent");
print("Isn't that beautiful?");
GetPlayerName(playerid,PLAYERNAME2,24);
if(strlen(PLAYERNAME2) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
}
}
PHP код:
public onPlayerConnect(playerid) //Level 0
if(strlen(PLAYERNAME) >= 20) //Level 1
if(strlen(PLAYERNAME2) >= 23) //Level 2
Part 2: Whitespace
Now, let us divide the code even more by using whitespace, for that, we will now look at Level 1:
PHP код:
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent");
print("Isn't that beautiful?");
GetPlayerName(playerid,PLAYERNAME2,24);
if(strlen(PLAYERNAME2) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
1: Sending a client message
2: printing something onto the console
3: retrieving the players name
4: entering an if-statement(level 2)
As you can see, we have 4 diffrent tasks at level 1, now we seperate each of them with an empty line:
PHP код:
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent!!!!");
print("Isn't that beautiful?");
GetPlayerName(playerid,PLAYERNAME2,24);
if(strlen(PLAYERNAME2) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
Part 3: Redundant Code
Doubling code just bloats your .pwn files and makes it harder to read the code, because you have to read more, it is like having to read the same function over and over, but every time you read the function, something might have changed. If you were to change the code, you'd have to change it at more than one place, this will most likely lead to mistakes.
As you can see in our code, we have two variables where we store player names in,
PHP код:
PLAYERNAME
PHP код:
PLAYERNAME2
So, we create a function instead:
PHP код:
new PLAYERNAME[24];
public onPlayerConnect(playerid)
{
PLAYERNAME = getName(playerid);
if(strlen(PLAYERNAME) >= 20)
{
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent");
print("Isn't that beautiful?");
PLAYERNAME = getName(playerid);
if(strlen(PLAYERNAME2) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
}
}
getName(playerid)
{
new VARIABLE[24];
GetPlayerName(playerid,VARIABLE,24);
return VARIABLE;
}
Part 4: Defines
In PAWN you have the option to use defines, those are constants that are replaced on compiletime, which means they make no difference in performance but they higher your codes maintainability. Whenever you use a string or a number more than once (or you change it very often), you should probably use a define instead. Looking at our code, we can see us using the number '24' three times. In our case there is already an existing definition, called MAX_PLAYER_NAME and it defines the maximum length of a players name.
Let's use it:
PHP код:
new PLAYERNAME[MAX_PLAYER_NAME];
public onPlayerConnect(playerid)
{
PLAYERNAME = getName(playerid);
if(strlen(PLAYERNAME) >= 20)
{
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent");
print("Isn't that beautiful?");
PLAYERNAME = getName(playerid);
if(strlen(PLAYERNAME2) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
}
}
getName(playerid)
{
new VARIABLE[MAX_PLAYER_NAME];
GetPlayerName(playerid,VARIABLE,MAX_PLAYER_NAME);
return VARIABLE;
}
Part 5: Variable Names
Variable names are very important, if a variable is called 'tree' for example, you would probably think it has todo something with trees, but what if that's not true because someone called it 'tree' just because he felt like it? So, you should always give your variables proper names which describe what they are there for.
Looking at the function that we created, where we just called the variable, that we use to store the players name in, 'VARIABLE', which is complete crap. So, what if we call it 'NAME' instead? Hmmm nah still not good. But why is 'NAME' not good? Well, usually there is two types of variables, cosntants(variables that stay the same) and "normal" variables. our constants are the defines and the const variables and our "normal" variables are the ... variables. But how do we know if a variable is a constant or a variable?? Naming conventions are the key, if we simply use uppercase letters only for our constants and camel case naming for our normal variables, we always know what type it is.
So we will call our variable 'playerName':
PHP код:
getName(playerid)
{
new playerName[MAX_PLAYER_NAME];
GetPlayerName(playerid,playerName,MAX_PLAYER_NAME);
return playerName;
}
Part 6: Variable Visibility
Every variable has a scope where it is visible(useable), in our case, we can use
PHP код:
PLAYERNAME
PHP код:
playenName
PHP код:
getName(playerid)
So what do we do?
We will try not to make a global variable as long as it is not neccessary:
PHP код:
public onPlayerConnect(playerid)
{
new playerName[MAX_PLAYER_NAME];
playerName = getName(playerid);
if(strlen(playerName) >= 20)
{
SendClientMessage(playerid,-1,"You have got a long name ...");
print("A clientmessage has been sent");
print("Isn't that beautiful?");
playerName = getName(playerid);
if(strlen(playername) >= 23)
{
SendClientMessage(playerid,-1,"Maybe you should overthink that name.");
print("Another clientmessage has been sent");
}
}
}
getName(playerid)
{
new playerName[MAX_PLAYER_NAME];
GetPlayerName(playerid,playerName,MAX_PLAYER_NAME);
return playerName;
}
PHP код:
PLAYERNAME
PHP код:
public OnPlayerConnect(playerid)
PHP код:
getName(playerid)
Part 7: Documentation
In addition of making the code itself readable, you can also document the code, so people don't have to read the actual code of a function to know what it is doing.
As an exmaple, let us document our function:
PHP код:
/*
This function returns the name of the player with the given playerid
*/
getName(playerid)
{
//the variable that we store the name in
new playerName[MAX_PLAYER_NAME];
//puts the players name into the prepared variable
GetPlayerName(playerid,playerName,MAX_PLAYER_NAME);
//returning the players name to the function caller
return playerName;
}
END
I hope you learned something, i'll gladly accept any feedback. Also, i know there are already other topics like this, but i kind of wanted to make my own, since it is something based on opinion (mostly).
greetings Marcel