DEV Community

Jesse M. Holmes
Jesse M. Holmes

Posted on

There is more than one way to make your code readable

Let's say you find the following code:

  useEffect(() => {
    const generateId = (acc: number, curr: string) => 
      acc += cur.charCodeAt(0)

    if (id === 0) {
      let x = profileId.split('').reduce(generateId, 0)
      setId(x % 8 + 1)
    }

  },[profileId])
Enter fullscreen mode Exit fullscreen mode

What do we know about this effect?

  1. It runs when the profileId changes and if some other id is equal to zero.
  2. The profileId is converted from a string to a string array.
  3. The string array is reduced using a generateId function that returns (acc += cur.charCodeAt(0)) % 8 + 1, whatever that is.

If a less experienced developer finds this in a React component, they may be confronted with a few obstacles:

  1. How comfortable are they with .reduce()? What are acc and cum?
  2. What is x, and why are we setting the other ID to whatever x is?
  3. What is the intent of the effect? Why is it needed?

A more experienced developer, perhaps even the developer who wrote this code, will face similar obstacles. How can we write this code so that someone can understand what is going on right away? Here are a few attempts.

Comment your code, and use variable names that reveal their intent

Variable are things, and we should name those things well! Call them what they are! It's not an ID, it's an Avatar ID. This would be an improvement even without the comment block. I prefer to think of .reduce() as having state, explained beautifully by Joel in under 5 minutes:

An informative comment or comment block causes no penalty to performance, and you won't lose cool points for writing one. I promise the developer reading your code would rather understand what is going on than being impressed by your one-line function.

If you are fortunate enough to be mentoring junior developers with some frequency, there is also no penalty for leveraging the community for the bits of the JavaScript developers don't touch every day.

  /**
   * Generate the avatar id
   * 
   * 1. convert licensingProfileId from string into string array
   * 2. (reducer) sum the ascii code for each character
   * 3. (reducer) mod by 8 for the 8 possible avatars
   * 4. (reducer) add 1 to generate the possible id
   *
   * Learn more about .reduce():
   * MDN: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
   * Minute JavaScript: (https://dev.to/joelnet/minute-javascript-array-s-reduce-method-18h0)
   * 
   * .charCodeAt(0) returns the ascii code of a string character at the index passed in. 
   * In this case, item is always a single-character string.
   */
  useEffect(() => {
    const generateAvatarId = (state: number, item: string) => 
      state += item.charCodeAt(0)

    if (avatarId === 0) {
      let avatarId = licensingProfileId.split('').reduce(generateAvatarId, 0)
      setAvatarId(avatarId % 8 + 1)
    }

  },[licensingProfileId])
Enter fullscreen mode Exit fullscreen mode

Shorter code isn't necessarily more readable

Remember when your math teacher would hand your assignments back covered in red ink with Show your work!! written across the top? Just me? Feel free to follow this strategy here as well. I personally wouldn't go as far as this example with transient/placeholder variables at each step.

  /**
   * Generate the avatar id
   */
  useEffect(() => {
    const generateAvatarId = (state: number, item: string) => {
      let asciiCode = item.charCodeAt(0) // Get a number from the string character
      state += asciiCode // state is the sum of the ascii codes
      return state
    }

    if (avatarId === 0) {
      // transform string to array so that we can use .reduce()
      let stringArray = licensingProfileId.split('') 
      // starting from 0, sum the ascii codes for each character in the profileId
      let asciiCodeSum = stringArray.reduce(generateAvatarId, 0)
      // There are only 8 avatars to choose from
      let selectedAvatar = asciiCodeSum % 8
      // Add 1 to assign an ID of 1–8
      let selectedAvatarId = selectedAvatar + 1
      setAvatarId(selectedAvatarId)
    }

  },[licensingProfileId])
Enter fullscreen mode Exit fullscreen mode

Whatever combination of techniques you decide to use, the result will save questions and head scratching when the code has been stale for a while.

Top comments (0)