"There is always a well-known solution to every human problem–neat, plausible, and wrong."
– H.L. Menken.

If you've ever gathered requirements, reviewed change requests, or even handled support tickets, you've probably seen cases where a proposed solution did not resolve the user's need. Learn to recognize the true need underlying a request so you can create solutions that actually solve problems.

To illustrate, consider the following book titles:

A Study in Scarlet
The Sign of Four
The Adventures of Sherlock Holmes
The Memoirs of Sherlock Holmes
The Hound of the Baskervilles
The Return of Sherlock Holmes
His Last Bow
The Valley of Fear
The Case-Book of Sherlock Holmes

Suppose these are stored in an array and you've been asked to print the titles with JavaScript:

    var iTotal = astrTitles.length; 
    if ( iTotal > 0 ) {
        
       for ( var iTitles = 0; iTitles < iTotal; iTitles++ ) {
          var str = astrTitles[ iTitles ];
          writeTitle( str );
       }
    }

Here, the writeTitle() function represents whatever display technique is appropriate for your use (example #1).

Your code might vary, but the underlying approach would likely be similar. You'd loop through the array and print each element value. (It's worth noting that the initial order roughly corresponds to original publication order of these titles.)

Now, suppose your users ask you to print the titles alphabetically. To do so, you might use (example #2):

    var iTotal = astrTitles.length; 
    if ( iTotal > 0 ) {
    
       astrTitles.sort();
       for ( var iTitles = 0, iTitles++, iTitles < iTotal ) {
          writeTitle( astrTitles[ iTitles ] );
       }
    }

This leads to:

A Study in Scarlet
His Last Bow
The Adventures of Sherlock Holmes
The Case-Book of Sherlock Holmes
The Hound of the Baskervilles
The Memoirs of Sherlock Holmes
The Return of Sherlock Holmes
The Sign of Four
The Valley of Fear

Sorting the values is the obvious, simplest answer. Is it the correct answer? Not really; it addresses the request, but not the need. This version uses the entire string value to determine sort order. However, there's a difference between alphabetic sorting and dictionary sorting (which ignores leading articles). In dictionary sorting, "A Study in Scarlet" appears after "The Sign of Four." The need, then, is to use dictionary sorting rather than strict alphabetic sorting.

In earlier times, libraries handled this by moving leading articles to the end of the title, as in "Study in Scarlet, A", "Sign of Four, The", and so on.

You could follow the same convention by modifying the data values accordingly:

"Adventures of Sherlock Holmes, The"
"Case-Book of Sherlock Holmes, The"
"His Last Bow"
"Hound of the Baskervilles, The"
"Memoirs of Sherlock Holmes, The"
"Return of Sherlock Holmes, The"
"Sign of Four, The"
"Study in Scarlet, A"
"Valley of Fear, The"

This approach is simple and leads to the expected result. It's well-known, neat, and plausible. It also avoids code changes. However, the technique forces the user to adapt to the limitations of the implementation. Worse, future features (such as search) become more difficult to implement. There must be a better way.

You might think to store separate data values: one displayed to the user and one used to sort the data. In the long run, this would be more effective than changing the data because it provides the correct order without affecting the user's experience. However, additional costs soon become apparent. First, storage increases because of the near duplicate data values. Second, your code now needs to synchronize both values when the data changes.

(Contrary to expectation, book titles can change over time. "The Sign of Four" was originally published as "The Sign of The Four" and there's an open debate as to which title is the correct one.)

Fortunately, JavaScript provides a better way, one that slightly increases the code without duplicating the data or breaking the user's experience (example #3):

    function moveLeadingArticle( sInput ) {
       var sResult = sInput.toLocaleLowerCase();
       var aArticles = [ 'a', 'an', 'the' ];
       var aWords = sResult.split(/\s/);
       if ( aArticles.indexOf( aWords[0] ) > -1 ) {
          sResult = aWords.slice( 1 ).join( ' ' );
          sResult += ', ' + aWords[0];
       }   
       return sResult;
    }

    var iTotal = astrTitles.length; 
    if ( iTotal > 0 ) {
    
       if ( aResultsArray.length > 1 ) {
       
          aResultsArray.sort( function( a, b ) {
             var SortTermA = moveLeadingArticle( a );
             var SortTermB = moveLeadingArticle( b );
             return SortTermA.localeCompare( SortTermB );
          } );
       }

       for ( var iTitles = 0, iTitles++, iTitles < iTotal ) {
          writeTitle( astrTitles[ iTitles ] );
       }
    }

Here, the moveLeadingArticle() function uses a regular expression to detect and move leading articles to the end of a title. The sorting code uses an anonymous function to override the built-in sort algorithm with one using the new function. These changes incorporate the librarian's trick without affecting the underlying data or the user's experience.

This provided the expected results:

    The Adventures of Sherlock Holmes
    The Case-Book of Sherlock Holmes
    His Last Bow
    The Hound of the Baskervilles
    The Memoirs of Sherlock Holmes
    The Return of Sherlock Holmes
    The Sign of Four
    A Study in Scarlet
    The Valley of Fear

This solution meets the user's need without adversely affecting their experience, without requiring changes to the data, and without complicating future feature requests. This is the right answer.

Your users are unlikely to notice the additional effort put into your final solution. That's fine; it really is. The satisfaction of programming comes, in part, from correctly meeting user needs, even when the implementation needs a little more work than originally expected.

Revision History

26 Jan 2017: Original post.