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

I'd say that it is one of the few cases where comments are the best solution.

You can't have functional code for what isn't done, so that's some information you can't express in code.

Furthermore, a major problem with comments is that you can't debug or test them. There are many tools that can analyze code, static or runtime, but because comments are just free text, you can't do much besides spellchecking. Also it is common to forget to update comments, and with the lack of testing, in the end, you get lies.

But here, the only maintenance these comment need is to remove them if they stop being relevant. For example because you finally did the thing you said you wouldn't do, or just scrapped the part. Very low effort, also rather easy to spot, since if you see a thing being done with an explanation on why it is not done, it means someone forgot.

It is also worthwhile because as programs grow, they tend to do more, and "not" assumption may no longer hold (there used to be 4 parameters, now there are 10000...), meaning it is something you should check.

A lot of slow code comes from an assumption that N will be small, and N ends up being big. By the way, that's why I favor using the lowest O(n) algorithm that is reasonable even if it is overkill and slower on small sets. Because one day, it may not be. If for some reason, using a low O(n) algorithm is problematic, for example because the code is too complex or the slowdown on smaller sets too great, then comes the "why not" comment.






In his specific example, a comment is not the best solution. You can create self-documenting code easily with an interface and an implementation, also commonly referred to as the strategy pattern.

Interface expresses “what the function does” while the implementation expresses “how it’s done with what tradeoffs”.

Bonus, in the future, if performance ever does become a problem, you swap in the new optimized implementation behind the existing interface.


Interfaces are not free. Depending on the implementation, and how you use them, it can have significant runtime costs, some compile cost (though usually negligible) and most importantly, code complexity.

When you see a call to an interface, you don't know what the code does concretely, you only know what it is supposed to do. The actual implementation and how it ties to the interface may by in a completely different place. It is one of my biggest source of headaches when debugging code.

Interfaces are useful, the strategy pattern is useful, but overuse is harmful. My idea is to not use an abstraction unless I know I am going to need it. For example, let's say I need to decode video, and I have a hardware decoder and a software decoder. Here, an abstraction make sense, as I know the software decoder will be prohibitively slow one some platforms, and the hardware decoder won't always be supported. But if the optimized version is sufficiently better so that it makes the old version obsolete, just change the code.

And if I don't know if I will need to change strategies later, I just write the first strategy, and if it calls for an interface later, only then I will do the abstraction.


It would be super cool if you could provide a list of line ranges for comments. Like "this comment covers lines 12-14".

I suppose if you make the refer nces fancy enough you wind up reinventing rst


This is actually really easy to do in most languages by wrapping the code you want to comment in a function.

  func uglyHackForCombiningTwoThings() {  
    // Do whatever ugly thing you want to do  
  }

You don't need a function, a simple {} block is enough if the language supports it. Some languages (ex: Python) don't have that though, you may need a function, or some other construct (ex: if true) in this case.



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

Search: