Hacker News new | past | comments | ask | show | jobs | submit login

Comments are incredibly useful for that bit of code that you spent hours trying to make it work and you couldn't figure out a way to name things well or to improve it. That's where a comment is priceless.



The downside of course is that comments aren't compiled/run - so they often become out of date. "Often" might actually be an understatement.

I can't tell you how many times I've been reading a comment that runs quite contrary to what the code really does. You then end up reading the code to reason about it anyway, paying two taxes. After too many of those experiences, you just end up going straight to the code as the source of ground-truth.

This all depends on the readability of the code / and how soon these comments get out of sync. Maybe my experience is atypical, but I doubt it.


Names for classes, methods, parameters, and variables all suffer from this same problem. I think the solution to align code and comments is code reviews. Not writing comments also works but fails to solve related issues.


Where I work, I've always required that code that's submitted for review has a descriptive commit message. That is, the commit should explain what the problem was and how it was fixed, and why it was done that way.

This way, I can run git blame (or the equivalent VCS command) on the file and get a reasonable set of comments that usually match up with the code.


I'm sure a lot of people are hoping that one day we can generate code just by writing the comments and leaving the machine to do the rest.

I certainly am.


More structured alternatives to comments make that kind of thing much more possible, e.g. https://hackage.haskell.org/package/djinn


Maybe it's because I write in Ruby, and so never have to do any tricky optimizing, but if solving a particular problem starts to run over a half hour, I look to re-architect the project, either by reaching for a gem or telling my boss that X is too hard and we should do Y instead. My patience for going down rabbit holes has mostly gone over the last year.

Also, again perhaps because I use Ruby, it never takes me more than a few seconds to name something. If it does, then it's a code smell and I go looking for the missing class.


I don't see how Ruby saves you from optimising (to my limited knowledge, it's not exactly a fast language), but I agree with you that naming stuff sensibly and extracting functions (which you can then name sensibly) is most important for maintainability and can make "in-code" comments unnecessary in many cases. However I strive to always document what a function does if its not obvious -- though I'd call that "documentation" and not "comment".

Example for obvious: Int add(Int x, Int y) in a typed language. Example for not obvious: add(x, y) in an untyped (or "dynamically typed") language (Does it auto-coerce? How? Can it add complex numbers? In my particular representation? ...).

Someone mentioned that sometimes comments are useful e.g. to document a quirk/bug in library function you call, and I have some examples of that in my own code. But most often you should be able to rectify that by wrapping said function in your own one that omits the problem.

If a function seems impossible to give it a sensible name that isn't ridiculously long, split it up. The more clear code of the individual parts and how they are combined should give a hint of what is actually computed here. Maybe it's a new concept in your business logic, in which case providing a clear and exact definition makes sense anyway (put it into the appropriate place in your documentation). This whole procedure can take a significant amount of time, but it will be worth it in maintainance!


> I don't see how Ruby saves you from optimising (to my limited knowledge, it's not exactly a fast language)

That's precisely why you don't optimize. If you find you need fast code, you use a different language. Ruby is the language you use when maintainability and extendability take priority over speed. It's excellent for web development, where any speed improvements you make will ultimately be dwarfed by network latency.

> Example for obvious: Int add(Int x, Int y) in a typed language. Example for not obvious: add(x, y) in an untyped (or "dynamically typed") language (Does it auto-coerce? How? Can it add complex numbers? In my particular representation? ...).

That's a good observation, and it's made me think about how I deal with this in Ruby. First, generally you can tell by looking at a method's code what it's expecting you to pass to it.

Second, you don't generally pass around complex types to library functions, you use basic Ruby value objects like strings, symbols, hashes, and arrays. A gem will often define its own classes, which you might pass objects of around, (money, phone numbers) these will often be the primary focus of the gem, and how to use these objects will be written right there in the documentation. These classes will typically have "parse" functions that will take random input and turn it into a more useful object.

In Ruby, you generally only pass around complex objects in your own code, using JSON or some other format to interact with external systems


> That's precisely why you don't optimize. If you find you need fast code, you use a different language.

Ah, now I get you :)

> First, generally you can tell by looking at a method's code what it's expecting you to pass to it.

Here we might differ, I would always prefer to state clearly in the function doc what types of parameter values are allowed. For example, even if you have a really simple little wrapper in javascript:

  function log(x) {console.log(x);} 
Without documentation, you have to know what console.log can do for different types. So I'd definitely prefer this:

  /** 
   * Logs x to console.
   * @param x a value of a primitive type (other types are not guaranteed to be logged in a readable manner). 
   */
  function log(x) {console.log(x);}
> A gem will often define its own classes, which you might pass objects of around, (money, phone numbers) these will often be the primary focus of the gem, and how to use these objects will be written right there in the documentation.

Yes exactly, it will be documented as any public API should be. I have no problems using opaque types. But a function call(x) which expects x to be some object representation and not any old string (for which the library has constructors, e.g. PhoneNumber(string)) should surely document this, no?


In my book it goes 1. types 2. tests 3. method/variable names 4. comments. If you can't make the code clear any other way then add a comment, but it should be a last resort.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: