Ren'Py about documenting code

GNVE

Active Member
Jul 20, 2018
701
1,158
So I guess this is a pretty novel question on this forum. I just wanted to know about documenting code. I'm trying to be a good boy and document my code properly (or good enough at any rate.) I'm still pretty new and wanted an outsider perspective if what I'm doing is good enough; am I going overboard or should I document more?
Below I provide some code and would like some feedback from the more experienced programmers :) The code provided is part of the event handler that will run the game and make the game easily updateable (or make it possible to mod in events).

Example 1:
Python:
def addcalendar(txtfilenumber):
        """addcalendar(textfilenumber) takes a textfile chops it's contents into tuples and then triggers the addtuple fuction to add the individual tuples to the calendar variable.
        textfilenumber is the numer of the textfile that needs to be read.
        textfiles for mods should be odd numbers. even numbers are reserved for the game.
        """

        x = [ i.strip() for i in renpy.file("txt/" + str(txtfilenumber) + ".txt") ]

        for j in range(len(x)):
            x[j] = tuple(x[j].split(","))
            addtuple(x[j])
Example 2:
Python:
def calendarsort():
        """calendarsort() does what it says on the thin it sorts the calendar after start or after load to make sure the events play in the right order."""

        global calendar

        for i in calendar:
            for j in range (1,8):
                calendar[i][j].sort()
Example 3:
Python:
def firststart():
        """firststart() is called upon when a new game is started. it will read the files in the txt folder in the game folder.
        the game can read files up to 25000. but will stop at the highest 1000 found. e.g. if you wish the game to read file 1001.txt another file called 2000.txt should be present in the folder (keep txt files that are multiples of 1000 empty). (I hope this will increase gamespeed on first start and after load.)

        for modding txt files should always be odd numbers. Even numbers are used for game files
        One event per line
        eventlines should be built as follows:
            week,weekday,time,whentrigger,label

            week 90 - 99 before start academic year
            Week 80 - 89 after end academic year
            Week 01 - 52 Academic year (academic year is not 52 weeks long but space is reserved anyway_

            weekday mon (1) - sun (7)

            time 0000 - 2400 (time between HH00 - HH04 is reserved to resolve schedule conflicts)

            whentrigger a quick selection for the eventhandler (if pc is not part of Scholastica those events can be ignored.) If it should trigger for multiple memberships just use the 'all' ID.

            label is the label needed to start the event.

            correct eventline example:
                91,1,1205,all,startprologue
        """

        global txtcheck
        global txtloaded
        global txtnotloaded
        number = maxcheck()



        for i in range(0,number):
            if renpy.exists("txt/" + str(i) + ".txt") == True:
                txtloaded.append(i)
                addcalendar(i)
            else:
                txtnotloaded.append(i)

        calendarsort()
 

Forix

Member
Apr 21, 2017
490
616
Professional programmer here in the video game industry.
Disclaimer : I will try to preach for cleanliness and simplicity, however I am no saint. I often fails to respect my rules ;) No one is perfect.

On paper and during courses, they will tell you to always document your code. The rule of thumb I tell the juniors I coach is that your code should always be as self-explicit and clear as possible. Documentation and comments should be additions to it to explain special logic, counter-intuitive algorithm (or choices), hacks. It has to be additive, not exclusive.

Variable and function names often gives you a lot of information about what is going on. Naming variable generic thing like x, varX, myVar is not super useful. Exception made for iterator (for i, etc).

When your function needs a huge block of comment to explain what it does : Split it up. A function should always be small and simple
We are rarely document a lot, due to time pressure and other factors. I rarely fall into people code where I see doc. I need to understand on my own what the fuck is going on, what were the intentions and what is that thing supposed to do. Hence why I find it important for your code to be self-explicit. Ask yourself : is my comment/doc adding anything important that can be easily missed or not quickly understood.

Based on this:
  • Comment about calendarsort --> does not add more (the function name is always ready explicit). Could keep it simple to why you need to sort (that would be useful)

  • Example 3, I find it nice. You explain the expected in and out, although label should maybe renamed to startEventLabel ?
 

rayminator

Engaged Member
Respected User
Sep 26, 2018
3,041
3,140
that's good practice thing to do just in case someone that reports error in your game that you can find the problem faster
 
  • Like
Reactions: GNVE

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,581
2,219
It very much depends who might be looking at your code in a month, a year or even 5 years.

If it's just you... comment as much or as little as you like.

If it's part of a team, either now or potentially in the future... comment as little as humanly possible.
If your code requires an explanation... rewrite the code to be simpler.
Write code as if the next programmer who picks it up is a brain dead moron... because eventually, it will be.
For the most part, code should be pretty much self documenting without comments. (i.e. easy to read, understand and follow).

The exception is if you are working on time sensitive code... where the code needs to be as efficient as possible. In that case, don't simplify... document.

But we're talking VNs and largely python/RenPy here... so if it's inefficient... it's unlikely anyone will ever notice.

As someone who worked as consultant programmer for many years, working on very large systems and some very large teams... I can be sure of one constant... people who update code, forget to update the comments. And if you can't trust the comments to match the code, the comments shouldn't be there.
 
  • Like
Reactions: GNVE

GNVE

Active Member
Jul 20, 2018
701
1,158
Professional programmer here in the video game industry.
Disclaimer : I will try to preach for cleanliness and simplicity, however I am no saint. I often fails to respect my rules ;) No one is perfect.

On paper and during courses, they will tell you to always document your code. The rule of thumb I tell the juniors I coach is that your code should always be as self-explicit and clear as possible. Documentation and comments should be additions to it to explain special logic, counter-intuitive algorithm (or choices), hacks. It has to be additive, not exclusive.

Variable and function names often gives you a lot of information about what is going on. Naming variable generic thing like x, varX, myVar is not super useful. Exception made for iterator (for i, etc).

When your function needs a huge block of comment to explain what it does : Split it up. A function should always be small and simple
We are rarely document a lot, due to time pressure and other factors. I rarely fall into people code where I see doc. I need to understand on my own what the fuck is going on, what were the intentions and what is that thing supposed to do. Hence why I find it important for your code to be self-explicit. Ask yourself : is my comment/doc adding anything important that can be easily missed or not quickly understood.

Based on this:
  • Comment about calendarsort --> does not add more (the function name is always ready explicit). Could keep it simple to why you need to sort (that would be useful)

  • Example 3, I find it nice. You explain the expected in and out, although label should maybe renamed to startEventLabel ?
Thanks for your explanation it helps a lot and I can see a few improvements I can make in the code. The function in example 3 populates the calendar on the game start (there is a separate one for when a save game is loaded) so I have to think up a better name there :)
 

mickydoo

Fudged it again.
Game Developer
Jan 5, 2018
2,446
3,548
Coding is like the first year of a new school semester. Day one you start out nice and neat, everything is underlined, formatted, different coloured pens, halfway through the third term you can hardly read your own handwriting, and every second page has a some sort of doodle on it.
 
  • Haha
Reactions: t727 and GNVE

Jofur

Member
May 22, 2018
251
270
I only really comment code that actively confuses me and I'm to lazy to rewrite. Try looking up a few tutorials on self documenting code, it's super helpful.
 
  • Like
Reactions: t727 and GNVE

shark_inna_hat

Active Member
Game Developer
Dec 25, 2018
705
2,733
So there's PEP-8 and PEP-257 that covers writing docstrings in Python:


But that's just part of the story, if you want to use some automated documentation systems (eg. Sphinx) you might want to structure your comments a bit more. There are a few ways one can do it, Google style being one I like (and don't actually use), here's a link:

and an example:
Python:
def function_with_types_in_docstring(param1, param2):
    """Example function with types documented in the docstring.

    `PEP 484`_ type annotations are supported. If attribute, parameter, and
    return types are annotated according to `PEP 484`_, they do not need to be
    included in the docstring:

    Args:
        param1 (int): The first parameter.
        param2 (str): The second parameter.

    Returns:
        bool: The return value. True for success, False otherwise.

    .. _PEP 484:
        https://www.python.org/dev/peps/pep-0484/

    """
    pass
 
  • Like
Reactions: GNVE and t727

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,364
15,281
There's many things said in this thread, but strangely the most important one is missing: What documentations are for ?

No, documentations are NOT there to explain the code or how it works.
If someone want to know this, it look at it and think about it. At worse, you add some inline comments to summarize the important (and not necessarily obvious) points, or to point where there's an effective and needed intention behind this part of the code.

And, no, documentations can NOT be replaced by self-explicit code.
Whatever how explicit can be your code, this will only tell you what it do and how it do it. But as I said above, it's not the purpose of the documentation. Self-explicit code will never tell you why the code is doing it, nor why it's doing it this way.


Documentations are there to describe the function/method/class/module/whatever.
There's a reason why the two most used script languages (Perl in the Past, Python nowadays) both include an embedded documentation feature. It's because, ideally, the documentation is the first thing you write, right after you wrote the global algorithm of your program/module/class, and way before you write a single line of effective code.
"Code is there to explain the comments to the computer" ( ) And this include the documentation.

Theoretically you plane your program/module/class, writing the algorithm that describe it. Then you write the structure (the function/class/method headers), write the documentation describing each one of them in the same time. And only then, you fill this structure with code.
Now, this being said, there's a whole world between theory and practice. In 25 years in the field, I never found someone who was always sticking to the theory. But rare are the effectively good programmers I worked with that weren't documenting their code. It's just that even them have/had the bad habit to do it afterwards ; what is understandable, writing documentation is boring. I don't remember who said this, but "commenting your code is like cleaning your bathroom - you never want to do it, but it really does create a more pleasant experience for you and your guests".

Because yes, the documentation isn't just for the others, it's also for you ; "documentation is a love letter that you write to your future self" ( ). And this is especially true in the current context ; someone who don't necessarily have a lot of knowledge and that will pass years working on his game.
Therefore, the question you have to ask before writing your documentation is : While I remember this in three months ?
If the answer is "maybe", and even more if it's "probably not", then you need to put it in the documentation, dot.


Now, the problem I have with your examples, GNVE , is that they use many words to say near to nothing. And the few they effectively tell us is hard to find.

A documentation should be a synthesis of the code. It should :
  • Summarize the purpose of the function/method/class/whatever.
  • If there's alternative to this code it should explain when this [whatever] is to be used, and what are the said alternatives.
  • List the parameters/arguments, giving their type (even if explicit), their meaning, and all possible particularities.
  • Give the type, and eventually order, of the returned value, if there's one.
  • List the important points to know.
  • Point the possible extra information.
All this in a concise and as easily readable as possible way.

Ideally, someone should find the information he search just by browsing the documentation. For this:
  • Each point should have its own block, and each block should talk about a single point.
    You can have more than one paragraph if it's really needed. But if an information do not directly regard the current block, use a "see [this]", do not include the information.
  • Each paragraph should be separated by at least one blank line.
    If there's a blank line, it's something different, else it's still the same point. This permit to quickly discriminate the information.
  • Each paragraph should have an explicit start.
    The less words the reader have to read to know if it's, or not, the block he's looking for, the better it is. Therefore, the intent should come before the information. The name of the parameter before it's meaning, the purpose before the way it's done, and all.
  • When there's important things to know, make it evident that they are important.


Now for a live demonstration, your three examples:

In the first example, you give a full description of the code, while missing the important point ; the path is automatically added.
Code:
def addcalendar(txtfilenumber):
    """
         Add a raw calendar into the calendar structure.

         - textfilenumber (string) 
              Filename where the raw calendar is stored.
              The path to the file will be *automatically* added.

          /!\ WARNING /!\
          Even numbers are reserved to the game. If your mod need to add a calendar, 
         you MUST use an odd number.

          See the top of this file for the structure of the raw calendar files.
    """

The second example is better, you give only the needed information. But in a way that isn't really pleasant to read.
Code:
def calendarsort():
    """
         Sort the calendar.

         Should be called right after start and right after load, to ensure that 
        the events while always be played in order.
    """

And finally the third example is the worse. You flood the reader under a tons of information that aren't necessarily clear, or not necessarily needed here, and that are really difficult to find.
Code:
def firststart():
    """
          Automatic process of all the existing raw calendar files. 

          Which files will be proceeded depend of [...]

          This function is designed to be called when the game start. To add calendars 
         to an already started game, use /addcalendar/.

          For debug purpose, the name of the loaded files will be stored into the
         /txtloaded/ list, while the /txtnotloaded/ list will contain the name of the files 
         not used.

          /!\ WARNING /!\
          Even numbers are reserved to the game. If your mod need to add a calendar, 
         you MUST use an odd number.

          See the top of this file for the structure of the raw calendar files.
"""
Side note:
I deported the description of the structures, because it's a global information. Both /addcalendar/ and /firststart/ need this information, why one should be deprived of it ?
Plus, the person that will have to read it shouldn't have to search to what function/method/class/whatever the explanation is attached.

Also note the "For debug purpose, ...", compared to a possible "the /txtloaded/ list is used to store the...". Three words, and the reader know if this information is what he's looking for or not. Opposed to many words before discovering that it's not what he's looking for.
 
  • Like
Reactions: Rich and GNVE

GNVE

Active Member
Jul 20, 2018
701
1,158
Thanks all for the examples and input. Seems there are a few things I can improve to make things clearer. Putting some information at the top of the document seems like a good idea anne O'nymous. I already noticed that some information was important for multiple functions. I probably won't become super good at this any time soon but I may prevent myself a couple of headaches in the future.