1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Guest, PO has ceased our separate tiering and adopted Smogon tiers for SM. More information and updates here.

    Dismiss Notice

Server Scripting Coding Standards

Discussion in 'Server and Client Scripting' started by Nightfall Alicorn, Nov 1, 2015.

  1. Nightfall Alicorn

    Nightfall Alicorn Left Pokémon Online, most likely not coming back.

    Joined:
    Oct 15, 2013
    Messages:
    491
    Likes Received:
    171
    PO Trainer Name:
    Nightmare Moon
    After coding here for some time. I've been trying to find clean coding standards and found many of the server goodies scripts are messy. So I've gone through all the stuff I've encounter to make this updated list. If any suggestions or changes post here.

    • Camel case for: functions, global variables and temp variables. (eg. channelName)
    • Caps & underscore case for: constants. Meaning variables that don't change. (eg. TABLE_HEADER)
    • Camel case w/ first letter cap for: classes. (eg Bot)
    • 4 space indention for tabs.
    Declaring Variables
    Code (JavaScript):
    1. // Try to declare your variables in a single use of var
    2. // and avoid redeclaring. Of course, you may declare a group earlier in
    3. // in the script and declare more later if they reach that part
    4.  
    5. // Correct
    6. // Eg. 1
    7. var x, i = 10, arrayExample = [];
    8.  
    9. // Eg. 2
    10. var x,
    11.     i = 10,
    12.     arrayExample = [];
    13.  
    14. // Although you would use the second example for long lines.
    15.  
    16. // Wrong
    17. var x;
    18. var i = 10;
    19. var arrayExample = [];
    Double Quotes Vs Apostrophes
    Code (JavaScript):
    1. // Correct
    2. var x = "Here's an example why to use double quotes.";
    3.  
    4. // Wrong
    5. var x = 'Here\'s an example why not to use double quotes.';
    6.  
    7. // As you can see, you would need to add a backslash before
    8. // apostrophe. This would be used for arrays and object property
    9. // names and their values also. Although, there are rare times
    10. // when using apostrophes to hold values better than
    11. // double-quotes.
    If, Else If & Else
    Code (JavaScript):
    1. // Correct
    2. // Eg. 1
    3. if (condition) {
    4.     sendChanMessage(src, "Condition 1.", channel);
    5. } else if (condition) {
    6.     sendChanMessage(src, "Condition 2.", channel);
    7. } else {
    8.     sendChanMessage(src, "Condition 3.", channel);
    9. }
    10. return;
    11.  
    12. // Eg. 2
    13. if (condition) {
    14.     sendChanMessage(src, "Condition 1.", channel);
    15.     return;
    16. }
    17. if (condition) {
    18.     sendChanMessage(src, "Condition 2.", channel);
    19.     return;
    20. }
    21. sendChanMessage(src, "All conditions above passed.", channel);
    22. return;
    23.  
    24. // Wrong
    25. // Eg. 1
    26. if (condition) return;
    27.  
    28. // Eg. 2
    29. if (condition)
    30.     return;
    31.  
    32. // Eg. 3
    33. if (condition)
    34. {
    35.     sendChanMessage(src, "Condition met.", channel);
    36.     return;
    37. }
    38.  
    39. // They do work but are harder to read and are
    40. // flown upon with jslint.
    Comparison
    Code (JavaScript):
    1. // Avoid ==, instead use ===.
    2. // Avoid !=, instead use !==.
    3. // If using == and !=, you must be doing something wrong.
    4.  
    5. if (arrayExample.indexOf(value) !== -1) {
    6.     return;
    7. }
    8.  
    9. // !== -1 works but > -1 would be shorter and easier to read.
    Try & Catch
    Code (JavaScript):
    1. // Correct
    2. try {
    3.     sendChanMessage(src, "This code works.", channel);
    4. } catch (error) {
    5.     sendChanMessage(src, "An error found. Error details: " + error, channel);
    6. }
    7. return;
    8.  
    9. // Note people either use e or err, personally I use error.
    10.  
    11. // Wrong
    12. try
    13. {
    14.     sendChanMessage(src, "This code works.", channel);
    15. }
    16. catch (e)
    17. {
    18.     sendChanMessage(src, "An error found. Error details: " + error, channel);
    19. }
    20. return;
    21.  
    Arrays
    Code (JavaScript):
    1. // Correct
    2. // Eg. 1
    3. var exampleArray = ["abc", "def", "ghi"];
    4.  
    5. // Eg. 2
    6. var exampleArray = [
    7.     "abc",
    8.     "def",
    9.     "ghi"
    10. ];
    11.  
    12. // Example 2 is better for long lines such as the /commands help.
    13.  
    14. // Wrong
    15. // Eg. 1
    16. var exampleArray = ["abc","def","ghi"]
    17.  
    18. // Harder to read with them squished together and frown upon with jslint.
    19.  
    20. // Eg. 2
    21. var exampleArray = [
    22.     "abc"
    23.     ,"def"
    24.     ,"ghi"
    25. ];
    26.  
    27. // Personally, I think wrong example 2 is better than correct
    28. // example 2. Because it is easier to read the commas when the
    29. // number of characters per line are different. Thus, reducing
    30. // syntax errors due to missing commas by accident. But best
    31. // to follow correct example 2.
    Function Parenthesis
    Code (JavaScript):
    1. // Correct
    2. sendChanMessage(src, "Hi " + sys.name(src), channel);
    3.  
    4. // Wrong
    5. sendChanMessage(src,"Hi"+sys.name(src),channel);
    6.  
    7. // Harder to read and frown upon with jslint.
    Function Declaring
    Code (JavaScript):
    1. // Correct
    2. // Eg. 1
    3. function getName(src) {
    4.     return sys.name(src);
    5. }
    6.  
    7. // Eg. 2
    8. var getName = function (src) {
    9.     return sys.name(src);
    10. };
    11.  
    12. // Wrong
    13. // Eg. 1
    14. function getName (src)
    15. {
    16.     return sys.name(src);
    17. }
    18.  
    19. // Eg. 2
    20. var getName = function(src)
    21. {
    22.     return sys.name(src);
    23. };
    24.  
    25. // Take note of the spacing before perimeter declaring
    26. // the passed values.
    For Loop
    Code (JavaScript):
    1. // Correct
    2. var x, playerNameArray = [];
    3. for (x = 0; x < playerIdArray.lengh; x++) {
    4.     playerNameArray.push(sys.name(playerIdArray[x]));
    5. }
    6.  
    7. // I preferably use x for for-loops and y if a for-loop inside a for-loop. I
    8. // hadn't needed to use z at all but should be avoided having more
    9. // than those two.
    10. // Others use i, short for int, as well k and j which are also acceptable.
    11.  
    12. // Wrong
    13. var playerNameArray = [];
    14. for (var x = 0; x < playerIdArray.lengh; x++) {
    15.     playerNameArray.push(sys.name(playerIdArray[x]));
    16. }
    17. // One of the biggest issues when I jslint a script are var
    18. // declaring in the parenthesis of for loop, making it
    19. // stop checking the rest of the script.
    The use of jshint/jslint plugin in Notepad++ is recommended. If you followed these standards you probably end up with 5 instead of 100 of errors on jslint.
     
    Last edited: Dec 11, 2015
    Joyverse and turbedi like this.
  2. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    167
    Those standards are only valid for po-server-goodies, not for the webclient or the main program.
     
    Nightfall Alicorn likes this.
  3. Fuzzysqurl

    Fuzzysqurl baa baa mareep I do what I want Server Owner Developer I do what I want Server Owner Developer

    Joined:
    Sep 12, 2012
    Messages:
    2,096
    Likes Received:
    967
    Sometimes extra line breaks around the code are helpful to make it more readable. This could include making variables on multiple lines, especially if you're initializing them right away. Also I personally like to add some spaces between various functions so it creates like a "group" (ex: All these functions deal with X) when everything is collapsed.

    Also doing something like below allows you to collapse just the "else" part by default in Notepad++.
    Code (text):
    1. }
    2. else {
    And i dislike defining the variable outside of the for() loop. looks messy and adds clutter imo.


    If you define everything at once too, you could be defining things that don't need to be defined yet because it might not even make it that far...


    Also, going to mention something: If you aren't changing that area, leave it alone in the scripts.
     
    Nightfall Alicorn and sulcata like this.
  4. sulcata

    sulcata stéphane curry best waifu Forum Moderator Server Administrator Forum Moderator Server Administrator

    Joined:
    Jun 13, 2012
    Messages:
    968
    Likes Received:
    744
    Capital letters with underscores are typically used for constants, not globals. Globals and locally/functionally scoped variable names tend to follow the same conventions of non-leading camelcase.

    There's also not really a reason to avoid multiple var statements. To be honest your last example regarding that almost looks more clear if anything.

    The reason to use double-quotes and not single is purely preference. There's no advantage since each can have the other within without escaping.
    "I'm a string"
    'So one string said to the other string, "I\'m a string"'
    That being said, only one style of string should be used to maintain consistency in notation. Double-quotes would be the most appropriate choice since other programming languages such as C/C++ and Java set a precedent of using them to denote strings, while using single-quotes to denote character values.

    Putting return statements in an if-else structure is just sort of ugly and unclear. Not saying the if-else structure should be ditched, but the returns probably could be in almost all scenarios.

    Generally for-loops first use i, then j, and then k. If you need any more than that then you've probably got some pretty severe nested logic that might be better separated into functions. x and y aren't bad, but I wouldn't make a habit of starting with them due to possible ambiguity with coordinate systems.

    Perhaps it's just me, but variable names that are 3 letters or less, not whole words, and not iterators look really messy. Like "res" that I keep seeing pop up in http request handler functions.
     
    Nightfall Alicorn likes this.
  5. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    167
    Oh, about the return thing. I completely use the wrong example all the time.
     
    Nightfall Alicorn and Sam Holmes like this.
  6. Nightfall Alicorn

    Nightfall Alicorn Left Pokémon Online, most likely not coming back.

    Joined:
    Oct 15, 2013
    Messages:
    491
    Likes Received:
    171
    PO Trainer Name:
    Nightmare Moon
    Could you show me an example what you mean with constants?

    If I'm correct your referring to res or resp being response?

    Okay, I've tried my best to improve and added extra notes. Also changed the title of the topic so everyone knows this is server related.
     
  7. sulcata

    sulcata stéphane curry best waifu Forum Moderator Server Administrator Forum Moderator Server Administrator

    Joined:
    Jun 13, 2012
    Messages:
    968
    Likes Received:
    744
    Constants are variables that don't get modified. Other languages normally have a keyword to declare them as constant, but javascript does not. That doesn't mean you can't use the same notation, all capitals+underscores, to still denote a variable which should not be expected to change.

    Also, jslint is ridiculously picky, jshint is usually very good for finding semantic errors without pointing out minor/inconsequential things.
     
    Last edited: Nov 3, 2015
    Nightfall Alicorn likes this.
  8. Duster

    Duster dodgerswin 2018

    Joined:
    Sep 23, 2013
    Messages:
    378
    Likes Received:
    698
    i don't see the problem with one line ifs when the conditional is easy to understand

    for example, something like
    Code (text):
    1. if (count === 0) return;
    which in more complex functions is much less cluttered than
    Code (text):
    1. if (count === 0) {
    2.     return;
    3. }
    especially when you have lots of nested blocks and stuff
     
  9. Maribel Hearn

    Maribel Hearn Scripter Developer Developer

    Joined:
    Sep 9, 2012
    Messages:
    33
    Likes Received:
    26
    PO Trainer Name:
    Maribel Hearn
    Looks nice! It's a good idea to have standards. However, I am not used to all of those standards myself; I have always had my own standards for my scripts. But since my scripts are private, it won't matter, really.

    If I ever decide to make a portable version for my scripts or contribute to the main server scripts, though, I'll try to adhere to these standards to support them. :P
     
    Nightfall Alicorn likes this.
  10. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    167
    Uh, those are suggested standards, not yet adopted :p
     
  11. Nightfall Alicorn

    Nightfall Alicorn Left Pokémon Online, most likely not coming back.

    Joined:
    Oct 15, 2013
    Messages:
    491
    Likes Received:
    171
    PO Trainer Name:
    Nightmare Moon
    I've done a little research. There doesn't seem to be any harm in one line statements without needing pointy brackets surrounding it. If it's a long condition at least have the statement under it with indent, else at the end of the short same line. Personally, I would avoid them myself. But I think it best hearing others opinions here.

    Lastly, I've been thinking. To avoid any confusion. Anyone think it be ideal to end a variable name with the suffix "Arr", it's shorter than "Array" anyway and sometimes I wasn't too sure back when I was scripting hangman. Example: playerNamesArr
     
  12. sulcata

    sulcata stéphane curry best waifu Forum Moderator Server Administrator Forum Moderator Server Administrator

    Joined:
    Jun 13, 2012
    Messages:
    968
    Likes Received:
    744
    It should be clear what type a variable is based on its usage and documentation of other functions.
     
    Nightfall Alicorn and Duster like this.
  13. Duster

    Duster dodgerswin 2018

    Joined:
    Sep 23, 2013
    Messages:
    378
    Likes Received:
    698
    not only what sulcata said, but you should be able to infer the type from the name:
    playerCount - number
    isPlaying - boolean
    playerName - string

    however with something like an array i can see where that might be kind of helpful
    players - could be array or object (associative array)

    so if it's helpful i guess something like playersNameArray would be ok (although i'd personally just use playersName)
    don't use playersNameArr though, no point in making it less clear just so save 2 letters, and i dont see how it's "less confusing" than playersNameArray
     
    sulcata and Nightfall Alicorn like this.
  14. coyotte508

    coyotte508 Well-Known Member Administrator Server Owner Administrator Server Owner

    Joined:
    Apr 21, 2010
    Messages:
    6,363
    Likes Received:
    167
    No. The idea to use things like bVariable or iVariable is a pre-2000 Microsoft standards that was then given up and is obsolete.
     
  15. Nightfall Alicorn

    Nightfall Alicorn Left Pokémon Online, most likely not coming back.

    Joined:
    Oct 15, 2013
    Messages:
    491
    Likes Received:
    171
    PO Trainer Name:
    Nightmare Moon
    Quick update before I forget again.
    • Global variables changed to camel case.
    • Functions added as camel case.
    • Constants added as camel case w/ first letter cap.
    I don't know why the variable "SESSION" is all caps though since it does have values being added, removed and changed.

    Anyway, if there's anything I've missed or changes suggested. Let me know.
     
  16. MidwayMarshall

    MidwayMarshall woof Forum Moderator Developer Forum Moderator Developer

    Joined:
    Jun 13, 2014
    Messages:
    303
    Likes Received:
    170
    myengine.globalObject().setProperty("SESSION", myengine.newQObject(mySessionDataFactory), QScriptValue::ReadOnly | QScriptValue::Undeletable);
    in my java coding experience static globals are written in all caps. While it has its properties changed, it always refers to the same instance.
     
  17. Camilo

    Camilo Member

    Joined:
    Apr 10, 2014
    Messages:
    53
    Likes Received:
    2
    I Recommend to set global variables syntax to: $Name like ruby

    Ej.

    $Utils
    $AnyThing
     
  18. sulcata

    sulcata stéphane curry best waifu Forum Moderator Server Administrator Forum Moderator Server Administrator

    Joined:
    Jun 13, 2012
    Messages:
    968
    Likes Received:
    744
    This is Javascript though, it just seems like an extra character, similar to Hungarian notation as discussed previously. In all honesty we should probably just find a reputable style guide and link to that. I don't know any off the top of my head though.

    edit: jQuery's seems relatively sane and short: https://contribute.jquery.org/style-guide/js/
     
    Last edited: Dec 23, 2015
  19. Nightfall Alicorn

    Nightfall Alicorn Left Pokémon Online, most likely not coming back.

    Joined:
    Oct 15, 2013
    Messages:
    491
    Likes Received:
    171
    PO Trainer Name:
    Nightmare Moon
  20. sulcata

    sulcata stéphane curry best waifu Forum Moderator Server Administrator Forum Moderator Server Administrator

    Joined:
    Jun 13, 2012
    Messages:
    968
    Likes Received:
    744
    1. ok
    2. kind of vague way of explaining it. I believe if the left hand side is "falsy" then the logical or operator returns the right hand side (not a boolean value!).
    3. don't use "new Array()", [] is much more common and has a few advantages that I can't remember off the top of my head.
    4. don't do this please, arrays should have entries you can access in an indexed for loop, this completely breaks that. This is what most people expect to use them for.
    5. ok, make sure it's readable. Cramming a bunch of variables on one line can look messy.
    6. ok
    7. ok
    8. ok????
    9. Don't do this ever. Just use an object with the necessary properties if the function header gets too long. If you need a variable number of arguments, then you should probably consider an array. This is also awful for doc generators.
    10. Don't use this for arrays, it can potentially loop over non-array indices and makes it ambiguous if you're dealing with an array or object. Just use the forEach method or an indexed for loop.
    11. charAt is more clear with intention imo, but I guess it doesn't matter that much. Makes it less ambiguous with arrays.
    12. This was covered on an earlier pointer they made.
    13. Don't do that, it obfuscates code and isn't readable.
    14. Or we could just use the much more flexible if-else chain.
    15. I could be mistaken, but the writer seems to think there's a separate float and int type. JavaScript only has one numeric type (double floating point precision).
    16. Using the increment operator in expressions can be unclear at times, it's a very fine line and I wouldn't recommend doing it all that often. Same thing for using assignment operators in separate expressions.
    17. ok
    18. ok
    19. Double bitwise for rounding is nowhere near as clear as Math.floor and it actually has different outputs in a few edge cases.

    Most of the stuff there seems like either common sense or bad practice. I don't know why they bothered to demonstrate how the not operator and if statement work of all things. I'm really surprised they didn't mention short-circuiting of logical operators, which is really important to know even if you don't utilize it intentionally. I mean just looking in the comments after I've written this all out it seems like a lot of people are finding flaws in the article (such as the variable||'' statement). One should code so that someone reading their code can tell more or less at first glance what is going on. Shortness doesn't equate with simplicity, only obfuscation.
     
    Last edited: Feb 20, 2016
    Nightfall Alicorn and Duster like this.
  21. Fuzzysqurl

    Fuzzysqurl baa baa mareep I do what I want Server Owner Developer I do what I want Server Owner Developer

    Joined:
    Sep 12, 2012
    Messages:
    2,096
    Likes Received:
    967
    Just want to point out the obvious since it might not be so obvious right now to some people: Shorter code !== Better code