Keep it simple, stupid (KISS)!

Everyone knows the DRY acronym: “don’t repeat yourself”. But another one I try to keep in mind is KISS: “keep it simple, stupid!”

When I first built my word and character counter, I think I overcomplicated it. Trying to avoid any form of “repetition”, I created a single function that could count words and characters.

/**
 * Count the number of words/characters in a form control
 * @param   {Node}    element    The element whose words/characters should be counted
 * @param   {Boolean} countChars Whether to count words (false) or characters (true)
 * @returns {Number}             The word/character count
 */
function countWordsOrChars (element, countChars) {

  // Bail if the element doesn't exist
  if (!element) return;

  // If counting charaters, get the count
  // Otherwise, trim any whitespace
  var count = countChars ? element.value.length : element.value.trim();

  // If no words/characters, return zero
  if (!count) return 0;

  // If counting words, get the count
  // (counting words as separated by 1 or more whitespace characters)
  if (!countChars) count = count.split(/\s+/).length;

  // Return the count
  return count;

}

I made the code more complicated than it needed to be.

This reminds me of the quote I shared in Rethinking DRY:

As Harry Roberts says, “DRY is often misinterpreted as the necessity to never repeat the exact same thing twice. This is impractical and usually counterproductive, and can lead to forced abstractions, over-thought and over-engineered code.”

We kicked off a new session of the Vanilla JS Academy last week, so I decided to rethink my approach. I opted for two separate functions this time: one for counting words, and one for counting characters.

/**
 * Get the number of words in a text area
 * @param   {Node} textArea The text area
 * @returns {Number}        The word count
 */
function getWordCount (textArea) {

  // Trim whitespace from the value
  var value = textArea.value.trim();
  
  // If it's an empty string, return zero
  if (!value) return 0;

  // Otherwise, return the word count
  return value.split(/\s+/).length;

}

/**
 * Get the number of characters in a text area
 * @param   {Node} textArea The text area
 * @returns {Number}        The character count
 */
function getCharacterCount (textArea) {
  return textArea.value.length;
}

This is so much better!

Two separate functions, each with its own job. The code is now easier to read, test, and maintain thanks to my newfound separation of concerns.

Keep it simple, stupid! 🥴


If you have questions, feedback, or any other suggestions, please do email me. I'd love to hear from you!