Refactoring Code Comments Can Increase Maintainability

The assertion of this post is that code comments are a smell.  Creating obvious, readable code is more maintainable that unreadable code that is heavily commented.

Matt Hinze is teaching Agile Boot Camp, part 1 this week, and one of his lessons is about code readability.  He spoke about code comments being a smell.  When something smells, it doesn’t guarantee that it is rotten, but it does create the need to examine more closely to see if any bacteria is beginning to invade the codebase.  In this case, code comments may be a smell or harbinger of maintainability problem.

Let’s get the first straw-man out of the way.  Taking an existing codebase and merely deleting all code comments does not make a system more maintainable.   I’m not suggesting you do this for your existing system.  This course of action would be foolish.

When developing code, sometime one finds that a section is less than obvious.  When an ambiguous section of code is discovered, the wrong course of action is to add a comment describing what it does.  The better option is the refactor the code to make it more obvious. 

Problems with code comments:

  • Code comments are not compiled
  • Code comments are not tested
  • Code comments are not verified frequently
  • Out-of-date comments have negative consequences
  • They are likely to remain when the code changes

How, then, do we communicate to the maintainer the purpose of code that is less than obvious?  Consider the following example that takes some ambiguous code with comments and refactors away the comments.

public class SpeakerClickReport
{
    public int Total { get; set; }
    public int IndTotal { get; set; }

    // get ration of individual clicks to total clicks for a given speaker.
    public int GetRatio()
    {
        //Total clicks for all speakers equaling 0
        if (Total == 0) return 0;
        //take clicks for this speaker and get the percentage compared to Total for all speakers
        return (int) (100.0*IndTotal/Total);
    }
}

Notice that the comments help to communicate the intent of the code, although it isn’t clear what this code is doing.  When this code changes, these comments will be out-of-date.  Let’s consider a refactored example and compare the readability.

public class SpeakerClickReport
{
    public int TotalOfAllSpeakerClicks { get; set; }
    public int NumberOfIndividualClicks { get; set; }

    public int GetPercentageOfTotalForIndividualSpeaker()
    {
        if (TotalOfAllSpeakerClicks == 0)
        {
            return 0;
        }

        var ratioOfTotal = (double)NumberOfIndividualClicks / TotalOfAllSpeakerClicks;
        var percentFormOfRatio = (int) Math.Round(100 * ratioOfTotal);
        return percentFormOfRatio;
    }
}

Notice that none of the code comments are left.  In their place are:

  • More obvious variable names
  • Whitespace used to divide sections
  • More intermediate variables to describe single-step decisions and calculations
  • Public API more obvious
  • Obtaining return value before actually returning it

The second example is more maintainable than the first because as code is refactored, the comments are actually embedded in the code, not ignored by the compiler.  As class members are renamed and moved around, the contextual information will remain and be refined.  The risk of the commenting information being out-of-date and useless is mitigated.  In short, embedding more information into the source code creates more maintainable code.

Code will be read many, many more times than it is written.

Hiring ASP.NET Developer Immediately -apply within

I am hiring a developer immediately on a contract basis.  I’m considering this contract-to-hire.  I would need this person to start within 10 days if I can, so apply immediately.  This is for on-site work in Austin, TX starting in January as soon as possible.

This developer will needs the following skills:

  • ASP.NET 3.5/C#
  • CSS
  • JQuery 1.2
  • Basic graphics creation/slicing

This person will work in the UI of enterprise application.  The UI uses ASP.NET, and it also uses JQuery.  UI development skills are critical.

Other necessary skills include:

  • Interpersonal skills
  • Requires little supervision
  • Works well with others
  • Understands process and business constraints

The environment is similar to a war-room.  Office and cubicles are limited in favor of working collaboratively.

If you are interested in this position, please use the contact feature on this blog or email jobs [a t] headspring systems [d ot] com

Hardcoding Considered Harmful – or is it?

  I had an interested conversation with a colleague recently, and the topic was hard-coding.  A definition from wikipedia follows:

Hard coding (also, hard-coding or hardcoding) refers to the software development practice of embedding input or configuration data directly into the source code of a program or other executable object, or fixed formatting of the data, instead of obtaining that data from external sources or generating data or formatting in the program itself with the given input.

Hard-coding has caused quite a bit of pain for folks trying to maintain systems.  One of the issues is that changing the configuration information requires a code change, and then a redeployment of the system.  Another issue is if the configuration is hard-coded into multiple places within the system.  Then the programmer must remember all the places the hard-coding exists.  Compounded by a situation where the system is hard to deploy, this can lead to a large maintenance problem.

To get around hard-coding configuration information into the system, we often move configuration to an external source, which is a text file or database table.  This allows us to change the configuration without rebuilding the system.  The caveat is that it allows us to believe that we have removed the configuration from the system, but we must be wary of behavior that depends on specific configuration values to exists.  I’ve mentioned the location of configuration in an earlier blogpost, and I’ve also mentioned fear of deployments.

Oren Eini boldly makes the assertion that a system is simpler to maintain when configuration is hard-coded in one place within the system.  Coupled with an automated testing and deployment process, changing configuration can be just as simple and predictable as possible.  Oren asserts that hard-coding as much as possible enhances maintainability.  He then defends his position with an example in a subsequent post

I agree with Oren.  The first draft of some functionality should hard-code everything.  Then subsequent revisions will cause some information to be factored out into mediums that can be maintained while suppporting all the requirements in scope.  The requirement cause us to make decisions about what information to hard-code and which information to soft-code.

Hard-coding as harmful or not is not an absolute.  When you dig deep into the requirements for a system, you will uncover specific information that doesn’t work as a part of the codebase.  That information has to be elsewhere in a softer configuration medium.

Conclusion:  hard-code it until hard-coding it doesn’t work anymore. 

Beware of Fear-Driven Architecture (do you fear deployments?)

At Headspring, we joke about PDD, or pain-driven development.  We consider PDD to be a good thing.  If there is pain, we do a root-cause analysis and solve the pain.  If there is no pain, we call “yagni” and move on.  If we are in a design discussion and we realize that we are proposing a solution without pain existing, we stop and move on.

Pain can be a good indicator of a specific problem that needs to be solved.  Beware of fear, however.  Often, fear of something can color our technical decisions and cause us to suboptimize one part of our system or process.

Let’s take deployments, for instance.  If our deployment is an all-weekend affair, then we will start to fear it.  If a deployment takes several people yet always goes wrong, we will dread the deployment date.  This is a very real scenario.  Without an automated deployment, this is likely to happen.  There is a deployment document with a list of steps.  Even so, this list of steps doesn’t cover all the possible failure scenarios.  Worse yet, in this environment, the last deployment is probably more than a month back in history.  This makes it hard to remember the specific problems encountered the last time.

With this dysfunctional deployment environment, the team is literally afraid of deploying the software.  They will do anything to avoid one, include making design decisions base on it.  Business rules?  Hello rules engine with rules defined in XML files.  Configuration?  Hello complex config files and “magic records” in database tables.  With this fear, it leads the team to put anything that “could” change somewhere else besides in compiled code. 

Next, the problem compounds.  Because of so many external dependencies, the production deployment becomes a two-step process:  Get the system out there.  Then make sure all the external config files and “magic records” are just right.  However, because it’s been 2 months since the last deployment, those files have been changed.  The configuration records in the database have changed.  They were not merged back to the development environment, however.  As time goes one, there are actually two code-bases that have to be kept in sync:  1.  The code.  2.  The configuration (which has more lines of code that the system itself (maybe)).

Perhaps I’ve used a little hyperbole, but I’ve seen scenarios similar to this (and have experience one that will never leave my memory).  The team lets fear drive design decisions.

Solution:  Take the fear, and identify the pain that we are afraid of.  Then take swift action and resolve the pain.  Resolving the pain of deployments would lead us to automate the process, do it more frequently, and iron out any kinks.

Without fear driving our design decisions, we can make better choices given the system’s current requirements.

Separating configuration from data lowers total cost of ownership

All software systems require configuration.  Some require much more configuration that others.  Configuration can be an overloaded term, but I’m speaking about the information necessary for the software to function correctly. 

Without this information, the software is unstable and will not work.  For most business systems, a common configuration item is the database connection string.  Without this configuration item, the system cannot function.  Other common configurations are the list of valid states or provinces for addresses.  Often the local state is defaulted to the top as a shortcut for the users.  Another example is a list of statuses, such as Pending, Active, Complete.  As usual, requirements should drive the approach taken.

Let’s talk about the Status list first.  Where should this configuration be managed?  The simplest approach is to maintain the status list in the software itself.  The tests around the software build will verify this configuration, and if the software has logic built around these values, the compiler verifies the important values are present.  If the Status list changes less than once per week, this is a fine approach since a system under enhancement might have weekly deployments.  (Note:  Using agile development, systems are easy to deploy, and our current projects get deployed many times per day to multiple environments.  Without an automated deployment, deployments are much more costly).

Let’s consider a list of states.  For a sales system, we might have 5 states if process orders for these 5 regions.  Our state list would have those 5 states with the local state defaulted to the top since it is the most common.  Again, we start with storing this configuration with the codebase, especially since the system is unstable without the local state.  If the list of states changes more frequently than weekly, we might consider wanting to change the list without requiring a deployment.  This would lead us to store the configuration separate from the codebase.  Options include putting the configuration in a file or the database.  The benefit of the configuration residing in a file allows the configuration to change while the system is running.  The system will have to be able to detect the change and reload the configuration, however.

Let’s take the requirements a bit further.  Let’s say we want a screen in the system to let authorized users add a state to the state list at any time.  They can also remove a state.  We have to analyze if there is a gold list (i.e. a list of states that cannot be removed because there are business rules around those specific values).  We might be tempted to put the state list in the database, but mixing this configuration with data is risky.  First, we need a mechanism to validate the configuration.  We need to have the application check the database table and ensure the “required” values are there.  Values added in one installation might somehow need to be synced up if a new value is considered to be part of the “gold” list.  Putting the list in data confuses data and configuration, and we have shyed away from it since the system is easier to implement and maintain if a new installation starts out with an empty database and functions properly.  Then implementation tasks can make the system usable for the target environment.

Ultimately, the requirements drive the approach to configuration.  Depending on the frequency of change, the number of unremoveable items, and other factors, you will decide where to store the configuration in a manner that minimizes total cost of ownership.

My recommended progressions of configuration locations are as follows.  Specific requirements should be the driving factor that cause you to move configuration from one medium to the next costly alternative.

  1. In the code
  2. In a file
  3. In a database
  4. Some other system-specific external configuration store

There is no cut-and-dried answer for EVERY project, but the requirements should be what drives the decision.  Along those lines, no one location is appropriate for EVERY piece of configuration.  Depending on the nature of the configuration, it will be appropriate to choose a different storage medium.

When designing a software masterpiece, make the first release in pencil

Our chief architect, Kevin Hurwitz, has a very disciplined way of approaching software.  It is inherently incremental.  It is inherently vertical.  He communicates the approach by citing recent discoveries about da Vinci’s techniques when painting the Mona Lisa.  According to various sources, da Vinci painted this timeless masterpiece first by drawing a simple sketch, then by layering on some paint, then some more, and finally by fine-tuning and tweaking the hands, face and lips with very tiny brush strokes.

Many of us (myself included) have a tendency to approach software very differently.  We like to get it perfect the first time.  We like to give the best user experience the first time.  We want to ensure we capture 100% of the necessary fields the first time.  In my experience, however, this approach is counterproductive, and the business can realize more value early by doing a sketch of the system first, and then layering on enhancements.

Gmail is a perfect example of this with its “Save to Draft” feature.  Early versions of Gmail were pretty crude, and the threaded conversations were the attention-getter.  Many users lost email text when the javascript malfunctioned and threw away the email: or perhaps their browser locked up.   Gmail added the “Save to Draft” feature and made the UX better. 

The point of this whole post is to deliver working software as quickly as possible.  When a discussion about the nature of a single field threatens to delay the delivery of a screen, deliver the screen without the field in question until such time the customer can work out what is needed with the special field.  Guessing at it up-front will ensure we get it wrong, and it will become clear once the rest of the screen is there.

When designing a great software feature, make the first version in pencil

Agile Boot Camp now with a Part 1/2 (Sign up now)

Our Agile Boot Camp developer training series has been so successful that we are adding a “Part 1”.  Up until now we did not have an offering for developers without familiarity with the topics used in the Agile Boot Camp.  We’ve added a Part 1 geared toward developers working on an agile team.  Part 2 is more geared toward leading an agile team (Senior developers, team leads, architects, etc).  I personally craft the overall curriculum for the Agile Boot Camp, and it includes the same techniques that we (Headspring) use on all of our consulting projects; therefore, this course has the unique advantage of having an evolving and real-world curriculum.

The next courses are on the calendar:

Agile Boot Camp: Part 1:  Jan 14-16, 2009

Agile Boot Camp: Part 2:  Jan 28-30, 2009

Starting with these classes, we are introducing ASP.NET MVC as the UI toolkit used throughout the course as we explore developer concepts in a codebase that appropriately illustrated the agile concepts necessary to keep the project performing optimally.

Discounts:  If you heard about this training through my blog, I’d like to give you a discount.  Please email me at jpalermo [AT] headspringsystems.com for a special discount code.

Party with Palermo: Alt.Net/MVP Summit Edition (save the date)

The next Party with Palermo is on the calendar!  This event will be sandwiched between the Alt.Net Seattle 2009 conference and Microsoft’s MVP Summit.  If you are planning on attending either conference, or if you will be in the area on March 1, 2009, plan on stopping by for some appetizers, beer, and a good time with other software folks.  The party will be at 7PM.

Party with Palermo has become a very popular event, and we have grown so much that it is prudent to RSVP so that we know the necessary capacity for the venue.  As some of you know, the last Party with Palermo, in Los Angeles for the PDC, had 380 people RSVPed.  Over 500 people actually showed up, and the bar was overwhelmed.  We’re taking measures to get a better RSVP count so that we can appropriately plan.  One of these measures is a professional contact list and newsletter.  If you would like to receive information about Party with Palermo as soon as it is available, please subscribe to the Party with Palermo newsletter. 

The event website will go live two weeks.  Until then, subscribe to the newsletter, book your travel plans, and tell your friends!  Also, if you have been to a previous Party with Palermo, please leave a comment with what you liked most about the event.