Tips For Making Better Software

Writing code seems really easy from the outside looking in. You sit at a computer all day and get paid for it.

In a lot of minds, it’s about showing up. Sit in front of the computer and the code will flow. The longer you’re there, the more code you get. The more code the better.

Having more bags of cements doesn’t guarantee a better building. Having more salt doesn’t guarantee a better meal.

While it’s important to the final product, time spent writing code just an ingredient like any other.

The knowledge on effectively using it is critical to getting the best possible results.

This isn’t a step-by-step guide. More like a handy guide on easy ways to improve the quality of your code. If this were about cooking, it would be tips on getting flavor into chicken, fish and vegetables. Tips and tricks, not recipes.

Here we go!

1. CODE IS AN INGREDIENT; STORE IT PROPERLY

If your software has commented-out chunks of code, you’re storing it wrong.

The right way to store code is in version control software.

Version control allows you to modify code without losing its previous state. You can safely add new features, improve old portions or roll back to previous if you screw things up.

Version control enables multiple people to work on the same code without overwriting each other’s changes.

While it requires a little bit of overhead to have properly stored code, the benefits gained far outweigh adding yet another tool to your belt.

2. OVERCOMMUNICATE

Building software is a group activity. Even if you’re working alone, odds are you aren’t making the software for yourself only. Even if you are, you may not be the only one to ever work on it.

Communicate to your team mates, end users and your future self as clearly as possible and often.

In your version control system leave clear notes on what each commit is about. “bugfix: prevented negative quantities” as opposed to “patch”. “Made product search case-insensitive” not “enhancement”.

Make your code legible: better variable names, more descriptive blocks of code, better spacing. You can’t be too obvious. Save your complex expression to a variable that describes its intent. if( is_even_number )  is way more clear than if( n % 2 === 0 ) . Separating it out into two lines doubles what you need to read but makes each line many times easier to grasp at a glance. It’s more code but is way more obvious.

Don’t let people think too hard about what your code does. Even if it’s just you, don’t require yourself to understand densely packed logic.

If you’re on a team, even more important to make your code clear. Make the code disappear and let them read plain words to get the point of your code.

3. WRITE MODULAR CODE BECAUSE CHANGE IS COMING

I’ve never been involved in a project that didn’t undergo a decent amount of change before completion. Layouts change. User flow gets modified. Schemas get updated. Things get added. Things get removed.

If your code is hard to modify, the quality of your software is likely to be poor. Since you didn’t account for change, the inevitable modifications will either take too long to implement or will be held in place with dirty hacks, the programming equivalent of duct tape.

ALL WORK AND NO PLAY

A strategy that’s served me well is to use an event-driven system to keep components connected, but not explicitly.

In a modern music player, odds are pressing the play button doesn’t only start the music. It might put an indicator beside the track name in the listing, fade in the album art and display the track metadata on a side panel. In pseudocode:

function pressPlay(){

  startTrack();
  fadeinAlbumArt();
  displayTrackMetadata();
}

 

Seems fine so far, right?

We know change is inevitable, so it comes as no surprise to us that we’ve created a setting to disable displaying track meta globally. We opted to sometimes fade in ads before the album art and we’ve implemented analytics to better understand how or product is being used.

function pressPlay(){

  startTrack();

  if( adPlacementTime() ){
    showAd( fadeinAlbumArt );
  }

  if( userHasntDisabledTrackMetadataDisplay ){
    displayTrackMetadata();
  }

  doUserAnalytics();
}

 

The problem here is your play button now has a deep awareness of unrelated parts of your app. It must now be aware of way more than it needs to do its basic job: playing music.

If the analytics lead your team to remove the track metadata display feature because nobody uses it, your play button will now crash the app because it directly calls two functions (the check function to see of its disabled and the display itself) no longer exist.

Eventually you find all the references to the now-removed functions, clean up the code and ship.

Big problem. A vocal minority who happen to be the more profitable segment of your audience loved that feature. That 1% accounted for 20% of revenue and 65% of referrals to new users. We need that feature back ASAP!

If you didn’t properly store your code, that feature would need to be rebuilt. Except now it’s not as battle tested and is bound to have bugs due to the pressure to ship fast and the many parts of the system the feature touched.

If you had version control, the code might have been live 5 minutes after the decision to bring it back was made.

You know this code sucks so you’ve decided to redo it.

function pressPlay(){

  startTrack();
  app.event('track-started');
}

 

Your track metadata feature:

app.on('track-started', function(){

  if( userHasntDisabledTrackMetadataDisplay ) displayTrackMetadata();
});

 

If you ever need to tie a new feature into the playing of a track, you can listen in on track-start event.

Code is now be grouped by function. Removing a feature is straightforward because everything to do with it is in one place. Need to extend an existing feature? New event.

Your code is just another ingredient in the creation of software. Don’t make it any harder to manage than it needs to be. Store it in version control, keep its intent clear and make sure it’s really easy to modify.