Hacker News new | past | comments | ask | show | jobs | submit login
Thoughts on being a programmer (yelsew.com)
235 points by earnubs on Aug 14, 2012 | hide | past | favorite | 190 comments



Be yourself. Code for fun. There's hundreds of ways to write the same thing, don't be a dick about your way, but stand up for good practices. Respect those who accomplish great things, because it was a lot of work, even if they say it was a weekend practice, they took a lot of time to get to that point. If you code correctly, one line changes are possible. Learn to desire success more than you fear failure. (I like this one) Don't become the old people you hate, always try to learn new things, no matter how alien. Who cares if you're coding on production live? Right? Right? Comments are for the weak, tracing and prototyping code is not. Mistakes are inevitable *It's hard being the smartest person in the room sometimes, wear it with humility rather than pride.

My version of the list. This was fun!


>Comments are for the weak,

Care to elaborate on this ? Commenting code is bad ? Or did I miss the irony ?


I think it could be summarised as thus, in general terms:

You should never need to write a comment to explain what you're doing. If you feel you have to, rewrite the code until it doesn't need explaining in a comment.

    # this method manipulates dimensions
    def method_x(a, b, c, d)
      # a is the width
      # b is the height
      # c is the depth
      # d is a list of options
      ...
    end
That could obviously be re-written as:

    def manipulate_dimensions(width, height, depth, options)
      ...
    end
However, it may very well be the case you have to explain why some code exists, or why it wasn't done another way:

    def post_to_awkward_api(data)
      # stupid.io doesn't accept HTTP Post params
      # so we have to use a comma separated string
      silly_string = data.join(',')
      ....
    end

    def bug_fix_workaround
      # see http://stackoverflow.com/relevant-question/...
    end
Not that my examples are amazing. But there'll always be the case where another developer (or even yourself) is not privy to the thought process that conceived a particular block of code.


We could probably resolve this aspect of the argument by teaching novices that a perfect/great/accurate/otherwise-superlative name(s) is better than almost any comment.


Not at all because programming languages like Ruby parameter names don't tell the full story:

if you have def find(name) what kind of type could be name? String "Steve"?? Symbol :Steve? Hash {:first => "Steve", :last => "Jobs"} ??


That just means that 'name' is a poor name for the parameter. Have 'first_name, last_name' or 'full_name' or 'names,' for example.

In addition, I think it's a good practice to get into to try and validate parameters at the top of any method. If the values don't fit your use for them, raise an exception.


That strikes me as very Pythonic attitude. If you're going to fail, fail early. But, I know Python way better than Ruby, so it might very well be a Ruby thing too.


I'm not sure if it's Pythonic as I've never written Python. It's a habit I carried over from the .NET world, actually.


Wouldn't the Pythonic thing be to only fail after you've tried, instead of validating your parameters in advance?


Yes. It's easier to beg for forgiveness than to look before you leap. You just use your parameters regardless of types and let the exceptions fly.


Is that really Pythonic? Isn't that just general best practice in programming?


In fewer words: comment why, not what.


I prefer:

Comment why, not how.


Exactly.

Also I would say that not all comments are created equal. You comment your API's first, then implement/explain them with code, then describe why with more comments ;-)


I've met a few senior level programmers who frown on detailed commenting (or commenting at all). I cannot wrap my head around this since I consider it best practice to comment.

A reason given to me was that "it takes up too much time to comment and when you make a code change you need to make a change in the comments as well." To that I say, so what! I would like the future me (or the future programmer) to have full knowledge on what's going on in the code.


> I've met a few senior level programmers who frown on detailed commenting (or commenting at all).

If they express those views, I wouldn't call them senior.

Commenting is necessary to express invariants, and to summarize complexity that would otherwise require each reader of the code to understand the code itself in depth.

Those are actually closely related things.

Very few languages are capable of succinctly expressing sufficiently detailed invariants. Some are better than others -- maybe they support Maybe monads instead instead of possibly-NULLs. However, it's rarely possible to express -- purely in code -- what the code is supposed to do, what the input is supposed to be, and what the output is supposed to be.

Failing to express those things means that any future reader/maintainer will be forced to trace your code, in its entirety, to reverse-engineer how it is probably supposed to work. In many cases said maintainer can never know for sure without tracing your code and ALL code that calls your code -- otherwise, any change to that code could break undocumented behavior that other code relies upon.

Anyone who advocates against comments is justifying laziness, and they're wrong. The only supportable argument for not commenting is if a language is sufficiently powerful and succinct enough to express all the invariants normally expressed through comments, as well as being readable enough to permit a future maintainer to understand the design of the code without requiring them to spend an undue amount of time studying its inner mechanics.

I'm not aware of such a programming language.


  “Don’t comment bad code—rewrite it.”
  —Brian W. Kernighan and P. J. Plaugher
Is that senior enough for you?

  > Anyone who advocates against comments is justifying
  > laziness, and they're wrong
No, they are actually advocating to put more effort in thinking about stuff: how you name your functions/methods/whatever, how do you name your arguments/parameters, how do you write the code itself.

To anyone interested I recommend to get a copy of "Clean Code" and read the relevant chapter. IIRC "Code Complete" mostly agrees.


> Is that senior enough for you?

No. Have you read 70s and 80s C code? Tried tracing through the original UNIX kernel sources? Tried working with them?

To understand all the invariants of one small aspect of the system quite often requires tracing through the whole system until you get to a well-documented input/output module point (via comments, man pages, or otherwise).

Also, the quote (aside from it being out of context) says to not comment bad code.

> No, they are actually advocating to put more effort in thinking about stuff: how you name your functions/methods/whatever, how do you name your arguments/parameters, how do you write the code itself.

You can't define all the invariants -- or summarize for readability -- in pure code.


> No. Have you read 70s and 80s C code? Tried tracing through the original UNIX kernel sources? Tried working with them?

Yes. It's some of the easiest to understand code I've read. For example, http://unixarchive.cn-k.de/PDP-11/Trees/V6/usr/sys/ken/slp.c

They're actually quite decently commented. The functions describe what they do clearly, and the bodies show how they do it tersely, with comments around the sticky bits.

Have you read through the original Unix kernel sources? Claiming that they're uncommented and difficult to work with is surprising. (On the other hand, the directory structure could be better.)


Without tracing the backing kernel structures and the code that relies on them, please describe why sleep(chan, pri) works, and as a maintainer, what I need to watch out for when modifying that code.

What does swtch() do? What does issig() do? Does that mean it's checking for a signal during sleep? What signals could be generated? Under what circumstances do I need to check for those signals? Are there any race conditions? Does ordering matter? What happens if I move the call to issig?

Beyond the invariants, this code is NOT READABLE. I can't just glance at the comments for an atomic unit of 4-5 LoC and see what it does -- I have to examine the code in depth, running the logic in my head, and explore the workings that way.

Reading code without comments is like tracing out a circuit without a schematic or documentation. First you have to manually establish the what, and only then can you even start to spend your time determining the why.

I work on modern BSD code. It's better than this old stuff, and I still have to dig to figure out how/why things are supposed to work. It's a headache compared to properly commented and documented code, where I can just skim standalone units and know what they do without having to trace everything myself.


Of course you need context to understand code. You can't get away from that without essentially translating the rest of the code into prose and attaching it to each line. At which point there are enough comments that you need context to figure out which parts of them you care about, reading them becomes a chore, and they essentially become noise. I've seen codebases with insane levels of commenting. I found myself ignoring the comments and tracing through the code.

If the model is simple and the code is clear, learning the context becomes easy, and it fits into your head. Following code becomes easy.


> Of course you need context to understand code.

Comments decrease the amount of code you must personally read and understand, and define invariants that can't be expressed purely through the code.

> At which point there are enough comments that you need context to figure out which parts of them you care about, reading them becomes a chore, and they essentially become noise.

I've never seen this outside of contrived examples from lazy developers that think they're too smart to need to comment their code.

> If the model is simple and the code is clear, learning the context becomes easy, and it fits into your head.

In other words, you must trace the entire system to understand it and then fit it into your head. This is not advantageous to maintainers.


> you must trace the entire system

No, just the part you care about. You do need a high level mental model of the system. I've never seen a system where this is not the case, regardless of the number of comments. Even literate programming -- or at least, the examples of it that I've seen -- suffered from this. (Amusingly, I found literate programming examples were often easier to understand by mostly ignoring the prose and looking at the code.)


> You do need a high level mental model of the system.

That is extremely time-consuming to build without code comments and documentation, regardless of how "literate" the code is, because code alone can not express sufficiently detailed invariants, and simple logical/atomic operations involve a non-trivial amounts of code. (especially when writing in C).

There's almost nothing I hate more than inheriting a complex uncommented code base and spending hours or days tracing out the code to build a high-level mental model, when instead, with reasonable comments, I could have had that model nearly immediately.


You want some sort of design document. Comments are not sufficient to describe the way that the concepts interconnect. They are almost always detail oriented, scattered and do not give the big picture.

Comments embedded in source code are singularly unsuited to giving the sort of interconnection of concepts that allows you to quickly and efficiently understand build a model of the system. They are a poor substitute for real documentation.

Something like this should always be present to describe the overarching structure of the system: ftp://gcc.gnu.org/pub/gcc/summit/2003/GENERIC%20and%20GIMPLE.pdf http://gcc.gnu.org/onlinedocs/gccint/RTL.html

Incidentally, I'm not sure if you're familiar with literate programming. That's where the code is almost an afterthought to the comments. This is an example of a literate program: http://tug.org/texlive/devsrc/Build/source/texk/web2c/tex.we.... You may be familiar with it -- it's tex, the core engine used by LaTeX. Compiled to PDF, the source looks like this: http://eigenstate.org/tmp/tex.pdf.


Design documents are necessary, but are no replacement for comments. When working in GCC briefly, I found the design documents to not be nearly so valuable as the (few, poor) comments that existed in the code (objc).


The problem with comments is that they decay into irrelevance and worse, lies (that chapter of Clean Code will live with me forever). You can't write a unit test to ensure comment correctness, but you can for code correctness. Hence the code is the only reliable source of the truth.


Comments only decay into irrelevance if lazy developers don't do their job. Circularly, it's developers that don't write comments that claim comments decay into irrelevance.

Imagine that.


However, for maintenance programmers to do their job, if the comments mostly describe the code, they have to ignore the comments. Why make the maintenance programmer's job any worse?

Good comments are golden, but bad comments (those that tell you what the code is doing or duplicate coding logic in the comments) are worse than useless because they make it harder to spot and read the good comments.

I think the only thing worse than an uncommented codebase is a codebase full of comments that tell you what the code is trying to do in full detail, every few lines.....


I work at a shop where we use comments sparingly if at all. Our primary product has 14m LOC and 400k unit tests. We enjoy over 75% global market share in our extremely lucrative industry. We didn't get where we are today by being "lazy" as you put it. Comments are by very definition a redundancy when the code is perfectly descriptive and self-documenting. Thus developers can get on with their job and be more productive when they don't have to duplicate their efforts for dubious benefit.


> We didn't get where we are today by being "lazy" as you put it.

The two are hardly correlated.

Have you ever worked with some of the Mac OS X code written by poorer teams? For instance, the security framework? The internals of that code is a disaster at best, and yet, the core OS enjoys tremendous success and market share.

> Thus developers can get on with their job and be more productive when they don't have to duplicate their efforts for dubious benefit.

How do you determine the invariants of your APIs when writing code against a module? I don't trust arguments that boil down to "we're much too important to waste our time documenting, code is perfectly expressive!"

It's not. You're just wasting your time somewhere else, in little tiny increments, every time you have to trace code a few steps down just to figure out what it probably is supposed to do.

Or, sometimes in BIG increments, when somebody new has to learn the code base.


> the core OS enjoys tremendous success and market share.

How is that relevant? OSX has at best around 10% global market share? I'm talking market dominance here.

> How do you determine the invariants of your APIs when writing code against a module?

We flick through the well-documented code just as you would largely ignore the code and flick through well-documented comments. Here is a simple example for you:

    public class EntitySynchroniser : IEntitySynchroniser
    {
    	public EntitySynchroniser(BusinessObjectFactory factory, IDirectorySearcher directorySearcher)
    	{
    		Argument.NotNull(factory, "factory");
    		Argument.NotNull(directorySearcher, "directorySearcher");
    		this.factory = factory;
    		this.directorySearcher = directorySearcher;
    	}
    	...
The arguments here are invariant - they must not be null. I don't need a comment that may or may not be written in precisely the same format between 100 developers maintaining the codebase. I simply look for the one call to Argument.NotNull that all developers use in this case. The code is MUCH more readable than if the constructor had a comment explaining that each should not be null, mixed in with explaining what each should do. I can also determine by file searching or through the IDE which methods have these requirements.

If readers want to know what this API is and what it can do they need only look to the interface, or the implementation of it's methods in the class. Each method explains what it does by maintaining the same level of abstraction within the method. Like:

    public void MethodA()
    {
        DoFirstHighLevelThing();
        DoSecondHighLevelThing();
    }

    void DoFirstHighLevelThing()
    {
        // do less high-level things
    }
Each method call would maintain a constant level of abstraction so that the code is easily reused, easily tested and easily maintained.

> You're just wasting your time somewhere else, in little tiny increments, every time you have to trace code a few steps down just to figure out what it probably is supposed to do.

If I needed to figure out why code wasn't working the way it should what's to say a comment would be more forthcoming in explaining the reasons for the defect? Surely if MethodA did "thing A" but was really doing "thing B" the comment would tell me "thing A", therefore I'd be forced to examine the code further anyway, only I'd be hampered by the deceitful comment also? This is the nature of a defect - something that operates outside the documented behaviour of the system or module.

Not to mention that your stated opinion is that comments should explain the inner workings of things so that consumers can be well informed. This has the potential for exponential maintenance as really low level changes are made. Imagine that you change the conditions under which data access-level exceptions are raised. If anything that ever touched your data source explained what happened in exceptional circumstances you'd have to change hundreds or thousands of comments, or face the sort of comment rot I mentioned earlier. This is the real time waster!

> ...when somebody new has to learn the code base.

This is always going to be the case. Comments don't make this task any easier than a well structured codebase. A well structured codebase comes from developers making the conscious decision that any reliance on the crutch of a comment is a failure to write proper self-documenting code. A well-structured self-documenting codebase by definition requires no comments (except for the "why" not the "how", which I fully support doing by the way).


> How is that relevant? OSX has at best around 10% global market share? I'm talking market dominance here.

Fine, I'm familiar with OS X, but I'm sure there's equivalent stupidity in Windows.

> The arguments here are invariant - they must not be null. I don't need a comment that may or may not be written in precisely the same format between 100 developers maintaining the codebase. I simply look for the one call to Argument.NotNull that all developers use in this case. The code is MUCH more readable than if the constructor had a comment explaining that each should not be null, mixed in with explaining what each should do.

No, it's not much more readable, because if properly commented, I WOULDN'T HAVE TO READ THIS CODE AT ALL. Instead, my IDE or documentation browser would tell me, inline, exactly what I needed to know.

> If readers want to know what this API is and what it can do they need only look to the interface, or the implementation of it's methods in the class.

If you have to look at code's implementation, you've failed. Why isn't that code a black box to me? Why do I care at all how it's implemented?

Why on earth would I want to waste time doing that instead of instant access to high-level API documentation?

Moreover, it's a contrived example, because nullable/not-nullable is the least of an API.

> Not to mention that your stated opinion is that comments should explain the inner workings of things so that consumers can be well informed. This has the potential for exponential maintenance as really low level changes are made.

No, my stated opinion is that comments that are externally visible should document externally relevant invariants.

Comments that are internally visible should document internally relevant invariants (if the code does not adequately express those, as it often does not).

> A well structured codebase comes from developers making the conscious decision that any reliance on the crutch of a comment is a failure to write proper self-documenting code.

A well-structured code base comes from writing good code. Comments are part of writing good code. Self-documenting code isn't fully documented code, unless it's literally a literate programming language. Claiming otherwise is just an excuse for you to be lazy and not write comments under the misguided auspices of being much too smart to need them.


Sure, if I were publishing a public API I'd want to document the functions available, but the fact is, the vast majority of the code we write at my shop is not consumed outside our own codebase. Why duplicate the effort of writing documentation when everyone has access to the code? There is no benefit for us so we don't do it. We made that decision and it's the right one for us. Sure, you have a different situation and I'm sure using comments has helped and empowered your developers, but for us it makes no sense and is a waste of time.

I'd suggest you stop trying to tell the world that senior developers must conform to your narrow views (narrow, by the sheer size of the response against your point of view here). Calling people things like "lazy" and insinuating they inflate their own abilities simply because they don't do what you think they should do is a pretty trollish thing to do. You obviously missed the first point in the original link.


The beauty of literate programming, quite honestly, is that because of the way that the documentation and code are interwoven, it requires fewer code comments, and encourages both clear code and clear documentation.


That code you linked has lots of comments containing lots of information. How is this an example of how Senior Programmers are against comments?


Maybe I haven't read K&R carefully enough but how can you have a function declaration like

    sleep(chan, pri)
without any data types?


Because the default datatype is int:-

  $ cat z.c
  foo( a, b )
  {
          return( a+b );
  }
  
  main( void )
  {
          return( foo( 3, 4 ) );
  }
  $ gcc z.c
  $ ./a.out
  $ echo $?
  7


Since you have already dismissed a well thought response, let's try irony instead:

"When you have spoiled ingredients, dispose 'em. Do not try to cover the bad flavor with condiments." - Famous Master Chef.

"You see? Master Chef does not like condiments. They take away the natural flavor of the food and anyone who uses them is an idiot who never will be a true cook". - Zealot Wannabe.


Actually the people I have met who tend to be most against documenting what code does with comments tend to have the best commented codebases I have ever seen.


You never specified that your backslash referred exclusively to comments that document what the code does. This kind of comments are in most cases the result of bad habits taught by introductory programming books and instructors alike, with possible one exception [1].

But comments are incredibly useful to document why code exists in the first place, what are the assumptions that must hold for it to behave as expected (including but not limited to preconditions, invariants and post-conditions), and possibly how to use it (if you are using some utility like javadoc to generate other types of documentation from source code).

[1] The exception I am thinking about is that in real life you cannot always deliver the best quality possible in your projects. You have to interact with horrible systems, make ugly tradeoffs and meet deadlines with limited resources. Things get convoluted from times to times, so the best you can hope for is to leave thoughtful comments explaining how some specially hairy component works. The maintainers of that software (including a potential future version of yourself) will be very grateful for this.


Agreed on this point. The idea is that the comments should have something to say apart from the code. You don't put a footnote in a book to repeat what you just said. You put one in to add a reference to something else, explain a caveat, or otherwise say something useful out-of-band.

In general, in my experience, the people who are most hostile to willy-nilly comments have some of the best commented code. They see the code as written both for the computer and the programmer, and the comments are thus either interface promises, or are footnotes. Most of the people like this I have worked with tend to produce extraordinarily readable code which contains a good number of comments which should be there. But the worst codebases I have worked with hands-down are full of comments.

As for your exception, I agree. I think it's worth flagging such comments however so that the reader immediately knows that this is a special clarification.

The last time I described what my code did, I was using Perl 5.6 or something and was trying to do a method call to a fixed name in a variable package and was having a horrible time. I ended up, I think, using the symbol table directly and the syntax was worse than hairy. It was downright misleading. So I added a comment something like:

# HELP! I can't find a better way to write this. The syntax is .... Anyone have any suggestions?

If you understand you are writing for a human audience and that your comments will be read only if generally useful, then the this leads to both code clarity and comment clarity. It may not always be possible to maintain and hence one would add comments explaining tradeoffs or flagging a section as unclear (and possibly explaining it). But these are avoided as best one can.


> “Don’t comment bad code—rewrite it.”

That's advocating against bad code, and specifically the fairly widespread practice of commenting what it does rather than fixing it.

It's not a blanket statement against comments in general.


Kernigan is absolutely right here btw.

There are so many problems with trying to make up for unclear code in comments, that's a real losing battle. I recognize that it may be worth breaking that rule sometimes, but then it is worth noting that, and flagging it so that other programmers can see and fix it. A comment like "#FIXME: This code is unclear: What it does is...." is perfectly acceptable.

Comments are for collaboration. You do NOT want to make them even appear useful for debugging.


> that would otherwise require each reader of the code to understand the code itself in depth.

Is that a problem? Even in code that has good comments, I always skip the comments and go straight for the code. Comments are okay if the code needed to employ hacks for some good reason, but otherwise I've never met a function that I wish had them.

I often wonder if people come from different backgrounds, which leads to completely different points of view on the matter. Personally, I find code easier to read than natural languages, but that doesn't mean everyone is the same and I respect that you might find comments useful. But why then assume that everyone needs comments?


Wait until you start working on multi-million line systems in companies where nobody - and I mean nobody - understands everything, and the original authors of pretty much every subsystem has since left the company; and you need to fix 20 critical bugs in the last week before the thing ships. Clues that are more high-level than the code can ever be start being really helpful.


> I've never met a function that I wish had [comments]

Come on, this is stretching credulity. Either that or you don't value your own time.


First, I think that requiring the reader to know the code in depth is a good thing. Comments should not be used to avoid this. Comments can decay in relevancy and, aside from function API documentation, should not be used in debugging. The way comments should be used is:

1) API documentation says this: does the code conform? If not, either the specification is bad or the code is bad.

2) Comments inform collaboration, but do not inform debugging other than as API documentation.


I do agree that there is merit to documenting public interfaces, but there are tools designed specifically for that job so that you do not have to go slogging through the source code at all when you want to look up a definition.

As a result, I feel that is a different matter to commenting for the purposes of code maintainability, which is what the parent poster is speaking to.


We are probably on the same page. I wrote this:

http://ledgersmbdev.blogspot.com/2012/08/patterns-and-anti-p...

Comments are not for maintainability.


> Is that a problem?

Yes, because it means I might need to read 6 layers of code and wind through multiple modules, instead of just reading the top layer that defines the invariants of input/output for a module.


I don't think people here are against commenting APIs... That's more of a documentation thing.


It's not just a documentation thing.

When you document an API you make a promise to the programmer. If you use the API according to the documentation, the API will behave according to the documentation. Documentation of API's establishes interfaces. If the code doesn't conform to the comments describing the API, it is the code's fault not the comments' fault.

I don't think people here are even against commenting code. I think people here are against (and for good reason!) duplicating coding logic in comments designed to describe in line-by-line detail the code that should have been readable in the first place.

Comments like that are FAR worse than no comments at all. If there are no comments at all, a new comment that is clear and relevant will be read. If you have a codebase full of bad comments you cannot start adding good comments until you clean that up.


> If they express those views, I wouldn't call them senior.

I wouldn't be so hasty as to assume that anyone making the above claim should be taken literally. Indeed, frowning on detailed commenting (or commenting at all) seems more like hyperbole then anything. After all, what is "detailed commenting"? It's not indication of quality.

    // Increments x by 1
    x++;
That is a detailed comment, but hardly worth while.

And the commenting at all remark does not indicate that all commenting is to be avoided. Rather that comments should be scrutinized. After all, comments are indicative of a confusion. If your code requires a comment to explain itself, maybe it's best to review what you are doing, and work to avoid confusion.

> it's rarely possible to express -- purely in code -- what the code is supposed to do, what the input is supposed to be, and what the output is supposed to be.

It's actually fairly easy to do that in all languages I'm aware of. It's part of the reason you have Unit Tests. To document what the code can do, but also the expected input and output. More often than not, we forget that.

I dislike the idea of promoting comments for the sake of comments. I much prefer the push for clarity in code. Limiting clarity to comments is bad form, and generally those pushing for lots of comments excuse confusing code because they use comments freely. They also believe that these comments will remain relevant, and make the call that should they not, it's not their problem, but the programmer that fails to update the comment.

This is akin to blocking user out of an account after the first wrong password entered. It's their mistake, after all. And our jobs as programmers are not write robust code. Comments cannot (and should not) affect that code, and relying on comments to provide the quality missing from the code is lazy.


Unit tests validate invariants, but they don't express them in a concise form, and they're not a suitable form of documentation.


> Unit tests validate invariants, but they don't express them in a concise form

I'd be more in line to say that if your Unit Tests aren't concise, then it's a problem with your Unit Tests, or at least, your implementation.

> and they're not a suitable form of documentation

Well, the output that you can generate form unit tests can easily be documentation, explaining in great detail exactly what can be done with what is being tested, without any hand waving either.

Still, that doesn't take away from everything else I said. In the end, if you rely on comments to explain your code, your code is probably lacking.


> Anyone who advocates against comments is justifying laziness

That is a gross generalization. I do not, in general, comment my code (and I know and work with many other programmers who do not) but I go to great lengths to ensure that my code is easily understandable. Commenting is not the only way to communicate intent.

I suspect we work in different sections of the industry, but in my world, comments are often a red flag rather than a welcoming sight!


> That is a gross generalization. I do not, in general, comment my code (and I know and work with many other programmers who do not) but I go to great lengths to ensure that my code is easily understandable.

You're almost certainly not succeeding, because unless you work with a language far more expressive than one I've seen previously, then your code can not express all the information I need to work on your code.

A complete lack of comments is on my top three list of "bad times ahead" warning signs when I inherit a codebase.

The other "bad times" warning flags are:

* A lack of documentation

* A lack of automated tests (integration, unit, or otherwise).

These three things can make or break maintainability on their own, and they also often serve as a proxy indicator for just how much thought an engineer put into fully understanding the invariants and edge-cases of the code they've written.

The hard part of writing comments, documentation, and tests is in understanding invariants and edge-cases. The easy part is writing down what you've understood.

> I suspect we work in different sections of the industry, but in my world, comments are often a red flag rather than a welcoming sight!

Unless your section of the industry has no interest whatsoever in maintainability, I'm not sure our respective sections are very different.


>You're almost certainly not succeeding

You seem pretty convinced, so I don't have high hopes of changing your mind with a post on an internet forum, but in my experience most comments can be replaced by clearer names, better abstractions and better tests. The ones that can't tend to be about the "why" rather than the "what".

>Unless your section of the industry has no interest whatsoever in maintainability[...]

My primary motivation is maintainability, and your claims to the contrary come across as pretty condescending.


> My primary motivation is maintainability, and your claims to the contrary come across as pretty condescending.

It's simple frustration with ego-based arguments from programmers that ultimately results in poor code bases.

Ego-based programming arguments are predicated on the idea that those that fail to deliver clarity must simply not be smart, wise enough, or skilled enough -- whereas with just a sufficient level of intelligence and skill and wisdom, one can produce lofty, comprehensible, elegant code.

If there's one constant I've found in my career, it's that everyone is dumber than they think, and everyone screws up. The ONLY thing that produces high quality code is careful attention to detail and slavish devotion to documenting and testing.

It's no different than any other pursuit; even a master carpenter will draw up plans, follow them, and measure twice (or three times). To think that one is smart enough to write perfectly literate code is foolish, and to force your future maintainers to deal with your uncommented code is to foist the costs of your short-term decisions onto them.


Comments in the body of a function should never be necessary for maintenance. The most unmaintainable code I have ever had the displeasure of working with was code which either had no comments or documentation or code with sparse documentation and LOTS of code comments.

If comments are necessary for maintainability, a simple solution is to flag the comment with a FIXME tag so that the next guy reads the comment and realizes that a section of code is unclear and should be looked at with extra care.

That isn't to say I am against code commenting. I find that when I follow my own code commenting practices and try hard to avoid using comments to explain code, I still use them frequently, probably more frequently than average. I am just saying the purpose needs to be clearly thought out.

In my view, the most important thing is interface documentation. This is a promise to the programmer, and it forms the basis of what you might think of as a development contract. You write your code this way, call the function this way, and you will get a certain return result. To a maintenance programmer, then, the question is whether the code works and by "works" I mean whether it fulfils its part of the contract by implementing what the comments promise. If a caller is requiring a corner case, then that can either be added to the documenting comments (i.e. adding to the promise) or the caller can be changed. So these comments are of vital importance and I see nobody arguing against them.

But within a function body things are different. Comments can be helpful here for collaboration and future development (and a subset of this is maintenance, but if you mind the rest this will take care of itself). A good maintenance programmer knows when to read the comments. if the comments describe the code, a good maintenance programmer will ignore them all in order to focus on what the code is actually doing and whether it fits the API docs. Bad comments then hurt more than they help and this includes comments which needlessly describe what the code is doing.

On the other hand good comments are golden and these either flag potential issues for the programmer (# BE CAREFUL OF SQL INJECTION HERE BECAUSE WE CAN'T USE PARAMETERIZED QUERIES!) organize code (# variable declarations) or add footnotes so that it is clear why a given choice was made (# RFC XYZ specifies a max timeout of 120 seconds).

The hostility is not to comments in code. The hostility is to a certain common practice, whereby comments duplicate code. There is no case where this makes sense without flagging the issue to a future programmer and noting that a rewrite is in order.


That's why you "Inherit a codebase", as opposed to "Build a codebase". People who maintain and people who build are... well... they're just different people. We do need them both, but, they are different. Which is why we need them both.


I also build code rather large new products, too.

People that build with no regard for future maintainers are building code incorrectly.

It makes me happy when I hand off a code base and the receiving maintainer actually tells me that they appreciate how clear and understandable it is. That's a level of care I wish I always inherited.

Maintainers versus builders aren't different people -- that's just what intellectually lazy programmers tell themselves when they're making another mess for someone else to clean up.


I don't think that is necessarily the case outside a corporate environment. I inherited the SQL-Ledger codebase when we forked to LedgerSMB. Now I am using it as scaffolding to build a very nice, clean, powerful codebase in its place.


Well, I inherited a codebase where all comments fell into two groups:

1) Copyright notices and brief (1-2 line!) file-level descriptions at the top of each file and

2) Comments that the code needed to have in place in order to run properly... Delete the comments and things break. I am not kidding.

Oh, no documentation and no unit tests either. We started adding unit tests and found that things like number rounding failed.....

Years later we are still replacing the old code as fast as we can. The obvious things including braindead security issues, were just the absolute tip of the iceberg.

Nowadays I write my documentation first, then code, then at least some tests.


I do not, in general, comment my code (and I know and work with many other programmers who do not) but I go to great lengths to ensure that my code is easily understandable. Commenting is not the only way to communicate intent.

I agree that commenting is not the only way to communicate intent.

I don't know what you mean by commenting code though. I find in general that the people who treat commenting as a last resort, and look for every other method to clarify code first, tend to also have some of the highest comment to code ratios, as well as the best comments.

This was driven home to me recently when I wrote some PHP classes for interfacing with LedgerSMB. I checked them into github and added the project to Ohloh, and was stunned when it said I had as many comments as code. But virtually all of these were interface documentation.


The problem with commenting code is that code is constantly refactored to deal with new invariants and edge-cases. What starts out as a great way to summarize the purpose and mechanics of a given function or statement becomes immediately stale once the function or statement is changed. In the best case, the comments are revised along with the code they describe.

However, everyone makes mistakes, as you have pointed out, and once a comment is forgotten during refactoring, that comment has become a liability to the future maintenance or use of the code it describes. Given that comments are, by definition, not executable lines of code, commenting errors do not show up in code execution. Since most bugs only become apparent because of incorrect execution, commenting bugs are difficult to spot. This is a problem when developers read the comment instead of the code to discover the purpose and mechanics of the commented function or statement, and can lead to further errors in client code of the function or statement when the called code doesn't conform to the specifications expressed in the comment.

Now the developer who has to fix the code has two things to debug; the code as it is written and the code as it is described in the comment. Which has authority? How do you prove the correctness of a comment?

You can prove the correctness of code, because it can be executed. You can test it using the scientific method, trace its execution paths at runtime and by reading the calling code. You cannot do this with comments.

Additionally, every line of source code is a liability to the maintenance of the code. Each line out source adds computational and mental complexity to the program they describe.

For these reasons, good, verbose variable and function names to describe the what, and corresponding tests to describe the how and why are superior ways to describe code over verbose comments.

However


The point of a summary though is to offer the promise of an interface. The code should implement the summary, not the other way around.

Code comments though are different. They are there to annotate code. They are incredibly useful in collaborative environments but only if they are used to organize, discuss, and debate the code, not describe it.


I've just read this whole thread.

flatline3, I can tell you flat out that you are wrong. There are plenty of senior level programmers that are quite deserving of the name who deliberately comment very lightly if at all. There are also plenty of senior level programmers who think that verbose commenting should be required of everyone.

I have experienced both styles, both in forms that are implemented well and implemented poorly. I have read arguments for both sides. I have found that either can work well, and either can work out horribly. (Though attempting both at once is very much not recommended.)

Personally I prefer to work with (and write) code that avoids comments wherever I have any reasonable alternative (clear variable names, calls to descriptively named functions, error checks with error messages that make it clear what I was trying to do, etc). However when all other alternatives fail, I do not hesitate to comment.

The most important case where there is no reasonable alternative is in descriptions of an API. The code that is there is how it happens to work right now. If you want to know what you can rely on to remain true in the future, read the documentation. Anything not documented is not part of the API, and you should be prepared to find it changed in the next release.


> There are plenty of senior level programmers that are quite deserving of the name who deliberately comment very lightly if at all.

Senior in name (and possibly years) only. I've spent enough years cleaning up messes to know that master programmers:

- Design carefully - Comment liberally - Test thoroughly

Thus they produce clean, well documented, understandable code. Skipping any part of that list is foisting delaying the cost for a much larger later reckoning of some poor future persons.

You might get away without commenting, but you're not doing anyone any favors. Skip all three and you're incurring significant technical debt.

I have no respect for programmers that think their sole job is to write code (no matter how "descriptive" it is).

> The most important case where there is no reasonable alternative is in descriptions of an API. The code that is there is how it happens to work right now. If you want to know what you can rely on to remain true in the future, read the documentation. Anything not documented is not part of the API, and you should be prepared to find it changed in the next release.

All functions are API. Some is mutable, because you can check and modify all callers. Some is immutable, because you can't.

It all needs to be documented, and the cost for not doing so can scale exponentially as a code base grows.


Ah, the "no true Scotsman" fallacy. No matter what someone has accomplished, no matter how much experience they have, you're the judge of whether they are really a senior programmer. And all who do not meet your standards are not senior programmers and are therefore not data points counter to your position.

Read the source code for Arc. You'll find that Paul Graham is not a senior programmer by your definition. Read the source code to some of Damian Conway's modules. You'll find that Damian Conway is not a senior programmer by your definition (though his stuff does usually come with wonderful documentation). There are plenty of other examples of talented programmers in your books are not senior.

From where I sit, I know nothing about you other than your account is about 2 months old and this discussion. In particular I know nothing of what you've done. However people that I respect a heck of a lot more than you have defended very light commenting styles. I've seen it work. I've also seen it fail. Ditto for heavy commenting styles.

Therefore, based on my own experience, I'm going to say that it is complex, with valid arguments on both sides. Which puts me on about the same page as Steve McConnell's book Code Complete.

But I'm going to go further. The downsides of a comment heavy style have to do with the possibilities of the comments being misleading. People have to be very, very careful to maintain comments along with the code. Based on what I've seen, I would personally not trust any team of programmers to do this reliably without having careful code review processes. If you have this careful code review process to alleviate the potential issues with commenting, I would advocate a much heavier commenting style.

But there is one line that is very important that explains a lot of the difference:

It all needs to be documented, and the cost for not doing so can scale exponentially as a code base grows.

There are a lot of problems that scale non-linearly as a code base grows. There are two possible responses to this. The first is to try to create procedures to alleviate the problems that are intrinsic to growing code bases. The other is to maximize what can be done without growing your code base.

There is a fascinating data point on this that is cited in Software Estimation: Demystifying The Black Art. For projects of a fixed size (about 50k lines of code) there is a graph based on real world estimates of months to completion versus team size. Initially as teams grow, calendar months fall. Then the graph bottoms out with teams of 6-8 people. Then it starts to rise. And then falls again. It isn't until you get to teams of about 20 people that calendar months fall to the same level. (Given that lines of code was the measurement, it is likely that the productivity of a 20 person team was overstated.) And then they start to fall further.

If your experience is mostly on teams of 12+ people, your observations about software development will be very, very different than if your experience is mostly on teams of less than 8 people. What works for those types of teams teams is very, very different. And given the huge productivity valley between small teams and large teams, there are a lot of problem areas where the right approach is to maximize what can be done by small teams, rather than to figure out how to build procedures to scale to (the now inevitably necessary) larger teams and code bases.

(If your experience is with larger teams, your first encounter with the potential productivity on small teams can come as a shock.)


Dependently typed programming languages can do the "express all the invariants" bit. Readability is an open question, though.


I tend to get a bit upset if code has comments that basically just describe what code is doing rather than why. Stuff along the lines of:

   // Increment the total
   total++;
   // Execute our SQL query 
   var result = query.execute();
Seems to happen a lot with developers who use comments to "sketch out" code (not a bad thing) and then leave the comments in place when the actual code is written.


That's a technique Steve McConnell calls "The Pseudocode Programming Process," and while it's verbose, it's not a Bad Thing. I don't do it, but I'd rather have comments like you posted than none at all.


That is legit. I have done it on occasion. It is like a relaxed form of literate programming.

I don't understand this vitriol against all forms of code commenting. (I personally hate the useless, mostly empty function headers forced by some coding standard)


The problem has to do with maintaining large, complex, and frequently changing projects. If your code tells me what the program is doing the first thing I have to do when debugging is ignore the comments.

If the comments describe the code this means I have to ignore all comments including those which may be relevant to my debugging. This causes a few specific problems in a collaborative environment.

The first is that the comments get stale/out-of-date/etc, more quickly and are therefore consigned to the archaeology of the program rather than of current relevance. At least with spurious logging, I can take it as a sign that someone had trouble with the code here. With comments I cant even tell if it was done in pseudocode and then translated below. It is useless.

The second is that you can't just add relevant comments into the mess without deleting all the other comments first. Otherwise they can't be sorted out easily or efficiently. In other words, it is worse than useless because it keeps proper, useful comments from being seen or read.

Third, if there are relevant comments there, such as

# This is the maximum value the standard allows for.

Then I won't see these and I am more likely to miss them and hence screw something up by accident.

A better approach is to recognize two things:

1) The code itself needs to be so clear, that you never need any comments for debugging (interface documentation is something very different), and

2) The code plus the documentation together has to be easily readable to the programmer. It also needs to be clear, concise, and avoid duplicating messages any more than needed. Duplication with the documentation of course is required by definition.

I hear a lot of people say they have code they would like to release open source but don't want anyone to see how horrible the code is. The answer is to learn to write code with a dual audience --- human and computer --- in mind. The code comments then function like footnotes would in a text, or as a way for two or three programmers to discuss/debate differences in approach. However, they are not debugging aids.


Actually many of us do find it a bad thing. Useless comments are worse than no comments.


sed 's/\/\/.*//g' shittyComments.c


you can get even crazier if you add in plenty of spurious logging

# print out the value of x prior to increment print("x value prior to increment: %d" % x)

# increment the value of x x += 1

# print out the value of x after increment by one print("x value after increment by one: %d" % x)


I've seen quite a lot of code that kind of looks like this:

   // Increment the total
   log.Debug("total before increment=" + total);
   total++;
   log.Debug("total after increment=" + total);
   
I find myself looking at it and going where is stuff actually happening!

I sort of wish someone would allow comments and logging to be combined as language features.


Check out Smart::Comments module in Perl [1].

It allows the specially-formatted comments to produce debugging output.

From the synopsis:

    use Smart::Comments;
     
    my $var = suspect_value();
     
    ### $var
     
    ### got: $var
     
    ### Now computing value...
     
    # and when looping:
     
    for my $big_num (@big_nums) {  ### Factoring...      done
        factor($big_num);
    }
     
    while ($error > $tolerance) {  ### Refining--->      done
        refine_approximation()
    }
     
    for (my $i=0; $i<$MAX_INT; $i++) {   ### Working===[%]     done
        do_something_expensive_with($i);
    }

[1] https://metacpan.org/module/Smart::Comments


Noooooo..... Not magic comments.............

Magic comments are evil, the pox of the earth, etc. I have nothing good to say about comments as code. This totally messes up the separation between code and comment.


The typical case where this happens is that the logging was added because of some bug somewhere and this was put in place to figure out what was going on with total. See it as an archaeological record more than anything else ;-)


Hm, my code didn't format as intended. What you wrote is what I meant.


I prefer code where I can skim the comments and see the major plot points, at a glance.


If you need to skim the comments to see how a function is doing what it's doing, the function is too long.


Maybe the compiler needs to see the whole function in order to properly optimize register usage, because the function is on the critical path.

There is sometimes more to code than readability, unfortunately. I have worked with functions thousands of lines long that can't be broken up without losing a few percentage points of speed - but these functions are called millions of times.


It's always a matter of heuristics, for sure. When you need to modify code in a way that's less than readable/obvious, then you start dropping in comments to compensate. Your first pass should be understandable and obvious and readable, with comments typically restricted to documenting functions and interfaces.


Effective use of macros or inlining could solve that problem.


Over 2,000 lines with macros. Inlining didn't give good enough results (at the time).


When it can take 3-4 statements to perform a single logical operation, there is still value in summarizing each block with a comment, even if the function isn't "too long".


That's what function names are for. Comments don't need to summarize. A useful comments says why code is this way, it doesn't summarize or repeat code.


> That's what function names are for.

A single function for every 3-4 line operation would result in incredibly disjointed code, and would require more explicit documentation of invariants because that function can now be called elsewhere (at least inside of the given translation unit).

> A useful comments says why code is this way, it doesn't summarize or repeat code.

That's nonsensical. Why wouldn't you want to abstract the complex?


I abstract code with code, not with comments. Comments in general stink, and are used to express what code can't. If I can express it in code, it doesn't need a comment. Every comment is a sign that you failed to write expressive code.

If you need a comment to say what the next four lines do, you need a function for that, not a comment.


Functions have maintenance and implementation overhead. They define an API that is accessible from the translation unit, and they thus require defining some amount of invariants. They also require breaking flow from the current function being implemented to hoist the code upwards.

A short, atomic unit of 4-6 lines of code does not deserve to be a function simply because it's an atomic unit, but it does warrant a simple comment that someone skimming the code can use as an index to determine where they want to look.

It's all about making the code approachable in bite size pieces for future maintainers, your collaborators, and your future self. Breaking it into pieces and describing the code means that maintainers are not required to trace out all the code and swap in a huge amount of knowledge just to determine what a given function does, and why, and what is safe to change within it.


> A short, atomic unit of 4-6 lines of code does not deserve to be a function simply because it's an atomic unit

And I couldn't disagree more with that statement, and virtually everything you've said. Maintainers don't need to look at a function to see what it does, that's what its name tells you and keeping functions focused on doing one atomic thing is what allows the name to replace the implementation and makes for well written programs. I despise programs written in the style you suggest.

A well written program is a thousand small functions/methods unburdened by long methods full of comments. Good code requires few comments other than those that explain implementation choices or class responsibilities. Comments are a code smell most of the time, they exist to make up for poorly written code.


I mostly agree, but "they exist to make up for poorly written code" should be "they exist to make up for less maintainable code." Less maintainable code may not be poorly written if other constraints (intense optimization in a critical path, for instance) force it on you.


Well, I did say to explain implementation choices which I think covers your point, as I do agree with you.


Yeah, I was just objecting to the implicit (and quite possibly unintended) value judgment.


Sure, I do like your phrasing better, less maintainable code.


You would actually write an "Increment the total" comment?


Some people certainly do! My favorite examples of how not to write comments are these code snippets from the API guide I was given at a previous job. The other 60 pages of API documentation are just like this- all what and no why.

The problem isn't that these comments are harmful (they're not), but that inserting these comments made the coder feel like they'd done their job of commenting their code well, when in actuality the comments provide no insight to why certain things are called or instantiated, or what certain values represent; critical knowledge one needs to extend the code beyond the specific example cases the API guide presented.

----

  ‘ A for loop iterates through each row of DataGridView
  For Each row In DirectCast(Me.DataGridView1.Rows, IEnumerable)
----

  Dim frmTakeBackTask As New TakeBackTask
  ‘ Public oTaskData of TaskBackTask gets populated from the local object oTaskData
  frmTakeBackTask.oTaskData = oTaskData
----

  ‘ A For loop is initiated to iterate through each child node contained 
  ‘ in the XML document
  For Each record In xmlDoc.ChildNodes.ItemOf(0).ChildNodes
      ‘ A nested For loop is initiated to iterate through each column
      For Each column In record.ChildNodes


I probably wouldn't write "increment the total", but I think it makes sense to comment on what the total is/represents, or why the total is incremented in some particular way (if it's non-obvious).

My beef with "increment the total" comments is not that they are there, but rather that they don't help me get the big picture.


That example is rather hyperbolic and not particularly useful. I can't recall the last time in 15 years that I thought "this code has too many comments!"


Back in college I was a teaching assistant for CS classes and graded a lot of what was very often very poorly written and majorly undercommented code. But I do remember once getting an incredibly unnecessary 2 page long comment for a 10 line function.

That may be the only time that thought has gone through my head.

At my first internship, the code base had basically no comments in it, but was in general very clean, very organized, and there was a ton of thought put into naming and organization for readability. It was a good exercise for me working like that because it forced me to not rely on comments to explain messy code. But I also remember having long debates about what to name a variable to make it perfectly clear to the next person reading this code what it does (and often times ending up with excessively long variable names) and thinking "wow...this is a waste of time. You could just add a 1 line comment"


Consider the standard Java cough paradigm used by multitudes of developers, and on by default in many Java IDEs:

    /* Gets the person's name
       @returns the person's name */
    public String getName() {
       return name;
    }
That is insane. The comment adds nothing to anyone's day and helps no one better understand the method than after simply reading the method signature.


It generates auto-docs, which are useful. It's just a ridiculously verbose way to do it, and it would be preferable if the documentation could be generated without the repetitive comment.


"I can't recall the last time in 15 years that I thought "this code has too many comments!""

I've thought that every time I see a source file that contains an automatically generated header built from the revision history.


I feel like there are some people who go overboard on the formalities of commenting (specific format, etc.), but in general I can't think of one instance where I've thought "man, I wish I (or someone else) hadn't spent time explaining what this does".

I even find that when I write comments to explain what a specific method is intended for, it helps me avoid violating the single-responsibility principle. If I clearly spell out what I'm trying to accomplish, it helps keep me focused.

To those who say that the code should be elegant enough to be read on its own, there are some cases where the business logic involved is really what needs to be explained. At the same time, what is elegant and concise for you may appear obfuscated and confusing for someone else. You may argue that they should know all the techniques that you know, but that's just the reality of working with others sometimes.


> I can't think of one instance where I've thought "man, I wish I (or someone else) hadn't spent time explaining what this does".

There are good uses of comments, but there are also bad ones. From Coding Horror [1] an example:

    '*************************************************
    ' Name: CopyString
    '
    ' Purpose: This routine copies a string from the source
    ' string (source) to the target string (target).
    '
    ' Algorithm: It gets the length of "source" and then copies each
    ' character, one at a time, into "target". It uses
    ' the loop index as an array index into both "source"
    ' and "target" and increments the loop/array index
    ' after each character is copied.
    '
    ' Inputs: input The string to be copied
    '
    ' Outputs: output The string to receive the copy of "input"
    '
    ' Interface Assumptions: None
    '
    ' Modification History: None
    '
    ' Author: Dwight K. Coder
    ' Date Created: 10/1/04
    ' Phone: (555) 222-2255
    ' SSN: 111-22-3333
    ' Eye Color: Green
    ' Maiden Name: None
    ' Blood Type: AB-
    ' Mother's Maiden Name: None
    ' Favorite Car: Pontiac Aztek
    ' Personalized License Plate: "Tek-ie"
    '*************************************************
Now imagine something like this exists for every function and you're reading the source code... Annoying.

Others are less extreme of course, but repeating the code in comments is bad and even harmful if you forget to update the comment as well as the code. DRY is a good principle to have.

Of course "all comments are bad" is simply wrong, comments are essential to explain decisions or non-obvious snippets or gotchas.


Reading this discussion (and posting a comment about s-expressions) got me reading about Lisp[1], and then wondering about contemporary Lisp implementations, and then to Arc where I found this amusing comment by our host:

"Object-oriented programming generates a lot of what looks like work. Back in the days of fanfold, there was a type of programmer who would only put five or ten lines of code on a page, preceded by twenty lines of elaborately formatted comments. Object-oriented programming is like crack for these people: it lets you incorporate all this scaffolding right into your source code."

http://www.paulgraham.com/noop.html

[1] I was paid to program in Common Lisp for about 6 years. However, this was a while ago so I was attempting to refresh my memory.


What is interesting about reading this discussion is that all of the 'examples' used in order to show that comments are bad are totally implausible. On the other side, the situation of 'no comments at all' is actually ubiquitous, in reality.

Writing out what you are doing takes a little work, and requires at least briefly thinking about it. It also means you can be embarrassed if your code is doing something irrational or unintended, and looking at everything again when you make major breaking changes.

By Occam's Razor, it seems more likely that complaining about comments is driven by an unwillingness to produce them more than actual practical problems created for others by their presence.


Yeah, that's exactly the kind of formality and over-commenting that I meant by "I feel like there are some people who go overboard on the formalities of commenting (specific format, etc.)". I saw a lot of examples of that at my old employer where they had tried (and failed) to automate some of their documentation years and years ago.

It's nice to have a brief description of what a class (or in many cases, a method) is intended for, etc. As others have said, it saves time each successive programmer from having to fully understand all of the source code.


Ah I see, misunderstood a bit.


The issue I have with commenting is some people enforce it for the sake of having comments in place, which would most of the time describe the "what" and the "how" of the code, rather than the "why", which in my opinion, where most of the value lies. In Java, the usual offenders would be the getter and setters in POJOs, like:

  * Returns the name
  * @return the name
  */
 public String getName();


Comments like that exist simply to appease documentation tools that can't derive those comments automatically.

The net gain is that you get nice API documentation. The downside is that you have a verbose and obvious comment in the source.


Aren't such comments usually autogenerated by the IDE or such tools?


There's some debate on this: http://queue.acm.org/detail.cfm?id=1053354


The only thing worse than uncommented code, is wrongly-commented code. In my experience, code is almost always wrongly-commented, either because the programmer wrote the comment wrong in the first place, or because they wrote the code wrong, or because the code was later updated to do something different, and the comment was not updated to reflect the changes. In my experience, especially in an old codebase, it's extremely rare to find a piece of code that is both thoroughly and accurately commented.

Given that reality, I would rather forego the comments for readable code. Readable code tells me what is going on, and doesn't lie!


In my considered experience, those who are most hostile to unnecessary comments tend to put the most comments in their code. It isn't an argument against code comments, just being very picky about what is a useful comment collaboration-wise.


The problem is not when programmer (A) writes the code and the comments correctly.

Nor when jackass(B) updates the code and not the comments, making them misleadingly worse than no comments at all.

But when the code now has to be maintained by programmer (C). This means you.


There's a lot of back-and-forth in this discussion already and I feel like some people aren't understanding that it's not about _never_ commenting the code; it's about only commenting when it is absolutely necessary (which is actually quite rare if you're writing clean, simple code (which is, itself, quite rare!)).

I think that everybody should be required to read the chapter about commenting in "Clean Code" before contributing to this discussion. It's very java-centric and not perfect, but there is some really good insight. There is a pdf available here: http://www.tud.ttu.ee/material/kallik/JOOP/Clean_Code_-_A_Ha... (if it really helps you, consider buying a copy and supporting the authors).


The key things are:

1) The code should speak for itself, and

2) You comment when you have something to say outside of what the code says.

Chances are, ironically, if you stop using comments as a crutch, you will use them more often because they will start to be a useful tool.


Maybe he's saying, if your code is simple and elegant enough you won't need to comment.


This is a fable bad programmers tell to themselves to justify their intellectual laziness.

No real world code is simple and elegant enough that you don't need to think through the complex invariants of the code, consider would be relevant to future maintainers, and then write it down.


  > This is a fable bad programmers tell to themselves to
  > justify their intellectual laziness.
No, actually commenting is easier solution for the lazy ones. Too bad they are to lazy to update the comments when something changes.

  > No real world code is simple and elegant enough that you don't
  > need to think through the complex invariants of the code
Oh, please…


>> No real world code is simple and elegant enough that you don't >> need to think through the complex invariants of the code

> Oh, please...

  sendDataWithTimeout(user_t *user, data_t *data, time_t timeout);
What happens if delay is 0?

Can user be NULL? What happens if it is NULL?

How large can 'data' be? Is there a limit? Will the send be chunked into multiple dispatches if 'data' is too large? Is that opaque to the caller? Does it matter to the caller?

If none of those questions are answered, the caller must delve into the sendDataWithTimeout() implementation to figure out the answers, and it is impossible to modify sendDataWithTimeout() without possibly breaking assumptions callers make based on what they've assumed from implementation of sendDataWithTimeout().

This applies equally well to blocks of code within a function that accept input and provide output. It helps to be able to reason about them as atomic units, without necessarily paying the code/maintenance cost of hoisting them into independent functions.


> This applies equally well to blocks of code within a function that accept input and provide output. It helps to be able to reason about them as atomic units, without necessarily paying the code/maintenance cost of hoisting them into independent functions.

This seems rather... crazy. Functions serve this purpose, avoiding creating function while still trying to think of your code block as a function is just absurd. Extract the function, if it deserves a comment and has parameters, and isn't an anonymous method for use with a higher order function, then make a real function out of instead of polluting the parent function with its implementation details.

The overhead of this additional function you're so worried about is nothing compared to the overhead of the mess that results by not extracting it. Your strategy favors long functions, yuk yuk yuk.

Listening to you talk, I'm horrified by the thought of what your code must look like; I bet your functions often require use of the scroll bar.


Functions for four lines of code is stupid when a simple one line comment would suffice.


No, it isn't; that's is precisely the purpose of a function and precisely the wrong way to comment.


Given the mental and work effort necessary to hoist out a function versus writing a simple comment, I think your position involves untenable trade-offs.

I'd much rather see code commenting the major steps of the function than a file riddled with tiny functions, all of which require breaking my train of thought, switching to a different section of the file to read, and then going back to the original function.

That's ludicrous compared to a one-liner "Send our token to the server" comment on a small block of code.


It's no effort, it's a simple automated refactoring, right click, extract method, choose name, done. I think your positions betrays your age and tells me you probably code in a text editor rather than a more powerful IDE. To fear extracting a method is just insane to me, a sign of past times.

Functions shouldn't have major steps, they should be one step each with a top level function calling the steps in sequence. A function should do one conceptual thing, or be a delegator to sequence other functions.

Mixing levels of abstraction where all the steps are inlined into the larger master function that also sequences them is IMHO a code smell that demands fixing. Kent Beck had quite a bit to say about this very thing in Smalltalk Best Practice Patterns.

Like I said, I bet you use the scroll bar a lot.


> Like I said, I bet you use the scroll bar a lot.

Says the fellow that hoists incredibly simple code out to independent functions.

On the subject of age, since you broached it -- Given your seriously arguing for not commenting, coupled with the naive hubris so often associated with youth, I can only assume that you're ether young, inexperienced, and/or do little work in maintaining production code across the years.


Wrong on all counts. I'm old, experienced, and maintain decades old systems.

And I'm not arguing for not commenting, I'm arguing for writing more expressive code so that function names are the comments and additional comments are not required. Nothing beats executable comments.


So, if the method was commented, would you:

(A) assume the comments are correct and skip reading what the code does?

(B) use comments as guidance and read code anyway?

The first seems awfully risky to me and poor advice to any programmer trying to write solid code.


> (A) assume the comments are correct and skip reading what the code does?

Yes, unless I was working on that particular piece of code. There's often far too much code in a code base to waste time reading it all, and reading the comments can provide quick understanding.

> The first seems awfully risky to me and poor advice to any programmer trying to write solid code.

Why? Bad code is bad code. Writing bad comments (or no comments) means you're writing bad code. Don't write bad code, and then write documentation to help yourself think through why it's not bad code, and tests to both help you think through it, and verify that it's not bad.


> No real world code is simple and elegant enough that you don't need to think through the complex invariants of the code

in my experience working on enterprise biz apps the opposite is true. comments are what you do when you don't have time to make the code explicitly match your mental model of the proper solution. "don't have time" is a bit of a euphemism, as a lot of people don't realize that it is possible to write code that explicitly matches our mental model of the solution, but whatever.

here's an example: python lib requests vs urllib2. one of these could probably use a comment. the other is self evident. https://gist.github.com/973705


In my experience working on enterprise applications, the worst code is that written by programmers that think they're so smart -- and their code is so good -- that it doesn't need comments.

No programmers are that smart, and no programmers are that good. I'm innately distrustful of any argument that's predicated on "be smarter than average".


If someone writes poor code, what makes you think they will be able to write quality comments? The reality is that if you are poor at expression, you are generally going to be poor at it in all mediums.


Yes. I generally see a correlation between no comments/bad comments and bad code.

They're signs of someone being too intellectually lazy to take the proper care necessary to produce good code.


I'm inclined to agree, but it is the generally accepted attitude in the industry.

Programming is design, but programmers are routinely taught that they do not need to care about design. The de-facto training facility for the industry, a CS degree, rarely goes into artistic endeavours (naturally, but students rarely take it upon themselves to fill their skill gaps after graduation). In fact, it is the status quo for programmers to joke about how poor their design skills are.

Good programmers go over and above and study not only the theory behind programming, but also design. Until we start promoting that programmers must be good designers, the problem will continue.


No real world code is simple and elegant enough that you don't need to think through the complex invariants of the code

Unless, of course, you write in a functional language like Haskell. All those invariants become explicit and your code magically becomes simple


If this is the intended meaning then I disagree. The problem is that the kind of code most of us write isn't pure implementations of algorithms backed by formal proofs. In that case the code is the documentation because it is an expression of a mathematical description of something.

The code most of us write is a hodgepodge of business logic, frontend code, and a bunch of glue to make it all work together. In the case of business logic context is highly important. Just looking at the code doesn't convey the whole story or the "why" this code does what it does. In this specific case comments are the difference between saying "we don't know why this works," and "according to BUG-#### we need to send the counterparty this field as a logon credential otherwise their system behavior is undefined."


A bad comment can waste a lot more time than the absence of a comment or a useless one (like x += n; //add n to x).


I think comments should be more to explain the why and not the what necessarily. Even in the example x+=n, the what part is simple. you are adding n to x. But why are we doing it there could be important to comment in the context. May be this addition changes the variable to trigger another action etc ?


I'd say build your code such that you don't need to comment but comment wherever there is some unclear reason for why something is done.

Instead of x+= n; running_total += total;

But comments are helpful for understanding the reasoning behind why something was done.

For example: $.resize.delay = 16;

Was placed in one file of some code I collaborate on with the comment "// this is probably a horrible idea"

I had to ask the developer what exactly the code does (yeah I could have looked it up but since he said it was a horrible idea I wanted to know why). Turns out it just configures the jquery resize event to fire at about 60 frames per second.

Having a comment like: // Configures jquery resize to fire the resize event approx 60 frames per second

Would have made the code a bit easier to understand.


> Having a comment like: '// Configures jquery resize to fire the resize event approx 60 frames per second' Would have made the code a bit easier to understand.

I'd argue that the following line is a better solution in every way than adding a comment as you suggest:

    setResizeEventFireRate(60); //just pseudocode of course
Self-commenting code is always better: less duplication, less maintenance, greater refactoring agility, and most of all, it encourages you to design a cleaner system in the first place.

Granted, in real-world scenarios, there will always be many cases where you are forced to add comments, sometimes extensively (hand-optimized code, inherently complex systems, etc).If anything though, this only confirms how important it is to aim for self-documenting code.

Real-world production code is rarely a pretty thing, and the fact that you have to start adding comments everywhere is a reflection of this. You'd be surprised how clean and elegant code becomes when your only goal is to make it as self-descriptive as possible.


Not surprised -- definitely agree that the code involved could be improved.

That said there is a bit of a code smell to what you're describing; having separate functions just to set the resize event time is a bit much.

What I think would be better is to set a constant to the resize frame rate and then remove magic numbers so that people viewing the code would understand how it works implicitly without the comment like you're describing. That or improving the library such that it's more clear what's exactly happening.


The "//just pseudocode of course" meant that that wasn't actually how you'd do it. Instead, you'd come up with an overall better design in how you handle resizing pages. If anything this proves the point that self-documenting code forces you to re-think your design often when something is fishy to begin with. In this case, setting "$.resize.delay = 16;" probably is an effect of deeper design issues. Not being able to fix it by just moving it into a function simply means that striving for self-documenting code forces you to fix the issues rather than patch them with half-hearted (or worse - a highly detailed) comment.

If there was ever 'code smell', it's when you see "x = y; // verbose way of saying sets x to y". And this is exactly your example - a verbose description of "$.resize.delay = 16;" If renaming variables and functions in this case doesn't make you feel better, I don't see why a comment would.

But yes... of course comments are important and needed in some cases, which I admit. However when they do, as other posters here have mentioned, it's usually annotating why, not how/what. I can't think of many reasons why it's not a bad sign if you find yourself explaining how something works - the only one that comes to mind is with hand-optimized code.


I think there may be some confusion.

The code in question is a configuration option for a third-party jquery plugin. There may be better plugins which expose their configuration options differently but I personally think that the benefits of using the library itself outweigh building something entirely from scratch for a more purist interaction. I've worked with some gross libraries before and I think that the benefit of using them outweighs a few comments for obscure settings.

The third party code in question isn't terrible as you can assume it's the resize delay from its name. I think what made it terrible was the fact that since a magic number was used (16) it wasn't as apparent for a reasonable developer to grasp without questioning it. Yes, some people will know that 16 milliseconds equates to around 60 frames per second but I don't think it's reasonable to assume everyone who looks at it will. It was a bad example on my part, however, as with a constant as opposed to a magic number you don't need the comment at all.

The code smell I mentioned was wrapping a third party configuration in a function as a way to limit commenting. I think commented configuration options make it easier for other developer to grasp why something is configured that way -- especially for code that will be minified.

I don't think I explained well enough that the code in question was from a third party interaction, however, so could see how we may be on different wavelengths. I'm also by no means a purist when it comes to comments though so I'm sure we may have opposing views (although I agree with the general idea as you mentioned to annotate why not how/what).


Be it as it may, magic number or not, that line should not need a comment. My principle above still holds: needing comments tends to hint that your design could be better and/or your code could be cleaner.

Maybe your library is flawed. Maybe JS is fundamentally flawed. I'm not making any comments one way or another about what's flawed in this picture or how to fix it, just that seeing this comment indicates room for improvement.

Imagine the ideal design/architecture for a given application on all levels. Does it involve the users of this code or API explaining everything in lengthy comments? Or does it involve a clean, beautiful, and elegant set of interactions that is both transparent and intuitive as to what is going on? The latter, I argue, needs no comments. The former, I argue, is indicative of design flaws or inadequate function names.

So why do we see necessary comments in real life, then? Because real life system designs are rarely ideal. I still like to try to get as close as I can, though.


The thing is, having a comment in a tricky bit of code, and knowing that the comment may be confusing because some jackass (maybe myself six months ago ?) changed the code but missed the comment is IMHO still better than having no information whatsoever.


>Don't become the old people you hate, always try to learn new things, no matter how alien. So following that: There's a good talk about Code Documentation: http://www.youtube.com/watch?v=tCw7CpRvYOE


What others have said. Good code is self commenting. I prefer to see comments reserved for instances where its not clearly obvious why a piece of code exists (hacky workarounds, etc...)


Don't hate the old people. They have a lot to teach.


You're right. I guess I meant the aspect of fear one has of new things as they get older. I hate that personality trait. It is more prominent in older people.


I don't think a lot of older people are afraid of new things. Instead they are more skeptical, because they've seen it before and it isn't as new as you'd like it to be.


Something in one of Zed Shaw's old talks stuck with me. Roughly:

"Don't go with the flow of the industry. Try [unconventional] things because there's something beneath [software] that we haven't figured out yet."

I suppose there's two personal disclaimers:

- I'm not that interested in the business aspect of software.

- The answer to what the magic beneath is may elude me due to it simply being "math, stupid".


...due to it simply being "math, stupid".

Care to elaborate?


I liked "err vicariously" ;-)

It's good to learn from your own mistakes, and even better to learn from someone else's.


Yea. A good workplace is one in which calling "that one is my fault" is a natural part of your work flow and doesn't cost you points (unless you become to frequent).


Yeah, but sometimes "vicariously" doesn't cut it, you have to "do the work," you have to grind it out.

http://raganwald.posterous.com/what-ive-learned-about-learni...


Hey, it's a pithy one-liner (two-worder) -- and like any such chestnut is going to be wrong a lot of the time.

Even so, learning from someone else's mistakes is "cheaper" than making mistakes yourself. The further you can get by avoiding mistakes others have made so you can get to your own personal mistakes, the better.

I'd say "err vicariously" gets better the more you think about it, rather than needing to be nitpicked.


It's a maxim. It's supposed to guide your behaviour, not be taken 100% literally.


>Always back up before tidying up. I liked this piece of advice, it's a lesson we all hate to learn.


Happened to me last night -- I wish I read this yesterday. Who am I kidding... I prefer to learn these lessons the hard way :)


Don't you use version control?


Version control won't save you if you start tidying up (and introduce new bugs) before you commit changes.


You shouldn't be making commits so monolithic that that becomes an issue.


I read it as s/backup/commit


long long ago, version control was something i avoided as i was yet to see it's benefits and it was an avoidance to the problem at hand (learning to program).

with git this isn't as necessary, woopla.


To be fair, version control and backups should be separate things.


Right, because your backup is a VERSION of the code that you want to keep around, in case you need it right?

Some version control tools don't let you create local, private versions. That is too bad. That doesn't mean that doing so is not a version control concern.


IMO version control, file versioning and backups should all be separate things and ideally all available.

Even when using a version control system that allows for robust local branches, sometimes it is nice to be able to revert a specific file's state to a known recent version that you never bothered to commit. Sometimes editor undo is sufficient for this, sometimes not. Dropbox and Google Drive have both saved me some time in this area (like 15-30 minutes, not days, but even that is appreciated) recently.


Isn't that just evidence that your commits aren't granular enough? Certainly, simply backing things up generally won't solve your problem, since good backup procedure can involve offsite storage being hours out of date.


I miss VMS, it solved this problem in such a naturally elegant way.


I would add: Don't release on a Friday.


Sadly, the company I work for ONLY releases on Friday nights because the business closes out at 5pm. sigh


Communicate often. Have a beer with a fellow programmer. Don't be afraid to break code.


> Don't be afraid to break code.

Just not in production :)


Problem is that code always breaks in production. What we should strive for is not to cause a critical break that creates massive loss for the company. But code has and will break in production.


Even better is to have an automated immune system that detects production issues and rolls back. We push to production dozens of times a day with dozens of engineers committing, and with that environment, problems will eventually slip through your local tests and buildbot.

Bugs happen; it's far better to focus on robustly dealing with problems than it is to build layers of bureaucracy and process in an attempt to pretend that you can avoid all errors. At my current company, dozens of engineers are pushing to production dozens of times a day. We have an extensive test suite that runs on every commit before code can be pushed to production, but there's always something that slips through, which is why we also have an automated cluster immune system that can automate a rollback whenever any metrics go bad during or after a push.

Bugs happen; life is better if you expect it and plan for it. My philosophy is, break production, and keep breaking it until you're damn good at dealing with production failures. Don't let fear of breaking production slow you down.


There's no better way to learn.


> There's always plenty of room for improvement - in your code, in your abilities, in you.

I just saw an amazing movie about a man that embodies this philosophy: "Jiro Dreams of Sushi"[1]. This man's dedication to further mastering his craft is unparalleled. Even though he is widely regarded as the best Sushi chef in the world, he is still singularly focused on becoming better every day.

I highly recommend watching - it's very inspiring.

[1] http://en.wikipedia.org/wiki/Jiro_Dreams_of_Sushi



The bit about there always being room for growth was driven home for me yesterday as I was looking through how to build an object model in PostgreSQL using object-relational features. I went through the features one by one and discovered that I had only scratched the surface of that aspect of PostgreSQL. I suddenly understood how to rethink what I was doing in terms of design patterns in order to build object interfaces in the db for the relational underpinnings.


It is written so beautifully that the "code" part of these thoughts can be substituted for many other things: design, engineering, life etc.


Don't be an asshole

Agreed but on the page, it looks a bit of out of place with the other points.

My mind fills in the details as "don't act like you are the programmer who's a hundred times more productive than the others, even if it seems like you are".

But that's a big question. Apple Computer arguably expects its programmers to all be the x100 producers and was managed by someone who it more or less was admitted to be an asshole (a genius, inspiration, unique asshole but still an asshole).

So it think the greatness and asshole-dom question is not settled for people even if I would embrace it.


"Err vicariously"

Loved that. Subtle, yet deep!


That was a short, concise, pragmatic, wise and rockin article.




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

Search: