I've never seen a language's style guide recommend avoiding comments before
haskell.org
haskell.org
Comments are useful to describe __why__ you're doing something, often when you are not able to change the unexpected behaviour. Whenever I build an API library, my code is littered with comments like "Acme Corp API requires this happens before that" with a link to that bit of the API documentation.
Here's a C++ example about "documenting surpises" (taken from Steve McConnell's Code Complete:
for ( element = 0; element < elementCount; element++ ) {
// Use right shift to divide by two. Substituting the
// right-shift operation cuts the loop time by 75%.
elementList[ element ] = elementList[ element ] >> 1;
}
And a Java example: /* The following code is necessary to work around an error in
WriteData() that appears only when the third parameter
equals 500. '500' has been replaced with a named constant
for clarity. */
if ( blockSize == WRITEDATA_BROKEN_SIZE ) {
blockSize = WRITEDATA_WORKAROUND_SIZE;
}
WriteData ( file, data, blockSize );
He also gives a whole list of situations in which comments are a bad idea, and it's similar to the OP.A modern compiler can inline most of your function calls if you like. That way you can factor the code appropriately for both concerns.
Please note that in many cases putting an algorithm in a single function is the wrong choice but there is also a cost in splitting it.
Plus your annotations are updated! Comments wither and die.
[Edit] to be clear, if there is something going on that would cumbersome to "document with types" i just write comments. There's also a place for function description and example.
As a rule of thumb, if I've thought more than 20 seconds about what a particular section of code has to do, I comment it.
Unfortunately, having been doing this trade for 30+ years, I've found most people write crappy code in a hurry to try to hit some deadline based on incomplete requirements and confusing business rules. A few precious comments stuck in there can help the next guy, months or years later, figure out what the heck your original intent was or why a block of code exists at all.
As I get older, I find it helps me remember what I was doing.
One of my software developer friends was fond of saying: "the worst code I ever saw was my own!"
YES if your code is clean and elegant and well named and clear you don't need to explain anything in common language.
YES you should strive for such.
However, the REALITY is your code sucks and no one is going to want to have to figure out what the heck you were doing. A few comments would really help.
The next reality is that the typical developer may be literate in a dozen or more languages and the language du jour that you coded so elegantly in has fallen out of favor and no one remembers those dusty corners you so beautifully exploited to make something work.
Comments would help even more if you learn to use some basic grammar and spelling when you create your comments. (It doesn't have to be literature, but try to make your comments as readable as you think your code is - please!) Nothing will turn another developer off to trying to decipher your code than a few comments that make you look like a moron.
Style guides that eschew comments, IMO, are counterproductive. They feed on the developer's ego and disregard reality.
Comments cost essentially nothing to add to your code and can save it from an early death and complete refactoring by the next guy who comes along.
Leaving a note about that weird thing is probably a good idea.
A novice programmer will just do the weird thing (no comments).
An intermediate programmer will spend twice as much time as they should, trying to think of an elegant solution, before doing the weird thing anyways (and maybe leaving a comment).
A good programmer will just do the weird thing, leave a comment, and move on.
-- NOTE
-- This is called by the database-level DDL trigger.
-- Do not drop it. Do not break it.
We don't have a dev/qa environment, and tend to be a bit... lax about change management. There are a few pieces of code that this is particularly unsuitable for. function f_soundex (p_in varchar2) return varchar2
is
-- [name of specific source file from one of our other systems]
-- If the first (kept) letter has the same code as the following letter,
-- a proper Soundex ignores that following letter. The [other system] soundex
-- keeps it.
Sometimes it is necessary to do weird things for compatibility reasons. // See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98335
// Apparently, DestroyHandle doesn't get called properly when a control is disposed. Since this
// makes Invoke() hang, we have to fix it.
Sometimes external libraries/frameworks have bugs to work around. /* Don't let things scope to the repeat block. Even when they aren't used, they
make the end statement slow. read-record.i has strong scoping for the data
tables, and everything else is lifted to procedure scope. */
Sometimes there are performance reasons for doing things in a particular slightly odd manner. Sometimes there are correctness reasons (as with a 9-line comment earlier in the same program as this last example).But comments are most useful when they explain why something is being done, not what's being done. The latter is usually simple to work out with even the most hideous code. But if I don't know what you were trying to do or why you did something in a particular way, seeing what you did alone may not be all that helpful, especially when maintaining code.
Indeed. However, when developing software I'd expect that the responsibility is first to express yourself clearly in code and only second to express yourself in prose, which means if you're taking very much time to do the latter it's time that could be spent doing the former.
That's a good reason to avoid breaking up logical blocks of code with comments.
Its not a good reason not to comment.
> Bad code with useless comments is worse than bad code with no comments.
That's a good reason to have code review (which includes review of comments) to ensure that there is neither bad code nor useless (including out of date or misleading) comments.
Comments have certainly aided me enormously in navigating very large, sometimes crufty, codebases.
Whatever their benefits are, this is not true at all. Comments are expensive to write and maintain. They are VERY VERY expensive to maintain because there is no automated way to test them.
Reason: In Software Archeology (a.k.a. maintaining legacy code) you are often happy to get any kind of clue as to what went on inside someones head. Maybe they saw an edge case?
Of course you should write self-documenting code with variables and function names that explains most of it but when you either have to
1. factor out a new function
do_this_to_fix_that_weird_thing(weird state)
or
2. have to add a line
state == weird ? fix = fix+1:continue // weird is a weird state that sometimes occurs even though vendors api docs says otherwise.
please think twice.
Outdated comments are a problem but very often a problem I'll happily deal with compared to not having them at all. If a comment doesn't make sense you can also try checking VC history.
3. fix_bug_that_occurs_even_when_api_docs_say_otherwise(weird)
A comment on its own isn't inherently harder to maintain any other piece of code or documentation. Sure, it's not zero cost, but I find more often than not they exceed the cost associated with not commenting.
Some system of backrefs could handle this, of course, but I'm not aware of anything in use...
The only time a comment should refer to non-local information is to document an assumption or basis of the local code, which is still correct information about the local code as long as it is the assumption/basis of the local code, even if the assumption is (or later becomes) false.
Of course, it would be useful to have a way to verify the information about the assumptions to see if they have become false, but that's not about validating the comment, that's about validating the code it comments, since if the assumption is false, it is quite likely that the code needs to change (and this may not be something that unit testing the local code can discover, as such comments often are not about correctness but about choosing a less-than-obvious alternative correct approach for optimization, or to work around a quirk of the code being called, etc.)
Comments also break flow and get in the way of code reading, but could probably just be hidden during review.
Actually, that only makes them hard to review if you are trying too hard, which defeats the purpose of reviewing comments -- if it is hard to validate the utility of a comment without the context of the programmer involved, its a bad comment and needs, at a minimum, to be clarified.
After all, the whole point of a comment is to communicate information to a future person who lacks the context of the programmer involved.
Comments are highly valuable but like any tool they can be abused, or done in such a way that they don't make things better.
To be fair, the style guide that's linked to doesn't actually say not to write comments. It says that if you're going to write a comment, think twice. Maybe you can make the code clearer instead.
At any given time I'm writing code as clearly as I can given my experience and body of knowledge. It also is representative of my exposure to and familiarity with the problem domain at that point in time. As these things evolve, my older code ceases to be as clear as I thought. It may very well not be the way I'd solve the problem again.
And that's before I need to start making changes to code clarity to satisfy a hard requirement (reduce memory usage, cache values, tighten up performance, etc.).
Are you looking for an excuse to be lazy? How about "I'll just put a comment in there and not worry about it"...
The actual code I work with is fairly straightforward and easy to understand functionally. I can understand the what of pretty much any of the code my organization runs in short order.
But the why is vital. This week I've implemented things for reasons I won't remember in six months. Simple, easy to understand code. I've also been fighting with another system that predates me. I can see that it's modifying the original message to map particular values elsewhere downstream, but I have absolutely no idea why or which downstream system is expecting them. I've lost hours trying to track this down when a line or two explaining WTF the piece of code exists would have told me exactly where I needed to look.
Yes, your code should be understandable and self documenting to some degree anyway. But your code doesn't exist in a vacuum, and can't document what exists external to it.
I also think you should target for 0 comments in an ideal world. Every time I write a comment I remind myself, can't you really write this in a more obvious way?
But reality is that exercise requires time that you don't always have
A few precious comments stuck in there can help the next
guy [..]
More than spending that time on improving the code?- The proper use of comments is to compensate for our failure to express ourself in code. Comments are always failures. We must have them because we cannot always figure out how to express ourselves without them, but their use is not a cause for celebration. So when you find yourself in a position where you need to write a comment, think it through and see whether there isn’t some way to turn the tables and express yourself in code.
- The older a comment is, and the farther away it is from the code it describes, the more likely it is to be just plain wrong. The reason is simple. Programmers can’t realistically maintain them.
- Comments Do Not Make Up for Bad Code! One of the more common motivations for writing comments is bad code. We write a module and we know it is confusing and disorganized. We know it’s a mess. So we say to ourselves, “Ooh, I’d better comment that!” No! You’d better clean it! Clear and expressive code with few comments is far superior to cluttered and complex code with lots of comments. Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning that mess.
``` // Bad:
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
(employee.age > 65))
// Good:
if (employee.isEligibleForFullBenefits())
```I also find TODO comments quite helpful. It requires far fewer brain cycles to process a TODO comment than to parse the code, figure out what it's doing, and make an assertion that it's incomplete.
Comments can also make code much more approachable to junior programmers, who may not have heard of principles like Tell Don't Ask, or Composition Over Inheritance. When I'm working with a junior dev, I find that comments usually reduce the number of interruptions I receive that are along the lines of, "Hey why did you do this thing this way?"
Really, it's just not a good idea to make sweeping generalizations like, "Comments are always failures". The real world has time and budget constraints, and comments are sometimes the most effective way to satisfy those without screwing the next developer to read the code.
Why not? The effort involved is not very high.
If you mean that they won't maintain them, well, I agree. Sometimes I fail to do so myself - but that's my laziness, not because keeping a comment up to date is actually difficult. The fact that programmers can be lazy is why we put processes in place to catch ourselves - code reviews, code style enforcement, and so on.
Because, realistically developers will be lazy. For example:
"Sometimes I fail to do so myself - but that's my laziness"
> code reviews
So, here is the thing, "programmers can be lazy." Programmers can also miss things. Code reviews don't catch everything.
So, when someone says "programmers can’t realistically maintain them", they are being realistic. Really. It's great to be hopeful, but the simple fact is, you can't trust that comments are maintained.
There's nothing that intensely difficult about implementing processes that keep at least the vast majority of comments up to date. If you don't feel like it, or your organisation doesn't have the will to enforce it, then fair enough. That's not the same as it being impossible.
I should refactor. But sometimes it's not feasible when you're in a hurry and the area has no unit tests to prop it up. Adding a tag "TODO: CLEANME" or something similar works as a reminder.
I think it's a common fallacy to believe that it is our failure when we can't express a particular thought. The language itself, be it human or the far more restrictive and qualitatively restrained computer version, is deficient in many regards.
/**
* Frobnicates a foobar
*
* @param Foobar $foobar The foobar to be frobnicated
* @param int $intensity The intensity with which the foobar will
* be frobnicated (defaults to 4)
* @return mixed The result of frobnicating a foobar
*/
function foobar_frobnicate(Foobar $foobar, $intensity=5)
{
// frobnicates the foobar
return $foobar->frobnicate($intensity);
}
It's utterly ridiculous.Pretty sure I've been guilty of this in the past, too. As I recall, the documentor tools make a lot of noise if you don't supply wasteful and irrelevant values for every single little thing even if it's blindingly obvious from the symbol, context or idiom what it means and what it does.
The purpose of this comment is obviously not to clarify the code for someone working on it, but to ensure the automatically generated API docs stay consistent. I write comments like these above functions all the time, because we have a zero-warning policy for doxygen comments over here, to prevent people forgetting to document public API methods (or slacking off out of laziness). Sure, the comment block is redundant since it contains nothing that cannot be derived from the parameter names and the name of the function, but it does make sure a doxygen run will not spew warnings and errors all over the place, drowning out uncommented methods with far less obvious functionality or parameters. The redundancy is a small price to pay to enforce a good self-documented API.
I really don't understand any of the discussions about not documenting code because it should be 'clean and obvious'. First of all that's mixing up 'how' and 'why' code is like it is, second it's a small effort to write and maintain code comments (contrary to what some people like to suggest otherwise), third it can help you organize your thoughts while you are writing the code (write the steps of your algorithm in comments, then translate them to code), etc.
Personally I also like how the syntax highlighting breaks up blocks of code with API doc comments, which makes it much easier to see where functions start and end when scrolling fast, or how they can separate distinct steps of an algorithm. 'No comments' really is the inverse of 'literate programming', like most of the time, the truth is probably somewhere in the middle.
http://www.haskell.org/haskellwiki/index.php?title=Commentin...
It isn't official in any sense.
In the bitcoinj code style guide there is a big section on comments that gives positive examples as well as negative examples:
One of the best cases for comments IMO is documenting an unexpected behaviour on the part of a third-party API. But even then, correct exception / error-handling code can obviate the need for comments in many cases.
If I'm reading code (from an experienced programmer) and I see a comment, I immediately pay attention, because Here Be Dragons.
For scientific coding, comments should align with the underlying theory for the code: “This implements matrix transposition with regard to ... as defined by ...”, so that next generations can align code with papers better.
And when you’re in a wacky environment like the PHP runtime or coding for a moving target like the browser, comments might be indispensable to explain one or the other really strange way of doing things, where you simply have no other choice. Look at the [jQuery source code](https://github.com/jquery/jquery/tree/master/src), where they comment excessively, which browser quirk they address with which work-around.
100x this. Scientific software should be held to a different set of standards than non-scientific software, primarily because you can probably not assume that your reading is familiar with the underlying domain.
As someone who works as a programmer and system analyst dealing with code in a non-scientific business domain where I've also worked on the domain side, I don't think that this separates scientific code from any other codes. Programmers often disdain domain knowledge beyond that which they already have found to be immediately relevant. Which is perfectly understandable -- there's a reason they chose to specialize in programming rather than as domain experts in whatever domain.
But I think complicated program segments related to business practices etc. also deserves comments, even just "see spec xyz" or "see section 1.2.3 of code xyz" (similar to how you might say "See Smith et al. '14" in a scientific setting)
(Preferably the reasons for discarding the simple solution should be provided as well, as circumstances may change.)
(<+>) :: Monoid m => m -> m -> m
(^?) :: s -> Getting (First a) s a -> Maybe a
As a Haskell beginner I didn't find it to be a particularly self-documenting language. Between the use of custom operators and point-free style you can write a lot of code without naming anything to give a hint about what you're doing. * Return the first parameter
* Return the second parameter
* Perform param1 `mappend` param2
* Perform param1 `mappend` param2
* Return the mempty value for the Monoid m
The first two are unlikely to be correct, since if all they were doing was returning a particular parameter, then there is no reason to have the Monoid type constraint. The last one similarly makes no sense, since it's a function that is identical to `mempty` irrespective of it's parameters.The order of operations however should be documented. I'm almost certain that the implementation is the third function, but a one line comment stating that could possibly be useful.
All of my above reasoning was predicated on an understanding of Monoids. So while I'm not sure the right thing to document is the function, I do think an explanation of `Monoids` should be documented in `Data.Monoid`.
PS - Where is that first function defined? I've used a similar operator defined in XMonad, but if I remember right that was defined over Arrows. Also is that second function from Data.Lens?
* Perform param2 `mappend` param1
I'd be a little surprised if it was the third option, simply because that's already spelled <>. Hoogle doesn't turn up a definition with that signature, though.But let's take a swing at it. We start with something of type (s). At the very end, we're left with something of type (Maybe a). Since we know nothing about the types (s) or (a), we need something to relate these to each other if the function is going to produce a (Maybe a) for us (unless it just always gives us Nothing).
There's a lot going on in that second argument, but we can clearly see that it's some type parameterized by (s) and (a), so it provides that connection. It "tells us how to get an (a) out of an (s) in a way that might fail" - which intuition is additionally helped along by the fact that the type so parameterized is called Getting.
There's a little more going on, and for that you'll need to dive into the (extensive) documentation for lens. One thing that is not going on is any side effects though. The operator section (^? foo) will take some (s) and turn it into some (Maybe a) based only on the information contained in that (s) and foo.
shouldPickWorkUnit :: (ImportId, WorkUnit) -> STM Bool
shouldPickWorkUnit (k, u) =
case hostNameFor url of
Nothing -> return True -- Invalid URLs are fast to process.
Just hostName ->
takeWorkThat'sAlreadyDone <*>
(don'tTakeSomeoneElse'sWork <*>
don'tExceedTheRateLimitFor hostName)
This way, the domain logic is legible from the actual code, which strikes me as almost always better than having tricky code with comments. Trying for this also encourages "domain-driven abstraction," and this is one of Haskell's greatest strengths.In fact, the remaining comment can be factored away too:
shouldPickWorkUnit :: (ImportId, WorkUnit) -> STM Bool
shouldPickWorkUnit (k, u) =
takeWorkWithInvalidUrl <*>
(takeWorkThat'sAlreadyDone <*>
(don'tTakeSomeoneElse'sWork <*>
don'tExceedTheRateLimitFor hostName))
Advice like "avoid comments" needs to be taken as a calling for actually spending time and effort to write obvious code, and for using appropriate abstractions!I don't want to run my internal compiler in my head when i'm reading your code, so you better make sure there's at least a docblock above every function that describes in 2 sentences what it does so I can get a global overview of what the heck this file is doing.
People that suggest that 'the code is the documentation' are always forgetting that reading code is way more taxing on the brain than reading english.
I can completely live with a 50 line function that does magic in a legacy project, as long as I don't have to read through it.
'split it into pieces' is everybody's favorite argument, but nobody is going to pay you to refactor it. DOCUMENT IT.
Code comments definitely fall into this category. I've worked with developers who I greatly respect who are obsessive about code comments. I've even been told that the comments are more important than the code and in that specific context it made sense.
But my own experience and biases make me think code comments are a problem. I like to refer to them as future lies. There is virtually no back pressure on comments to keep them in sync with the code. There is no automated way to verify them and refactoring tools on comments are rudimentary at best. To put it simply, I no longer trust comments and will usually ignore them in order to verify the code itself. I can't count the number of times I've found comments that directly contradicted the code it was commenting. It isn't even uncommon to find comments that are incorrect when they are written!
As to the folks recommending comments that document the "why" of a piece of code, I'd counter that if you have a "why" you have a specification. If you have a specification it should be verified in a systematic way. So performance improvements, or specific client requirements should be encoded in tests so that they don't regress. Comments do not provide that safety.
That's not to say I never comment my code. Just that it always feels like a failure when I do. It is usually because it is cheaper to comment than to provide cleaner code or better verified specifications.
Look at the Backbone.js annotated source [1] (the stuff on the left is just the comments pulled out from the original source JS). The comments make it much, much quicker to grasp what's going on, even though many of them just state exactly what the corresponding code does, which according to the Haskell docs' advice is pointless and to be avoided.
This is golden!
...thus they (comments) tend to diverge from actual implementation.
It happens, you update/refactor code, and forget to update the comments. Thus the comments are outdated or worse not applicable anymore. Common mistake by less-detailed oriented developers. Begs the question, in this case is is better to have confusing/incorrect comments, or no comments at all?A bad description isn't just a problem in itself, it can indicate a worse problem sat waiting to jump out and bite as you walk by.
Yes, but is it the intended and/or desired behaviour in all cases that the codepath in question will be expected to experience?
That is the problem, especially in code that deals with rare edge cases so is not run often, and/or covers many circumstances where it is right but is wrong for one set of inputs that no one thought to test before (or since that code last changes).
http://dl.acm.org/citation.cfm?id=1368215
I'm sure the dissertation is available somewhere on cs.wpi.edu, too.
In my experience comments are no more likely to diverge than tests are. With tests you have the advantage that they must compile. With comments you have the advantage that they are inline/interspersed with your code and so get read every time the code is read.
"It happens, you update/refactor code, and forget to update the comments."
So then the next developer to read that part of the code notices that the comment doesn't make sense, or is not well written, and they update it. No different than if they notice poorly named/misleading functions or variable names or a dozen other code smells. No big deal and certainly not a good case for commenting less.
Just as a heads up, there are lots of testing paradigms that have the tests inline with the code it is testing. That they aren't the default in most languages is most disappointing.
It allows you to document the intended inputs and outputs of the function and state its purpose. This increases maintainability and reusability.
Functions themselves should be short and written as a sequence of logical steps.
I'm also a big fan of doing things right rather than just hacking until it works, which seems to put me in a minority.
I'm guessing Haskell doesn't need that? A simple statement of purpose would still help though?
Currently I only do the following:
/**@fn foobar
* @brief Does foo
*/
-edit formattingIn C at least, I think it's important to specify whether we're expecting a pointer to a single element, a pointer to an array, if the pointer is an output, etc etc. A uint8_t* could be many things...
"In this book we don't use many comments; we try to make our programs self-documenting by using descriptive names."
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html...
In modern Lisp, though, it's still considered good form to include both a docstring, and internal comments explaining anything particularly tricky.
PendingResult<MessageApi.SendMessageResult> pending = Wearable.MessageApi.sendMessage(mGoogleApiClient, mWearableNode.getId(), path, data);
pending.setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
@Override
public void onResult(MessageApi.SendMessageResult result) {
....
}
}
Okay, now suppose this were a Python-based API instead? Perhaps it could be something like this, after some relevant initialisation: wearable.sendmessage(mywearable, path, data)
@wearable.onresult
def onresult(result):
...
Tell me which one is more in need of commenting.That said, I think some of the commenters in this thread should spend time maintaining a MLOC+ sized code base before dismissing comments as 'code smell'. Even in well-written code, if you're a maintenance programmer who is unfamiliar with a particular functional area, a few comments talking about the overall purpose of the code and why it works the way it does can save you enormous amounts of time.
Finally, if people are letting comments go out of date, IMO they have a quality issue. Either the comments are useless and should be removed, or they're useful and should be kept up to date. If your developers are letting useful comment areas go out of date, it should get caught by code review.
It's crazy how much time I spend on them and sometimes they are confusing because the specs change and I keep forgetting to add/remove/update something in a docblock when I rewrite some part of the code it documents (I'd say between 10-20% of my commits are docblock updates).
I believe brief or even no documentation may be the best approach until you are on the verge of releasing a stable version.
While you are on developing and testing mode, it seems a better idea to forget about comments and focus on modularity.
After all, Why would I need comments if all the rest of my team sees is an interface satisfying a previously established and well defined contract? That's why docblocks should be only documenting public interfaces, some kind of dump taken from the part(s) of the contract they implement.
I'd consider instead other top priorites on those phases:
- Keeping an homogeneous codebase in regard of design and coding guidelines and conventions.
- Re-factoring before it becomes a problem
- Writing neat unit and integration tests
And, the most important:
- Keeping a channel open with the client, constantly feeding guided demos and prototypes showing your progress to make sure you are on the right track and you didn't get it backwards, updating specs and being realistic about what can be done and what not in which time frames with the provided resources.
An official style guide? Maybe. But it is one of common philosophies. See for example:
"If you need to comment something to make it understandable it should probably be rewritten."
http://kotaku.com/5975610/the-exceptional-beauty-of-doom-3s-...
Comments often go out-of-sync with the code, so I think it makes a lot of sense to prefer writing comprehensible code instead of trying to explain with comments something totally incomprehensible.
I wrote more about this here (it's Lua code, but it applies to any language):
http://kiki.to/blog/2012/03/16/small-functions-are-good-for-...
-- swap the elements of a pair
swap :: (a,b) -> (b,a)
Yes this is redundant. let b=a+1 -- add one to 'a'
Yes this is also redundantDoes it mean that every piece of code can be expressed as clearly as in a one-line comment in natural language? I don't think so.
Since I don't think anyone here would argue that "increment a by one" is a useful comment, the part about duplicate/obvious comments isn't adding much to the discussion about the usefulness of comments.
Nevertheless, it's true that comments cannot be checked by the compiler, and that's a more interesting point, I think.
What about checkable specifications together with a comment explaining the formula, particularly for anything with a nice physical intuition? This kind-of addresses the out-of-date comment problem.
Another example which came to mind is a Lamport comment about some sort of layout-related thing, I can't remember specifics. The comment gives a really good intuitive feel for why his code produces a nice-looking layout. Without the physical intuition provided by the comment, the code is pretty difficult to grok. I can't find it, so I really hope I'm not making this up...
edit: 2nd par
What the article omits is the suggestion of commenting the right way, i.e. adding reasoning or the description of the high level logic behind the code.
Comments may be a code smell when it is necessary to explain what your code is doing.
Anywhere where you have some freedom to solve a problem one way or the other it may clarify why the implemented approach was chosen.
eg.
// The reason we use a custom swap function instead of
// the one that is shipped with the framework is because
// of an edge-case that occurs quite frequently in our
// scenario
// Refer to Change Request 345.
void Swap (Foo a, Foo b) ....
// get the user $user = $this->getUser();
Times that by the thousands of lines in a project and you have one big headache!
I hope you have a problem with complex functions. (They should be made as simple as possible).
My scenarios for this typically include: * Disposable project, eg prototyping an idea for a client * I have an impossible deadline and I'm on a fixed project rate, maybe I should have quoted more, who knows, it happens
If you do that, after the deadline is over, you will get assigned another task with another 4-week deadline. And then another. The code will get increasingly complex until you can't keep with it any more. And then you will leave the company, or they will fire you. And the people who gave you that deadline will refer to you as "the guy who left that horrible mess of code".
I decided long ago that that's not how I want to live my life.
If someone gives me an unreasonable deadline, I negotiate it. Hard. By explaining the problems, and making sure everyone understands the tradeoffs being made.
And if the deadline is really immovable, I negotiate a period to refactor after the deadline is passed, and in which I am not assigned other tasks.
And if that is not possible, then I start looking for another job. Fortunately now it's a great time to be a programmer.
But hey, if that works for you, then great. To each his own.
Of course, this sometimes happens, but it shouldn't be encouraged. This way you are creating technical debt, which will be very expensive to pay off.
It's hard to explain. You know it by experience.
Writing simpler code is more expensive than writing complicated code for that reason, unless you are a genius who can simplify any complex problem instantaneously. Anyways, your argument basically amounts to "do good, no do bad."
It may be a good idea to comment "what" the code does, if it isn't clear (the code itself is "how" it is done, but "what" does it do may be hard to read, e.g. sometimes you use a clever hack for performance reasons).
As always, handle with care :-)
I know that's absurd in practice, we don't always have the time but I've always used comments as a last resort.
If I need to comment code to make it understandable at a glance, so be it but I'd rather avoid them all together and rewrite until it's clear enough without them.
Using Python or Perl it is easy to go from a for loop to a map or list comprehension. For many less experienced programmers it will make it less readable and more difficult to comprehend. Using a more functional approach will usually lead to less side effects and silly bugs, so I prefer to code this way, and add a comment to explain what the line is doing if it is not obvious.
I shouldn't have to read code in detail to understand it, unless it is broken and I am fixing it. Comments should inform me on the broad strokes of the code.
Let's say you are parsing a standard tab delimited file. You find that the tab delimited file has some non-standard features, so you have to write some extra lines of code to handle it. For people who thinks the code just parses a standard tab delimited file, these lines will be confusing, so you comment these lines and say why you included them.
I appreciate that this type of thing is language dependent.
If the OP meant to be sarcastic, that's just like me saying "yes" when I mean "no"---my mistake, not yours, and you can't be blamed for assuming I meant what I said.
I do favor putting a short comment on some methods/functions/procedures.
Good code needs no test either,... wait no ,that's a stupid thing to say,because nobody writes "good code",code isnt good or bad,it either results in the expected behavior or not.
If it means "the machine executes it and is able to produce the expected outputs with the right inputs", and nothing else, then you are missing a key concept about code.
You see, code is not written for machines. If that was the only reason, we would all write direct binary. Code is written for people. More specifically, other people. (Or you, in the future).
If no one (except a machine) is capable of understanding a piece of code, then that code is indeed bad; it has failed its main purpose. The more understandable by people code is, the better it is.
I agree that once compiled/interpreted, these differences don't matter. Until the next bug or feature request arrives. Then it matters quite a lot.
Assume someone who can't write clear code can write clear comments. Also search and replace clear with "readable" "literate" "concise" and last but not least, "correct"
Assume a programmer has full authority over all 3rd party, supplier and customer APIs, interdepartmental processes, and all business logic, management selected fad technologies, such that its logically impossible to be unable to always factor out weird confusing stuff resulting in clear code / clear comments. My program is the world and none have dominion over any of the rest of it and any other conception of reality is wrong. (And edited to add I've gotten involved in some weird "EE" stuff and like it or not, the world itself is plain old weird and illogical sometimes and if you don't like that, a computer programmer can't fix it, only a physicist, or maybe a diety. This isn't a big problem in the world of CRUD apps but it does happen)
Assume comments only exist as a inspirational descriptional prose tool. Sometimes I use them as placeholders for something I know belongs there but either I or the business are not ready. Sometimes I use them as a cheatsheet because I'm personally really uncomfortable. Sometimes I use them as an outline more like names on a map to orient myself than a travelogue.
Assume all programmers fit the management ideal of identical replacable cogs. "How could someone work here without knowing by heart how to convert dBmW into volts or the difference between S21 and S12 microwave scattering parameters, so I have no need to comment this, but I've never actually used this corner of matrix math while employed before so I'll make one of those laughable comments that is a simple linear translation just to help me keep my head on straight.
Assume comments go thru the same code review process as code. If a comment in file A tangentially relates to function Q in file B, and you modify function Q, your code review process will probably examine file B and the comments in it, but how do you ensure file A gets modified? This is especially bad with those "because" style comments. (edited to add, at least date your comments?)
Assume no metrics exist WRT comments to be gamed. Your continued employment and possible promotion exist because of a content free meaningless metric number, perhaps lines of comments. Ask a professional to generate a number, you'll get a nice number, but unprofessional work. Ask a professional to do professional work, and you get professional results and who cares what the number is. That requires a high caliber of management, usually unavailable. Even worse a low caliber of management, the kind most likely to demand adherence to meaningless metrics, is also exactly the type least likely to successfully evaluate the professionalism of the code so they don't end up with good code. So you get meaningless metrics resulting in meaningless comments right next to bad code, if you enforce metrics.
Assume there exists a silver bullet for comments, just like this months silver bullet fad for code also fixes all problems.
(edited to add) Assume there's one human language. I worked at a place where outsourcing and H1B took complete control over corporate IT such that code comments and even some internal documents were no longer written in English. This makes comments rather hard to follow when engineering tries to cooperate with IT. So... I'd love to follow your detailed internal process for dynamic DNS for my spectrum analyzer, but you guys don't use English and we don't use your India language, so...
swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)
or even this: map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = (f x):(map f xs)
Those functions actually are self-documenting. Trying to explain them further is just going to clutter the page.On the other hand, at 10,000 lines of code, a lot of that being parochial business logic, I'm going to want high-level documentation of why all this code exists. My emotional impulse is going to be to throw out all this shit code (in the business world, all code is shit) so please tell me why that is a bad idea. (I know it is, and I'm not going to do it, but please tell me why I'm not going to do it.) I'm going to want an entry point. I can't count the number of days of life I've lost just looking for entry-points in gigantic enterprise codeballs. Like, what actually runs?
Actually, 10,000-line single-programs should be rare-- Big Software is almost always a mistake, see here: http://michaelochurch.wordpress.com/2012/04/13/java-shop-pol... but that's another rant.