When Code Duplication is not Code Duplication

Duplicating code is a bad thing. Any engineer worth his salt knows that the more you repeat yourself, the more difficult it will be to maintain your code. We’ve enshrined this in a well-known principle called the DRY principle, where DRY is an acronym standing for Don’t Repeat Yourself. So code duplication should be avoided at all costs. Right?

At work I recently came across an interesting case of code duplication that merits more thought, and shows how there is some subtlety needed in application of every coding guideline, even the bedrock ones.

Consider the following CSS, which is a simplified version of a common scenario.

.title {
  color: #111111;
.text-color-gray-1 {
  color: #111111;

This looks like code duplication, right? If both classes are applying the same color, then they do the same thing. If the do the same thing, then they should BE the same thing, right?

But CSS and markup in general presents an interesting case. Are these rules really doing the same thing? Are they both responsible for making the text gray? No.

The function of these two rules is different, even though the effect is the same. The first rule styles titles on the website, while the second rule styles any arbitrary div. The first rule is a generalized style, while the second rule is a special case override. The two rules do fundamentally different things.

Imagine a case where we optimized those two classes by removing the title class and just using the latter class. Then the designer changes the title color to dark blue. To change the title color, the developer now has to replace each occurrence of .text-color-gray-1 where it styles a title. So, by optimizing two things with different purposes, the developer has actually made more work.

It’s important to recognize in this case that code duplication is not always code duplication. Just because these two CSS classes are applying the same color doesn’t mean that they are doing the same thing. In this case, the CSS classes are more like variables than methods. They hold the same value, but that is just a coincidence.

What looks like code duplication is not actually code duplication.

But… what is the correct thing?

There is no right answer here. It’s a complex problem. You could solve it in lots of different ways, and there are probably three or four different approaches that are equally valid, in the sense that they result in the same amount of maintenance.

The important thing is not to insist that there is one right way to solve this problem, but to recognize that blithely applying the DRY principle here may not be the path to less maintenance.

15. March 2017 by evan
Categories: Software Design | Tags: , , , , , , , | Leave a comment

Remaking Cool Music, Rebooting a Blog

I spent the weekend remaking the theme from the Netflix show The White Rabbit Project. It’s a pretty rocking little theme. I really admire any composer who can write a good piece of music that lasts only thirty seconds, and the composer of the original theme certainly succeeded in that respect.

In that blog post, I included the drum presets, synth presets, and audio files used in the remake.

So why didn’t I post that here? In short, I am trying to revive my defunct blog. I was pretty hardcore about blogging for about six years, from around 2007 to 2013, but since then I have let it slip. Social media seemed to take over and make blogs irrelevant.

Or at least it felt like my efforts were wasted three years ago.

Now I feel like I have more to say about computer music, and I feel like mass social media, where everyone is lumped together into one big mass, aka Twitter and Facebook, is dying. I feel like the flaws in it are apparent.

So maybe blogs are both the past and the future? Or maybe the future is something we can’t see yet? Either way, I am rebooting computermusicblog.com.

18. December 2016 by evan
Categories: Uncategorized | Tags: , , , | Leave a comment

I love Pandora, but where is the discovery?

I have been a loyal Pandora subscriber since the month they started offering subscriptions. I love the service. I will continue subscribing forever, even if it’s only to keep my perfectly tuned Christmas music station.

But Pandora is not serving its audience very well, and that annoys me.

I probably listen to Pandora over five hours a day on each work day, and probably an hour or two on days off. When I tell someone I use Pandora, they inevitably ask me, “why don’t you just use Spotify?” More and more, I feel like they have a point.

In the past, I have preferred Pandora because it enabled discovery. It allowed me to create stations that would play music that I liked, but I had never heard. As a person who has spent decades of his life listening to and studying music, one of the main things I like about a piece of music is that I’ve never heard it before. In the past two years or so, I feel like this aspect of Pandora has dwindled or disappeared.

More and more, I feel like my Pandora stations primarily play the tracks that I have already voted for. Admittedly, some of my stations have been around for over a decade, so I have voted for a lot of tracks. When I vote for a track, however, it isn’t an indication that I want to hear that track every time I turn on that station. A vote is an indication that I want to hear tracks that are similar to that track.

But this is just too rare lately on Pandora. I hear the same Ellie Goulding tracks that I voted for last year. I hear the same Glitch Mob tracks that I’ve heard for the past six years. I still like that music, but I would prefer to hear something else. Why not play another track off the album that I voted for? Why play the same single track over and over?

“But why not click the ‘Add Variety’ button?” The ‘Add Variety’ button adds a new seed to that station. I don’t want to change the type of music played by the station, I simply want it to play OTHER music that falls within my already-indicated preferences.

What really irritates me, is that this doesn’t seem like a hard feature to implement. Why can’t a user tune the amount of new music they hear? Why can’t we have a slider that we can control with our mood? If the slider is set to 1.0, then we are in full discovery mode. Every track played will be one that we haven’t voted on. If the slider is set to 0.0, then every track played will be one that we HAVE voted on. In this way, Pandora could act like Spotify for users who like Spotify, and for people like me, it can act as the best shuffle on the planet.

As a programmer who has worked with large datasets, search tools like ElasticSearch, and written lots of web applications, I know that this isn’t a difficult change. It might require one schema change, and less than ten lines of new code. But it should be implementable and testable in under a week. Design might take longer, but here, I will design it for you.

pandora discovery slider

pandora discovery slider

And seriously, Pandora, I will implement this for you if you are that desperate. My current employer will loan me out, and even without knowing your code base, I could get this done in a month.

So come on, Pandora. Serve your audience. Stop making me explain why I prefer Pandora over Spotify. Add a discovery slider. Today.

11. December 2016 by evan
Categories: Criticism | Tags: , , , , | Leave a comment

How to Share an Audio File on Android from Unity/C#

Rendering audio to a file is an important feature of an audio synthesizer, but if the user can’t share the file, then it’s not very useful. In my second pass on my synthesizers, I’m adding the ability to share rendered audio files using email or text message.

The code for sharing audio files is tricky. You have to tell Unity to generate some Java code that launches something called an Intent. So this code basically instantiates the Java classes for the Intent and the File, then starts the activity for the intent.

Figuring out the code is tough, but you also need to change a setting in your player settings. Specifically, I couldn’t get this code to work without Write Access: External (SDCard) enabled in Player Settings. Even if I am writing to internal storage only, I need to tell Unity to request external write access. I’m assuming that the extra privileges are needed for sharing the file.

Here’s the code.

public static void ShareAndroid(string path)
    // create the Android/Java Intent objects
    AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
    AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");

    // set properties of the intent
    intentObject.Call("setAction", intentClass.GetStatic("ACTION_SEND"));
    intentObject.Call("setType", "*/*");

    //instantiate the class Uri
    AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri");

    // log the attach path
    Debug.Log("Attempting to attach file://" + path);

    // check if the file exists
    AndroidJavaClass fileClass = new AndroidJavaClass("java.io.File");
    AndroidJavaObject fileObject = new AndroidJavaObject("java.io.File", path);// Set Image Path Here
    //instantiate the object Uri with the parse of the url's file
    AndroidJavaObject uriObject = uriClass.CallStatic("parse", "file://" + path);
    // call the exists method on the File object
    bool fileExist = fileObject.Call("exists");
    Debug.Log("File exists: " + fileExist);

    // attach the Uri instance to the intent
    intentObject.Call("putExtra", intentClass.GetStatic("EXTRA_STREAM"), uriObject);

    // instantiate the current activity    
    AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = unity.GetStatic("currentActivity");

    // start the new intent - for this to work, you must have Write Access: External (SDCard) enabled in Player Settings!
    currentActivity.Call("startActivity", intentObject);

07. October 2016 by evan
Categories: Software | Leave a comment

Recording In-Game Audio in Unity

Recently I began doing a second pass on my synthesizers in the Google Play store. I think the core of each of those synths is pretty solid, but they are still missing some key features. For example, if you want to record a performance, you must record the output of the headphone jack.

So I just finished writing a class that renders a Unity audio stream to a wave file, and I wanted to share it here.

The class is called AudioRenderer. It’s a MonoBehaviour that uses the OnAudioFilterRead method to write chunks of data to a stream. When the performance ends, the Save method is used to save to a canonical wav file.

The full AudioRenderer class is pasted here.

using UnityEngine;
using System;
using System.IO;

public class AudioRenderer : MonoBehaviour
    #region Fields, Properties, and Inner Classes
    // constants for the wave file header
    private const int HEADER_SIZE = 44;
    private const short BITS_PER_SAMPLE = 16;
    private const int SAMPLE_RATE = 44100;

    // the number of audio channels in the output file
    private int channels = 2;

    // the audio stream instance
    private MemoryStream outputStream;
    private BinaryWriter outputWriter;

    // should this object be rendering to the output stream?
    public bool Rendering = false;

    /// The status of a render
    public enum Status

    /// The result of a render.
    public class Result
        public Status State;
        public string Message;

        public Result(Status newState = Status.UNKNOWN, string newMessage = "")
            this.State = newState;
            this.Message = newMessage;

    public AudioRenderer()

    // reset the renderer
    public void Clear()
        this.outputStream = new MemoryStream();
        this.outputWriter = new BinaryWriter(outputStream);

    /// Write a chunk of data to the output stream.
    public void Write(float[] audioData)
        // Convert numeric audio data to bytes
        for (int i = 0; i < audioData.Length; i++)
            // write the short to the stream
            this.outputWriter.Write((short)(audioData[i] * (float)Int16.MaxValue));

    // write the incoming audio to the output string
    void OnAudioFilterRead(float[] data, int channels)
        if( this.Rendering )
            // store the number of channels we are rendering
            this.channels = channels;

            // store the data stream

    #region File I/O
    public AudioRenderer.Result Save(string filename)
        Result result = new AudioRenderer.Result();

        if (outputStream.Length > 0)
            // add a header to the file so we can send it to the SoundPlayer

            // if a filename was passed in
            if (filename.Length > 0)
                // Save to a file. Print a warning if overwriting a file.
                if (File.Exists(filename))
                    Debug.LogWarning("Overwriting " + filename + "...");

                // reset the stream pointer to the beginning of the stream
                outputStream.Position = 0;

                // write the stream to a file
                FileStream fs = File.OpenWrite(filename);



                // for debugging only
                Debug.Log("Finished saving to " + filename + ".");

            result.State = Status.SUCCESS;
            Debug.LogWarning("There is no audio data to save!");

            result.State = Status.FAIL;
            result.Message = "There is no audio data to save!";

        return result;

    /// This generates a simple header for a canonical wave file, 
    /// which is the simplest practical audio file format. It
    /// writes the header and the audio file to a new stream, then
    /// moves the reference to that stream.
    /// See this page for details on canonical wave files: 
    /// http://www.lightlink.com/tjweber/StripWav/Canon.html
    private void AddHeader()
        // reset the output stream
        outputStream.Position = 0;

        // calculate the number of samples in the data chunk
        long numberOfSamples = outputStream.Length / (BITS_PER_SAMPLE / 8);

        // create a new MemoryStream that will have both the audio data AND the header
        MemoryStream newOutputStream = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(newOutputStream);

        writer.Write(0x46464952); // "RIFF" in ASCII

        // write the number of bytes in the entire file
        writer.Write((int)(HEADER_SIZE + (numberOfSamples * BITS_PER_SAMPLE * channels / 8)) - 8);

        writer.Write(0x45564157); // "WAVE" in ASCII
        writer.Write(0x20746d66); // "fmt " in ASCII

        // write the format tag. 1 = PCM

        // write the number of channels.

        // write the sample rate. 44100 in this case. The number of audio samples per second

        writer.Write(SAMPLE_RATE * channels * (BITS_PER_SAMPLE / 8));
        writer.Write((short)(channels * (BITS_PER_SAMPLE / 8)));

        // 16 bits per sample

        // "data" in ASCII. Start the data chunk.

        // write the number of bytes in the data portion
        writer.Write((int)(numberOfSamples * BITS_PER_SAMPLE * channels / 8));

        // copy over the actual audio data

        // move the reference to the new stream
        this.outputStream = newOutputStream;

As written it will only work on 16bit/44kHz audio streams, but it should be easily adaptable.

07. October 2016 by evan
Categories: Software | Tags: , , , , , , , | Leave a comment

Erratum, an Album Made Entirely with Custom Noise Apps

Erratum is an album that has been in gestation for over a year, and even as I release it into the wild I am refining my ideas about it, and apps, and the place of apps in music-making.

Erratum noise music album cover

Every track on the album was made using freely available sound mangling apps of my own creation. This intersects with my current philosophies about music and music-making in a few ways.

First, by making all the apps publicly available, I’m basically open-sourcing the album. Okay, the apps aren’t open source (yet), but other musicians can now very easily make very similar music. I think this is a good thing. I hope people find my apps useful. But this is a significant change from my thinking of just a few years ago, which was dominated by a slightly-more-insular academic perspective. The academic perspective says something like “I put in a lot of working making the software, so why should I let just anyone use it, or copy my algorithms.” This is an attitude displayed often by the old-guard type of guys I learned from, and in my previous art albums like Disconnected, I took the same stance. With the continuing dominance of social media over good-old-fashioned-blogs, I’m starting to think that sharing is more important than building up my own ivory tower though, and I tried to do that with this album.

Second, this album is full of short pieces. I’m starting to come around to the idea reflected in Cage’s Sonatas and Interludes, which is that if you’re going to write weird music, it’s better to write many short pieces or movements than to write something monolithic. So each of the pieces on this album are short and unique. The album is held together only by the thread of the mobile apps used to make them.

Finally, this album reflects the increasing pleasure I get from listing to music that is very close to noise. Some listeners might call some of this music noise. One of the apps I used to create this album, Radio Synthesizer simply adds radio-like noise to an audio file in greater or lesser proportions. When I had my first child I remember putting her to sleep with white noise, and for awhile, white noise was 100% effective at putting her to sleep. I think that made me more appreciative of all the different ways that noise can be generated. This album reflects a lot of different ways of getting to and from a noise-like state.

Stream Erratum from evanxmerz.bandcamp.com or check out the apps I used to make it on Google Play.

28. June 2016 by evan
Categories: Music, Software | Tags: , , , , , , , , , , , , , , | Leave a comment

Granular Synthesis for Android Phones

Granular is a granular synthesizer for Android devices. Play it by dragging your fingers around the waveform for the source audio file. You can upload your own audio files, or just play with the sounds that are distributed with the app.

The horizontal position on the waveform controls the location from which grains will be pulled. The vertical position controls the grain size. The leftmost slider controls the amount of frequency modulation applied to the grains. The middle slider controls the time interval between grains. The rightmost slider controls randomness.

Download Granular from the Google Play Store and start making grainy soundscapes on your phone.

20. June 2016 by evan
Categories: Software | Tags: , , , , , , , , , , , , | Leave a comment

The Simplest Unity Bundling Example I Could Make

Asset bundles in Unity can be tricky. I’ve spent a lot of time at work developing a pretty slick bundling system. The system pulls the latest from our git repo, then uses manifests to pull in new procedural assets, then generates all the bundles for each level, then uploads them into versioned folders on Amazon S3.

Most big projects will need something like this.

But it’s probably best to start with something simpler. The system I’ve built for work is probably 500 – 1000 lines of code with everything included. This weekend I wanted to find the least amount of code with which I could make a working bundles system.

This system has no extra features. It doesn’t support simulation mode. It doesn’t support procedural assets. It doesn’t support multiple simultaneous downloads. It doesn’t support viewing download progress. But it does work.

Here’s how to get Unity asset bundles working in under 200 lines of code.

Download the AssetBundleManager from the Asset Store

You don’t need the examples. You’re really only using this for the UI features added to the Editor, but some of the included classes in that package are also a good starting point.

Assign assets to bundles

When you select an asset, you should see a drop down all the way at the very bottom of the inspector. Use that dropdown to create a new asset bundle, then add your assets to it.

Create editor script for clearing bundle cache

When you are testing bundles, you will need an extra menu item to delete your local cache. Make an Editor folder somewhere and drop this script in it.

using UnityEngine;
using UnityEditor;

public class BundleOptions
    /// Delete all cached bundles. This is necessary for testing.
    [MenuItem("Assets/AssetBundles/Clear Bundle Cache")]
    static void LogSelectedTransformName()
        if( Caching.CleanCache() )
            Debug.Log("All asset bundles deleted from cache!");
            Debug.LogWarning("Unable to delete cached bundles! Are any bundles in use?");

You will want to click Assets > AssetBundles > Clear Bundle Cache between each generation of bundles to make sure that you are using the latest version in editor.

Create a BundleManager class

Your BundleManager class will download bundles and allow the program to access asset bundles. If you expand this example, then this will be the center of your work.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class BundleManager : MonoBehaviour
    // the web server where your bundles are stored - you can test this locally using file://c:/path-to-bundles/etc
    private static string baseBundleUrl = "file://c:/example/Unity/MyGame/AssetBundles";
    private static string baseBundleUrl = "http://www.example.com/MyGame/AssetBundles";

    // this dictionary will store references to each downloaded asset bundle
    private static Dictionary bundles;

    /// Get a reference to an AssetBundle instance that has already been downloaded.
    /// This should be used when you want to load an asset from a bundle.
    /// the name of the bundle to get
    /// a reference to an AssetBundle or null if that bundle has not yet been downloaded or cached
    public static AssetBundle GetBundle(string name)
        if( bundles != null && bundles.ContainsKey(name) )
            return bundles[name];
        return null;

    /// Very simple method for downloading a single bundle.
    /// Extensions to this method may include a progress monitor and a callback for when the download is complete.
    /// the name of the bundle you want to download
    /// an IEnumerator to be run as a Coroutine
    public static IEnumerator DownloadBundle(string bundleName, System.Action downloadCallback = null)
        Debug.Log("Attempting to load bundle " + bundleName + "...");

        WWW www = WWW.LoadFromCacheOrDownload(getFullBundleUrl(bundleName), 1);

        yield return www;

        // if there was a download error, then log it
        if( !string.IsNullOrEmpty(www.error) )
            Debug.LogError("Error while downloading bundle " + bundleName + ": " + www.error);
        else // if there was no download error
            // try to get the downloaded bundle
            AssetBundle newBundle = www.assetBundle;

            // if the bundle is null, then log an error
            if( newBundle == null )
                Debug.LogError("Unable to save bundle " + bundleName + ": Bundle is null!");
            else // if a valid bundle was downloaded
                if (bundles == null)
                    bundles = new Dictionary();

                // store a reference to that bundle in the dictionary
                bundles[bundleName] = newBundle;

                Debug.Log("Successfully loaded " + bundleName + ".");

        // if there is a downloadCallback, then call it
        if( downloadCallback != null )

    /// Return a string representation of the platform that will go into the bundle path.
    private static string getBundlePlatform()
        if (Application.platform == RuntimePlatform.Android)
            return "Android";
        else if( Application.platform == RuntimePlatform.WindowsEditor )
            return "Windows";

        // maybe this is some strange version of Android? Need this for Kindle.
        return "Android";

        // do not support other platforms
        //throw new System.Exception("This platform is not supported!");

    private static string getFullBundleUrl(string bundleName)
        return baseBundleUrl + "/" + getBundlePlatform() + "/" + bundleName;

    // Use this to initialize the bundles dictionary
    void Start ()
        if (bundles == null)
            bundles = new Dictionary();


Modify that script by replacing baseBundleUrl with the place where your bundles are stored locally for development and remotely for production.

You will also need to hook this script into the program somehow. You can attach it to a GameObject if you like, but that isn’t strictly necessary. All you really need to do is start a coroutine to run the DownloadBundle method, then call GetBundle to get the download. Then just call the LoadAsset method on the asset you want to instantiate.

Generate bundles

When you click Assets > AssetBundles > Build AssetBundles, it will generate bundles for whatever platform is selected. You will need to generate bundles for your development machine and for your target platform. Make sure to modify the getBundlePlatform method to support your platform.

And…. ?

And that’s it. Asset bundles are not really that complex when you boil them down. For my music apps, I just want them to store a few extra sound files that I don’t want to distribute with the executable. So a system like this works fine. I just start the download when the app starts.

Of course, for larger projects you will need many more features. Versioning bundles is very important for the development and build processes. Also you will want to show a progress bar on the screen. And you will want to load entire levels into bundles, which is a little more tricky. But hopefully this will get you started on the right track.

06. June 2016 by evan
Categories: Software | Tags: , , , , , , , , , | Leave a comment

Why I Created QuizMana.com

When I was teaching at UCSC and SJSU, I taught very large courses, often consisting of over 200 students. Courses that size create lots of infrastructural problems. Communication is a huge problem, but that’s mostly taken care of by Canvas or Blackboard. The bigger problem for me was assessments.

I think that even well-written multiple choice quizzes are not great assessments. In multiple choice quizzes, students always have the answer presented to them. Even very difficult multiple choice quizzes never ask students to explain their reasoning. They never force students to come up with a concept from memory. They present students with the false premise that knowledge is fixed, and is simply a matter of choosing from what already exists.

So I always wanted to use other types of questions, and I did. Or at least I tried to. To incorporate even one short answer question meant hours of grading. I once did a single essay assignment for a large class, and probably spent over forty hours grading essays.

I needed a grading tool that could quickly save me time, while allowing me to diversify the types of assessments I could use on a week-to-week basis. For the past three months I’ve been building a website that automatically grades short answer, essay, and multiple choice questions. I call it QuizMana.com, and it’s accepting applicants for the closed beta right now.

The hook of the website is automatic grading, but the purpose of it is to save teachers as much time as possible. So the grader gives a score for every question, but the site then points the teacher to all the “low confidence” scores. These are the scores where the grader didn’t have enough information to be fully confident it gave an accurate score. The teacher can then grade the low confidence responses on a single page, and then they are done!

So the grader is part of a larger process that means that teachers only grade the work that actually needs their attention.

I think this can be a great tool, and I think it will save teachers a lot of time. If you’re teaching a large class this semester, then give yourself a new tool, and try QuizMana.

25. January 2016 by evan
Categories: Software | Tags: , , , , | Leave a comment

How Can Comments be Controversial?

Comments add information to your code. They don’t impact the execution of that code. So how can they be bad? I believe that more commenting is better, and that comments are a vital tool in maintaining an agile codebase, but I’ve met many experienced developers who argue with me about comments.

The Pragmatic Programmer is an excellent book. It outlines best practices that have solidified over the last thirty years or so as software development has grown as a field. The authors share these practices as a series of tips that are justified by real world anecdotes. In a section on comments the authors say

“The DRY principle tells us to keep the low-level knowledge in the code, where it belongs, and reserve the comments for other, high-level explanations. Otherwise, we’re duplicating knowledge, and every change means changing both the code and the comments. The comments will inevitably become out of date, and untrustworthy comments are worse than no comments at all”

They make the point that obsolete comments are worse than no comments at all. This is undoubtably true, but it has been bastardized by many programmers as an excuse for not commenting. I’ve heard this excuse, along with two others to justify a lack of comments in code.

  1. The code is self-commenting.
  2. Out of date comments are worse than no comments.
  3. You shouldn’t rely on comments.

In this post I want to address each of these points. I think that thorough commenting speeds up the rate of consumption of code, and that obsolete comments are a failure in maintenance, rather than in comments in general.

1. The code is self-commenting

This is the excuse I hear most often from developers who don’t comment their code. The thinking is that clear variable and method names replace the need for comments. There are situations where this is true. For very short methods with a single purpose, I see that no additional comments may be necessary.

But most methods are not very short, and most methods achieve several things that relate to one overall purpose. So in the first place, very few methods fit the bill.

This is not a valid complaint because good comments only make the code easier to read. While the code may be legible on its own, a comment that explains the purpose of a method, or the reason for
a string operation, can only make it easier to read. The author of Clean Code agrees due to the amount of time we spend reading code.

“the ratio of time spent reading vs. writing is well over 10:1. We are constantly reading old code as part of the effort to write new code. Because this ratio is so high, we want the reading of code to be easy, even if it makes the writing harder.”

Because we spend more time reading code than writing it, a responsible programmer knows that the extra comment in a method which takes very little time to write may well save another programmer many hours of learning.

2. Out of date comments are worse than no comments

To refute this argument, lets take cars as an analogy. If you buy a car, then drive it for twenty thousand miles without an oil change, it will break down. If you did that, the fault wouldn’t be in cars in general. Rather, the fault is in the lack of maintenance.

Similary, obsolete comments are not a failure of comments in general, but a failure of the programmer who updated the code without updating the comments. That other programmers have bad practices does not justify continuing that bad practice.

Obsolete comments are a broken window. If you see them, it is your job to fix them.

So while obsolete comments ARE worse than no comments, that argument is an argument against bad coding practices, not comments in general.

3. You shouldn’t rely on comments

The argument that a programmer shouldn’t rely on comments is a subtle dig at another programmer’s skill. They’re saying “a good programmer can understand this code with no comments.”

There is a grain of a valid point there. If you consider yourself a senior programmer, then you should be accustomed to wading through large volumes of bad code and parsing out the real meaning and functionality.

But even for senior programmers, comments make it easier to read and understand the code. It’s much easier to interpret a one line summary of a block of code than to parse that block line by line. It’s much easier to store that one line in your head than it is to store the whole block in your head.

The real reason why this is the worst of excuses is that not all programmers working on your code are senior programmers. Some are green graduates straight out of college. Yes, a more experienced programmer could understand the code without comments, but it will cost that graduate hours to figure out what they could have gotten in minutes with good comments.

My Commenting Principle

Comment your code so that a green programmer can understand it.


Comment your code so that your boss can understand it.

What does it take to make your code readable by a green graduate? Imagine them going through it line by line. If there are no comments, then they need to understand every function call, and every library routine. They need to understand a bit about your architecture and date model.

Now imagine that every single line is commented.

In that scenario, a green programmer can read your file by reading one comment after the next. If they need more information, they can still drill into the code and get the details, but they can understand the overview just through comments.

The closer you can get to that, the better.

Don’t listen to the arguments against thorough commenting habits. Just point the detractors here.

16. January 2016 by evan
Categories: Software, Software Design | Tags: , , , , , | Leave a comment

← Older posts