Comments or no comments?

There are those who like comments, and those who prefer to use (very) descriptive method names and often instead of comments. What do you prefer?

Personally, after revisiting code that I haven’t in a while ago, I am glad I left comments such as this:

# If sure order_transaction is successful AND discount was applied 
# then create referral
def create_referral(order, transaction)
end

Probably not even the best place for the comment - but I’m glad it’s there either way

1 Like

I feel that your comment just reiterates the code, especially if coded in small, incapsulated methods:

def order_flow
  if order_transaction.success? && discount?
    create_referral
  end
end

conveys the same information as your comment for me.

So, yeah, I’m in the other end. I don’t like comments that just reiterates the code. What I need in comments are more an answer to why.

3 Likes

Yeah, I’ve got something to that affect too… but I kinda like having a narrative - I mean, it’s easier to understand English (especially in the way you would normally speak it) than code (even Ruby).

I started doing a lot of this after reading some of Nando Vieira’s paypal-recurring gem, I was so impressed by the comments because they almost act like a manual:

https://github.com/fnando/paypal-recurring/blob/master/lib/paypal/recurring/base.rb:

      # Request a refund.
      #   ppr = PayPal::Recurring.new({
      #     :profile_id => "I-VCEL6TRG35CU",
      #     :transaction_id => "ABCEDFGH",
      #     :reference      => "1234",
      #     :refund_type    => :partial,
      #     :amount         => "9.00",
      #     :currency       => "USD"
      #   })
      #   response = ppr.refund
      #
      def refund
        params = collect(
          :transaction_id,
          :reference,
          :refund_type,
          :amount,
          :currency,
          :note
        )

        request.run(:refund, params)
      end

      # Retrieve information about existing recurring profile.
      #
      #   ppr = PayPal::Recurring.new(:profile_id => "I-VCEL6TRG35CU")
      #   response = ppr.profile
      #
      def profile
        request.run(:profile, :profile_id => profile_id)
      end

      # Collect specified attributes and build a hash out of it.
      #
      def collect(*args) # :nodoc:
        args.inject({}) do |buffer, attr_name|
          value = send(attr_name)
          buffer[attr_name] = value if value
          buffer
        end
      end

Then DHH wrote that post about using highly descriptive method names instead, and being lazy, I adopted that. Looking back now tho, I think I prefer more commenting - because I feel it makes things much easier for when you go back. I also think I am not that keen on longer method names - guess there has to be a balance.

I tend to not use comments a lot and prefer code that is clean and elegant, to the highest practical extent. This isn’t always the best strategy, since code sometimes needs some complication to work properly (e.g., in a game), but I often feel like writing a bunch of comments to explain the code detracts from the beauty of it (assuming the code in question is beautiful). Also, writing comments between writing code exhausts me and often makes me write worse and less code (plus I feel like I’m repeating myself, which I hate doing).

Granted, I sometimes write comments for really quirky stuff that I definitely won’t remember, but mostly I try to write code that speaks for itself and doesn’t require too much thought or explanation.

1 Like

Anytime you write a protocol (a standard to be accepted by all) it should have very thorough comments. If you’re writing anything that has a reason for specific implementation that should at least be commented. If you want to maximize the amount of people who use your library you should document every method. Those who don’t care for comments aren’t prevented from using code that has them. And many people won’t use code that isn’t properly documented.

I’m a fan of what the Rust language is doing in writing documentation on everything extensively that automatically gets exported into visually appealing documentation. It’s nicer when we don’t have to write the documentation separately from the code because then we’d have to manage the code in two places to make sure either is out of date. OH! And Rust’s code comments get evaluated with testing to verify correctness! Sweeeet!

Ruby has some great libraries for documenting methods. I prefer YARD for a minimalist approach. I don’t generate local documentation, but I appreciate all of the Ruby websites that have turned the gem libraries rdocs into web pages we can lookup.

All that being said I generally don’t document code unless it’s for others.

2 Likes

I use comments as documentation.

Documentation for those consuming the api. How to use the api.

Documentation for those maintaining the api. Why it’s written this way.

I try to only comment at the method level.

I also write pretty extensive commit messages. git blame and git log are under appreciated sources of documentation.

1 Like

One place I would appreciate seeing comments is where dependencies are included. Just a brief mention of what it is and what part of the application it is meant for. So comment the Gemfile :gem:.

2 Likes

I used to be a comment minimalist. But the more I return to my code, the more I’m tending to add comments. To explain how far I’m moving it would be worth describing some end points:

Bad
Comments that just repeat what the method name does:

# Add one to number
def add_one_to(number)
  number += 1
end

That comment adds absolutely no value - and is just some additional content that needs to be managed. If a method definition explains the functionality then you should not add comments. Only add comments if they add value.

In fact I would go further than that - writing methods so that they self-document is good practice. In my book, the above is bad, but this is worse:

# Add one to number
def aot(n)
  f(n, 1)
end

Comments should only ever be a clarification - they should never be the only explanation of the functionality. If you have to comment for people to be understand what your code is doing, then you need to rethink the way you code.

Good
The one file that I almost always add comments to (and one I think is too often not commented) is Gemfile. The main issue is that it is not always clear from the name of a gem, what functionality that gem is adding. The occasion that brought this home to me was when I was trying to track down where some database functionality was coming from. The functionality was added by the texticle gem, but it took me a lot of time checking through the READMEs of other gems before I worked it out. So now, if the name doesn’t obviously describe what the gems does, I will added a comment describing the gems functionality and/or why it’s been added to the app.

Another place I will always comment is where I have taken an unusual decision in the way I code. For example, because of an obscure bug I have had to handle an object in an unusual way. Such things should always be commented.

Inbetween
Recently I’ve started to comment classes. That is, I’ll add a comment to the class object describing what it does. It can often be difficult to choose a concise class name that fully describes what the object does and/or its place in the application. It is easier at the method level because what a method does is so much more limited. But a class is that little more complicated and therefore, that little more difficult to describe just by it’s name.

2 Likes

Yes. I comment up the gem file.

I will also try to include this in the commit message.

Added some really cool feature.

blah, blah, blah...

In support of this feature, added the following dependencies

- some_gem
- another_gem
2 Likes

Do you use long format commit messages then? Rather than the brief git commit -m "did the thing"

1 Like

Yes.

I try to format commit messages like this:

A summary that would make a good change log entry

A detailed description of the change. Could include why the change was made.
Might also include documentation about how this feature could be used. This
is also a good place to include research links, etc.

Details could be several paragraphs.

The end could include additional footnotes:
- dependency changes
- additional hyperlinks
- etc.

Here’s a blog post on using commit messages and git blame as hidden documentation: http://mislav.net/2014/02/hidden-documentation/

2 Likes

Awesome! They have a Vim plugin. :slight_smile: . What’s the way to enter a longer commit message? I don’t recall atm.

1 Like

From the command line, you just type git commit. No -m.

Vim users should definitely get GitHub - tpope/vim-fugitive: fugitive.vim: A Git wrapper so awesome, it should be illegal.

Emacs users should definitely get magit.

2 Likes

Great point - that the git commit messages are an important part of the documentation.

I once worked on a project where every commit message was “done what you fucking told me to do”. Unsurprisingly, that said all you need to know about that project.

1 Like

Also do other people think of their tests as a form of documentation?

Tests can be a useful place to see how a developer expects their code to be used. They can provide good examples of how different objects may be passed to methods, and the way in which the developer expects objects to be used.

And don’t forget the README. I hate projects that don’t have a decent readme.

2 Likes

Yes, each development need à full coverage with RSpec. Used while I develop and for explain what is expected in normal usage. Useful for any further evolution on the code, but not so easy for developers who just want use it (as a lib, or a gem). In this last case, documentation and comments are preferred. So, I think it depend what is your target.

2 Likes

Tests as examples? Yes.

Tests as documentation? No.

Tests make really nice, isolated examples. But they can’t tell the whole story. That’s why I think you you need all of those things. Comments, README, Changelog, Commit history, tests, etc. It’s all part of telling the story.

3 Likes

Thankfully not. Minitest: keep it simple. keep it ruby.

2 Likes

Long ago, I was told by someone that I respected that good code should be self-documenting. This is back when I was doing Java, and I didn’t agree right away, because I believed that comments were useful to describe portions of logic, for Javadocs, etc. However, the more that I thought about it, the more I saw opportunity for smaller methods with better names, better variable names, better class names, and overall better design. Eventually, I got to the point where comments were hardly every necessary. A few years later, I had started into Ruby. Over the last several years in Ruby I’ve found that, whenever I use a comment, it is almost always because I’m doing something wrong.

When they are wrong:

  • Comments are often an unnecessary crutch for not having smaller methods and better variable and method names.
  • Comments are a crutch for lack of clarity.
  • Comments are a crutch for something that can be done in a better way.
  • Comments can get out of date.

Some exceptions:

  • If have to explain why you are having to patch something, and only when necessary.
  • If you must indicate why you are using or not using a gem or certain version/commit of a gem, as was mentioned by another commenter.
  • If you are writing an API where the comments will help generate docs, and if those docs are really needed and not a crutch for poorly named methods and classes (e.g. Ruby standard library, Rails). Note that other documentation may need to accompany the API docs (e.g. readme, Rails guide), as mentioned by another commenter.
  • If they make something visible that frequently needed and automatically updated (e.g. the annotate (AnnotateModels) gem).
  • If you need markers to fix something later (e.g. TODO comments).

But, I think it is helpful to first consider a comment a possible indicator that there is a better way of doing something.

2 Likes

Here are two conferences talks involving comments. They feel differently on documenting methods.

MountainWest RubyConf 2015 - Message Oriented Programming

RubyConf 2015 - Communicating Intent Through Git by Josh Freeman

1 Like