Programmers as Channel Surfers

October 2nd, 2007 | by Bill Kayser |

If a program is to be a work of literature, then where does that leave object-oriented programs? In the era of functional decomposition, programs were built around algorithms and data structures. They executed in a single thread as a sequence of steps and subroutine calls, not unlike a story. Our object-oriented programs, on the other hand, don’t have such a fixed path of execution. Whether server or client applications, they start up multiple threads and make heavy use of message passing and asynchronicity. The essence of a program is not in a sequence of steps and subroutine calls but in the subtle relationships between classes spread across many frameworks and subsystems, relationships such as inheritance, aggregation and collaboration. So how does one read a Java application like a story? The whole idea of object oriented programs seems at odds with literate programming.

It may help to view your program less as a novel read in a single sitting and more like a TV show that is tuned in once a week by busy people with short attention spans. The purpose is still to engage and inform, but you need to keep in mind your audience could be jumping in to the story just about anywhere. Like a viewer flipping through channels, happening upon an interesting show, there’s a good chance that the first time a colleague comes across your code is clicking through the frames in a stack trace. They will be debugging an application trying to understand some unexpected sequence of events and will stumble upon one of your classes. Or they might drop in to use some small part of your API. Maybe they jump into your code to extend some capabilities, add a new feature, or make small changes as part of a global refactoring. They just want to know enough to get the task done and keep going. They might watch an episode but then move on.

There are a lot of practical implications to this approach but for this article I’ll just focus on one: give the user the information they need in the context of just “dropping in.” Think about the questions they might have looking at your code in a debugger: What is this class for? What elements are in the collection? Where did this member variable get set? Don’t make them work to find out something you could have made apparent with very little effort to begin with. Your goal is to give them enough information about each element so they won’t have to get sidetracked tracking down other references to the element just to see how it’s used . For example:

  • Don’t make it a precondition for them to read a big design document on your intranet just to be able to understand what your GizmoClass is. Put the information as close to the artifact as possible. In the code, or at least in the same directory as the source.
  • Document all your classes and interfaces. This may seem like a no-brainer, but it’s not about spending more time writing comments. Instead, keep it as simple as possible. Avoid verbosity and forms. Just a sentence or two to explain what the class is (especially helpful if you couldn’t come up with a really good name). Maybe say what it’s used for. That’s usually about as much as someone needs to know. Refrain from a huge exposition on the overall design or the justification for the class. Save discussion of the class members for the member comments themselves. And if you can’t think of something meaningful to say, don’t say anything at all.
  • Don’t duplicate information in an Interface and a Class. If you have to pick one, document the interface. Focus on the interface for describing what something is or represents, and in the implementation, anything noteworthy about the implementation.
  • When declaring variables of collection types, if you say nothing else in the comment you should at least state the actual type of the elements of the collection.
  • Method javadocs are critical for the casual audience, but not because they will show up in the HTML documentation. Most IDEs will provide javadoc comments in a tooltip or property sheet, saving the user the step of clicking through to the declaration, or opening up the javadocs in a new window.
  • Make variable names as descriptive as possible. Not just your member or local variables. People tuning in to your code the first time will have a much easier time decrypting your for loops if instead of i or index you use names like row, month, or customerNumber.
  • Consider “Hungarian Notation” for variable names. Many developers find this convention ugly and onerous, but you can’t deny the value of immediately recognizing a variables scope without having to jump to its declaration. There’s a wide spectrum of adherence to this principle; from the old C++ practice of limiting the convention to member variables with a ‘_’ prefix on one hand, to an array of prefixes identifying the scope of every variable.

The point of this is not to enumerate a list of documentation standards for your programs, but to get you to think like an author and empathize with your audience. Use your own experience learning and debugging other people’s code to determine what your audience needs from your documentation. Give them whatever they need to keep them from changing the channel before your program finishes.

Tags: , ,

14 Responses to “Programmers as Channel Surfers”

  1. By Vaibhav on Oct 2, 2007

    I didn’t know this till some time ago myself. A lot of us think of Hungarian notation only as prefixing type information to the front of the variable, however that is technically Systems Hungarian and not the more useful Apps Hungarian (which involves prefixing functional information to the variable name). More on Wikipedia:
    http://en.wikipedia.org/wiki/Hungarian_notation

  2. By Bill Kayser on Oct 9, 2007

    Very interesting. I guess I’d forgotten that the term referred to a notation that had more to do with the type of the variable than it did the scope. I’m kind of embarrassed because that’s not at all what I had in mind. I don’t think in Java with modern IDE’s that there’s much benefit to encoding the type of a variable in the name. Encoding the scope, however, I find useful. A prefix that indicates a member variable, parameter, or static. There’s a common idiom for final statics using ALL_UPPERCASE which is useful.

    I’d really like to know what other opinions are on the modified version of Hungarian notation where you encode the scope. I always liked the convention from C++ of prefixing member variables with an underscore, but there doesn’t seem to be a lot of affection for that convention among Java developers.

  3. By Vaibhav on Oct 10, 2007

    Well I can mention my experiences as a .Net developer and the best practice that we have propagated in Nagarro mandates the use of _ prefix for private scoped variables at the class level.

    Personally, I feel that the IDE intellisense is better utilized because pressing _ immediately filters the available options to only your private variables, which is really useful.

    But yes, I used to understand Hungarian in terms of including type information to the variable, but that (as you said) is not needed anymore. Earlier it was for informational and guiding purpose to reduce chances of type mismatches.

    However, I really like the Apps Hungarian concept a lot and would love to integrate it more and more into coding practices.

  4. By Manas Fuloria on Oct 14, 2007

    Bill, I’m really enjoying this.

    Just FYI, since we worked together I’ve become a convert to the importance of usability. Everything we do as engineers is to enhance human experience - our own or that of others. (Even if you are designing a bridge - you don’t want your users to get wet, right?!) It takes a lot of introspection and self-criticism to make human factors truly influence your design, but the results can be delightful.

  5. By Vaibhav on Oct 15, 2007

    Another good use of comments is to send messages to the next developer who will inherit your code as to why you used a certain non-obvious way to implement things. I was reminded of this while I was reading a post by Phil Haack. The complete post is here:
    http://haacked.com/archive/2007/10/07/the-greatest-compliment-a-developer-can-receive.aspx

  6. By Bill Kayser on Oct 15, 2007

    Also reminds me of the two flavors of comments I see all the time in our legacy code:

    // HACK ALERT Really should be doing this thread safe…

    // FIXME Need to localize this…

    The first is like a pre-emptive strike described in that article, a little disclaimer added to soothe a guilty conscience.

    The second is practially a joke. I’m sure a lot of developers think they’ll go back after the release and fix all these, and maybe some do, but I see hundreds of these in code that hasn’t changed for years. It’s like the advice I give new homeowners lamenting the fixup jobs they inherit when they move in: If something looks like it needs a repair or paint job, leave it for two months. After that, there’s a good chance it won’t bother you anymore and you won’t need to fix it.

  7. By Vaibhav on Oct 15, 2007

    Right… in .Net (and I keep referring to that, because I have little Java experience)… I personally do and also encourage my team members to leave //TODO: comments.

    The Visual Studio IDE lists ALL TODOs in a Task List whenever code is compiled. This way, a simple review to check if there are any pending TODOs helps wrap ends up before code commit/release.

  8. By Bill Kayser on Oct 15, 2007

    That’s a good policy. Eclipse does the same thing. It’s interesting though, that at some point on the project I’m working on now, it just became noise. When the current team took over, we found that view was filled with thousands of markers, FIXME’s and TODO’s, nearly all completely pedantic. Their intentions were probably good. I think what happened was they started this practice before using IDE’s that could show them all in a single list view.

  9. By Vaibhav on Oct 16, 2007

    I agree… this doesn’t work at all if you let the markers gather around. There needs to be a very disciplined approach to take care of these markers on a couple of times a week basis, if not on a daily basis.

    If the list becomes too big, it is very easy to lose sight of that important // TODO:

    //TODO: Need to rename this variable…
    vs.
    //TODO: Implement the code to save the record

    In that sense, //TODO: comments are not all that different from normal comments. You need to know when to put which… :)

  10. By Ramesh on Oct 16, 2007

    For very important TODO comments like Vaibhav mentioned:
    //TODO: Implement the code to save the record

    I prefer to put exception so that this could be easily figured out by developer (or tester in case developer is not doing the basic testing :) ).

    e.g.
    throw new ApplicationException(”Save not implemented.”);

    I am not sure what is the best way of doing this. Any comments?

  11. By Bill Kayser on Oct 17, 2007

    That’s pretty definitive! But I like it. Even better is to write a unit test that calls the method. Then you don’t have to wait for a tester to trip over it, it shows up as a “to-do” every time you look at your unit test results, showing it as a failure. I usually throw UnsupportedOperationException().

  12. By Deepak Nohwal on Oct 17, 2007

    Throwing UnsupportedOperationException() is a pretty good idea that I follow in my code. However, one cannot always do that. For example, places like where you want to do some optimizations in the code but you cannot do due to lack of time.

    // TODO:: Use MDBs insteadof Threads here.

    Now, things like these are often put up as TODO comments in the code but they are not trivial enough to be done immediately or even in a code review. Not sure how we tackle this problem of these not-too-many TODOs. Thoughts?

  13. By Bill Kayser on Oct 18, 2007

    The way I deal with it is defining my own tags. In Eclipse you can define new tags to appear in your task list, with different priorities. So I typically use WHKTODO for my own list of things to follow-up on.

  14. By Amit Jain on Dec 16, 2007

    I like the unit test strategy for ‘ToDo’ things.
    We , generally, write unit test cases againt the functionalities which are yet to be implemented and these unit tests keep failing till we implement them.

    Infact, in our project, we often follow test driven methodology where we write test cases at the start and implement functionality to make the unit tests pass.

Post a Comment