A few basic things I've learned over the years:
See also MethodCommenting for related information, and WellFactoredCode for the XP "we don't need no stink'n comments" approach. ;->
Use indentation to convey meaning. Where the meaning is the same, the indentation should be the same, and where different, different. This may mean that a single language construct is indented with more than one style. For example, "else if" should be indented to look like a "switch" rather than a train of "if"s. Think of it as a new construct, "elif", as found in some languages.
I want to use this principle to justify my two layouts for "switch":
switch (e) { case e1: statement; break; case e2: statement; break; }and:
switch (e) { case e1: statement; break; case e2: statement; break; }I use the former to save space where the statements are short - often they are single function calls, or even "return"s (and there is no "break").
(I said "want", because I'm not honestly sure it follows.) -- DaveHarris
''I think the reason you can't justify the second is because it blurs the line between case statements; they're not very clearly defined. I think that
switch (e) { case e1: statement; break; case e2: statement; break; }would be a little easier to justify. At least, I certainly find it to be. However, as a student of KevinBraunsdorf, I believe that CurliesAreFree?, so I also put curlies around my case actions. That is,
case e1: { statement; break; }It admittedly takes an extra vertical whitespace, but I think it's worth it.''
I'm experimenting with something like the following style for switch statements:
switch (e) { case e1: { statement; } break; case e2: { statement; } break; }The innovation being the placement of 'break' outside the case block and at the same level as the case keyword. This follows the first proposed rule because 'break' affects control flow _between_ the elements of a switch statement. From a practical standpoint, it makes breaks easier to find. -- JayDunning?
This may be covered in ExtremeProgramming somewhere, but in my opinion, NONE of the previous coding guidelines should be used except the first (pick a style and stick to it). Coming from a Smalltalk background, my general rule of thumb is "if a code section is long enough to need a comment, it's probably too long and should be refactored down to something smaller". I have stuck with that rule of thumb as I've taken up Java and I'm still quite pleased with the results.
Are you following the discussion in MethodCommenting? -- DaveHarris
Yes, I have been, although I don't necessarily think that that discussion has made a lot of headway towards resolving the problems. Let's take each of these points one at a time.
Every major section gets a block comment ...
If you mean "method" or "class" by "major section" then I agree with you completely. No one doubts that that kind of information is both proper and necessary to understand things at that level. If on the other hand you mean "section within a method" my question is "why is your method that large?"
Every major structural block gets a block comment...
Again, why is this necessary if each method contains one and only one major structural block? This seems to me like putting a band-aid on a problem.
Long or deeply-nested structures get "refer-back" comments...
Again, why are they so long? Can they be split up?
Separate interface comments from implementation comments...
I think this may be language dependent. What do you mean by this? Can you give an example in Java or Smalltalk?
Use blank lines to separate visually code which is separate logically...
If code is logically separate, why is it in the same method? Couldn't you factor out the code into another method?
It seems to me that the logic behind many of my points are best covered in some of KentBeck 's patterns: ComposedMethod, DecomposingMessage?, IntentionRevealingMessage?, and MethodObject (from SmalltalkBestPracticePatterns).
A Java example for Separate interface comments from implementation comments.... It comes from some code which turns a polygon into a series of smooth Bezier curves.
// Although the fit code generates extra Beziers as needed, // we can get a better fit if we split the polygon in advance. private int maximumSafeBezierRangeEstimate( int first, int size ) { // This version tries to detect features like sharp corners // by looking at the angle of turn between segments. // Previous versions just looked for long, straight segments, // but that didn't work so well.The first comment is what the routine does, and why; the second is how it does it, and why. The first is talking about the context in which the routine might be called; it tries to explain why you might want to call the routine. The second is implementation detail, a discussion of different algorithms for achieving the desired result. -- DaveHarris
I may have given the impression that I think every routine needs two comments. That wasn't my intention. My point was to distinguish between readers who want to call the method and those who want to change its body. If there are comments, they need to be aware which readership they are aimed at.
I agree that code factoring and good choice of names reduces the need for comments, and I don't think every routine needs a comment at all. (In that I disagree with many points of the original list.) However, I don't think comments can be eliminated altogether. Some of my reasoning is in MethodCommenting. -- DaveHarris
In ThePracticeOfProgramming, Kernighan and Pike say As much as possible, write code that is easy to understand; the better you do this, the fewer comments you need. Good code needs fewer comments than bad code.
... Yes, but one of the criteria for good code is that it should be maintainable. Comments help achieve that objective - especially in a verbose language like C++.
The comments inherent in the code argument, assumes that everyone is necessarily conversant with the problem domain. In the real world, this isn't necessarily so. Furthermore, the poor person who comes along to fix or enhance the code four months later will most definitely view the domain differently, and will most likely have a different skill set or level. Code should be written and commented for THAT level - the lowest common denominator. Most leads and managers would rather hire a programmer who writes maintainable, well-designed software full of comments and hints over a smarty who can save a CPU cycle with one-liners any day.
I have long believed that when it comes to software maintenance that most programmers spend at least 80% of their time trying to work out what was done before and why it was done that way. If this 'cost' can be reduced in any way, then surely it should be done. -- AlexHoffman
There are a lot of people on Wiki who would agree with your goals Alex but would question code comments as the answer. Have you had a look through MethodCommenting for example? (If you're a new contributor, by the way, I hope you enjoy it around here.)
The issue of different developers having different levels of familiarity with the problem domain is a key one. I may have missed it but I don't think that we have dealt with that issue so adequately on Wiki. I touch on it very briefly in passing in KnowHowToGrow subpoint 3 but it's a good deal more important than that implies! DaveCleal questioned some of the tenets of ExtremeProgramming in this regard a while back. Click on the title of Dave's page to see everywhere he's mentioned. Oh yes, it was one the longest WikiNames of all time, DavesRealExampleWhereThinkingAheadWouldHaveHelped. Although I largely agree with the XP "answer" in this instance as well, I'm not sure, as I say, that Wiki has addressed the "familiarity with problem domain" issues sufficiently.
In fact this point has just prompted me to ask a question I've wanted to for a while in TerminationCanBeSuccess. -- RichardDrake
This page mirrored in WikiPagesAboutRefactoring as of April 29, 2006