Better Comments

  • Comments posted to this topic are about the item Better Comments

  • I've just finished reading "Clean Code" by Robert C Martin.  It takes a dim view of commenting code preferring instead to refactor the code to the point where all functions and methods are simple and have meaningful names.  The view is that if the name of your function cannot express what the function does then the function is probably too complex and needs refactoring.

    It also emphasises the order in which the properties, methods and functions appear in a program.  Reading from top to bottom the main method should read like a summary of what your app does.  Below that comes the functions that it calls as the details of the summary.

    Personally I like having JavaDoc type comments and the tool to assemble them into a publishable format.  But then I enjoy documenting things and the disciplines that are required to keep this up-to-date.
    The problem is that the comments are not intrinsically connected to the code so nothing verifies that the comments match the code.  Perhaps the better approach would be to use BDD as the documentation or to focus on commenting the tests rather than the app code?

    When committing something to source control the text for the commit comment is "When applied this..." followed by whatever the commit is actually trying to achieve.  This encourages small commits of workable code.

    In terms of commenting databases using the MS_DESCRIPTION extended property for DB objects allows Red-Gate SQLDoc to pick up the descriptions.  Other databases seem to have standardised on using the COMMENT ON object IS 'suitable description'; syntax.
    If you don't attach useful business descriptions to your database objects then you will reap the wind.

  • Comments can actually make debugging a problem harder. For example: if the comment says this produces a specific date and the code does not do that, which is right? If you can't read the code then you can't debug the program. Writing comments is like writing paragraphs about a symphony - if you can't play the music, reading about it won't help.

  • Agree with the above. The problem with comments is that they are not maintained and become out of date quickly. I prefer code with very few/no comments (refactoring to give meaningful names, single responsibility etc). If I need to check something I can look at the version history and see what the check-in comments were and which work items they relate to, as these will have a lot more detail. Most of the time I don't need to do this so comments are just clutter.

  • LindaEwen - Friday, June 8, 2018 1:40 AM

    Comments can actually make debugging a problem harder. 

    Well yes, just the same as building a garden wall can make it harder to get into your house, if you forget to put a gate in it.  Doesn't mean you shouldn't do it - just do it properly.  And even the simplest code isn't necessarily going to help the reader understand why the code was written, or when, or by whom.  I agree that comments such as  -- clear the table in front of a TRUNCATE TABLE statement aren't helpful, though, and just add to the noise.

    John

  • David.Poole - Friday, June 8, 2018 1:21 AM

    I've just finished reading "Clean Code" by Robert C Martin.  It takes a dim view of commenting code preferring instead to refactor the code to the point where all functions and methods are simple and have meaningful names.  The view is that if the name of your function cannot express what the function does then the function is probably too complex and needs refactoring.

    It also emphasises the order in which the properties, methods and functions appear in a program.  Reading from top to bottom the main method should read like a summary of what your app does.  Below that comes the functions that it calls as the details of the summary.

    Personally I like having JavaDoc type comments and the tool to assemble them into a publishable format.  But then I enjoy documenting things and the disciplines that are required to keep this up-to-date.
    The problem is that the comments are not intrinsically connected to the code so nothing verifies that the comments match the code.  Perhaps the better approach would be to use BDD as the documentation or to focus on commenting the tests rather than the app code?

    When committing something to source control the text for the commit comment is "When applied this..." followed by whatever the commit is actually trying to achieve.  This encourages small commits of workable code.

    In terms of commenting databases using the MS_DESCRIPTION extended property for DB objects allows Red-Gate SQLDoc to pick up the descriptions.  Other databases seem to have standardised on using the COMMENT ON object IS 'suitable description'; syntax.
    If you don't attach useful business descriptions to your database objects then you will reap the wind.

    I do kind of agree with that in general. What can be useful is WHY code is doing a particular thing - I find this prevents someone coming after going on a journey trying to work out why an obscure thing is being done, thinking it's useless and deleting or circumventing the code, only to find out the reason through breakage. Comments for intent only is my general rule of thumb - unless it is to explain some really obscure operation.

  • I like comments that tell you who wrote the code. Then you can find them and take appropriate action!

    -- Andy Robertson 2018/06/08 I apologise for the following code - it is fubar

  • Concur I try to keep commenting to a minimum but do work on making things like function names very meaningful and I will try and ensure that I have meaningful error trapping in place along with decent formatting of things like spaces tabs and returns which seems like a small thing but I find it helps me view the code.

    Additionally if I have to call queries /views /procedures within a function I will try and name the views  / procedures in some kind of way that allows me to sort them in some kind of logical way that relates to an approximation of the order in which they need to be run.

    I use a blog to write up the more complicated structures and I will generalize the various parameters so I can drop into new projects this took a while to build up a decent library of code and structures but I get some big dividends from it now and the second time I implement a pattern I will typically be many multiple times faster than when I first figured it out. I also find that I can refresh myself on my structures much much quicker which prevents me from forgetting them its just a win win. When I have to re-implement a pattern I use some of the extra time I save to see if I can improve on my original and I will feed that back to my code library. If I have implemented something many times it is unlikely I will be able to improve on it.

    It also gives me more confidence in meetings when someone asks me to do something new. I know I've done it before and I know I have template code and I can better judge how long and what I can promise to commit to.

  • I follow the Pep 8.0 standard when doing comments in Python. I follow the same standard for the most part in SQL.

    I also mix this with the Google Python Style Guide to even further enhance my code and comments.

    So, does this help in the long run when it comes to code comments? Sure. When you start getting into complex projects, I've often have forgotten what things do. Take the below code example with a simplistic algorithm that's written in such a way that humans can easily get confused.


    def array_query(s, t, i, j):
    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    When I wrote this code with a Google engineer helping me out, it's pretty fresh in my mind. But, going back to it over a long period of time can be hard to understand what's going on at first glance. For new eyes on the project, it can also be very confusing on what's going on unless you're just that good. You toss in comments, then at least you get an idea that hey, this is simply taking an array of objects and just shifting them to the front or back of the array based on input.


    def array_query(s, t, i, j):
    """ A simple algorithm to shift a range of positions to front or back of the array.

    Type 1 Query that modifies the given array by removing elements from i to j and adding them to the front.
    Type 2 Query that modifies the given array by removing elements from i to j and adding them to the back.

    :param s: The query string we are working with
    :param t: Query Type. 1 moves to front of array, 2 to the back
    :param i: N starting number for range
    :param j: N ending number for range
    :return : New array with the chopped number ranges specified from i and j.
    """

    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    The style guides, especially the Google Python Style Guide help a lot in helping define what your SHOULD do in terms of comments. For example, when it comes to all your functions and classes, adding your typical header/doc strings to the code to help you define what is going on. What the purpose is, what params you are passing, what you are returning, defining some examples of usage and even what error catches you have defined.

    I follow the same in SQL with the help of SQL Prompt. I put headers on every stored procedure that defines the purpose, examples, and so forth with the history of authors who last touched it. The same is true for each major SQL statement with it's own small header to define what's going on. I think in the long run, it helps a great deal with getting a quick download of large and sometimes complex code.

    Here is my final submission for the above code. This would be further enhanced with an example input and output.


    def array_query(s, t, i, j):
    """ A simple algorithm to shift a range of positions to front or back of the array.

    Type 1 Query that modifies the given array by removing elements from i to j and adding them to the front.
    Type 2 Query that modifies the given array by removing elements from i to j and adding them to the back.

    :param s: The query string we are working with
    :param t: Query Type. 1 moves to front of array, 2 to the back
    :param i: N starting number for range
    :param j: N ending number for range
    :return : New array with the chopped number ranges specified from i and j.
    """

    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    if __name__ == "__main__":
    input_size = map(int, raw_input().split()) # Array size, Total Queries
    source_array = map(int, raw_input().split()) # Input array

    for case in range(0, input_size[1]):
    test_case = map(int, raw_input().split())
    array_query(source_array, # a[ ] = Input Array
    test_case[0], # q[0] = Query type
    test_case[1], # q[1] = i range (Min)
    test_case[2]) # q[2] = j range (Max)

    print abs(source_array[0] - source_array[input_size[0] - 1])
    print ' '.join(map(str, source_array))

  • xsevensinzx - Friday, June 8, 2018 5:31 AM


    def array_query(s, t, i, j):
    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    Code like this would need comments for sure. But why not change the names of things instead so that it is more obvious what is going on? i.e. rename "array_query" to "shift_sub_array", rename 's' to "query_string", make t an enum so you know what 1 and 2 mean, etc.

  • funbi - Friday, June 8, 2018 5:48 AM

    xsevensinzx - Friday, June 8, 2018 5:31 AM


    def array_query(s, t, i, j):
    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    Code like this would need comments for sure. But why not change the names of things instead so that it is more obvious what is going on? i.e. rename "array_query" to "shift_sub_array", rename 's' to "query_string", make t an enum so you know what 1 and 2 mean, etc.

    Yeppers, that can surely happen after with additional passes. This was just for a challenge I did with a partner to try and computate like a hundred million query strings within a few seconds. When you write stuff like this, you tend to stick to simplistic approaches with variables, names, like (a + b) / c and so forth.

    In this example, we were given s, t, i, and j as the default example inputs. We just stuck with them to work through the problem.

  • xsevensinzx - Friday, June 8, 2018 5:58 AM

    funbi - Friday, June 8, 2018 5:48 AM

    xsevensinzx - Friday, June 8, 2018 5:31 AM


    def array_query(s, t, i, j):
    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    Code like this would need comments for sure. But why not change the names of things instead so that it is more obvious what is going on? i.e. rename "array_query" to "shift_sub_array", rename 's' to "query_string", make t an enum so you know what 1 and 2 mean, etc.

    Yeppers, that can surely happen after with additional passes. This was just for a challenge I did with a partner to try and computate like a hundred million query strings within a few seconds. When you write stuff like this, you tend to stick to simplistic approaches with variables, names, like (a + b) / c and so forth.

    In this example, we were given s, t, i, and j as the default example inputs. We just stuck with them to work through the problem.

    I thought maybe variable name length affected performance or something o.O (spot who doesn't know Python! o/)

  • funbi - Friday, June 8, 2018 6:07 AM

    xsevensinzx - Friday, June 8, 2018 5:58 AM

    funbi - Friday, June 8, 2018 5:48 AM

    xsevensinzx - Friday, June 8, 2018 5:31 AM


    def array_query(s, t, i, j):
    if t == 1:
    s[:0] = s[i-1:j]
    del(s[i+(j-i):j+(j-i+1)])
    elif t == 2:
    s += s[i-1:j]
    del(s[i-1:j])

    return s

    Code like this would need comments for sure. But why not change the names of things instead so that it is more obvious what is going on? i.e. rename "array_query" to "shift_sub_array", rename 's' to "query_string", make t an enum so you know what 1 and 2 mean, etc.

    Yeppers, that can surely happen after with additional passes. This was just for a challenge I did with a partner to try and computate like a hundred million query strings within a few seconds. When you write stuff like this, you tend to stick to simplistic approaches with variables, names, like (a + b) / c and so forth.

    In this example, we were given s, t, i, and j as the default example inputs. We just stuck with them to work through the problem.

    I thought maybe variable name length affected performance or something o.O (spot who doesn't know Python! o/)

    Nope! Style is what defines really what you should use. That's the point of pep and Google style guide. You have certain rules in how you name things. This does not break it, but it would recommend exactly what you said to help make it readable. But that goes hand-and-hand with style of comments too.

    When you get into naming things single character variables, you often still check the doc strings for reference of what that variable means, which just makes it harder to read. Comments shouldn't be something you constantly have to reference (i.e.: s versus query_string). Should be there to give you a good understanding. Then the code should take you on that ride to the finish.


    s[:0] = s[i-1:j]

    versus


    query_string[:0] = query_string[range_min - 1:range_max]

    Performance improvements on this code was major when we took the approach of slicing and dicing in the source array versus creating a whole new array like many others did. The speed was dramatically faster.

  • I think commenting for the "why" part instead of the "what" is most important, but "what" can be important if it gives shape to your code. Jeff made the suggestion to me to include enough comments to be able to *just* read the comments and see a high-level workflow of what the code is trying to do .This was a helpful way to describe it for me, because sometimes something that seems obvious to the author when writing it isn't obvious to someone else who isn't familiar with the process.

    PLUS, it helps you refactor if you look back through your comments to figure out if you can make a flow and realize you either didn't explain something at all, or it's not necessary when you do try to explain it.

    Does that take longer? Absolutely. Does it force me to code less confusingly? Absolutely. Of course, I still need to modify the comments when code changes, so that they explain what is actually coded, but that's just something that has to be done.

    -------------------------------------------------------------------------------------------------------------------------------------
    Please follow Best Practices For Posting On Forums to receive quicker and higher quality responses

  • I agree with the why rather than what.  A rule of thumb for this is: Does the comment include the word because?  (Or a similar word like since, means etc.)

Viewing 15 posts - 1 through 15 (of 41 total)

You must be logged in to reply to this topic. Login to reply