JS Coding Patterns that give you away as a Junior Developer
Tags: javascript, functional, coding, programming
Published: 2020-08-31 23:23:25

Computer programming is somewhere between an art and a science. Your code must match the syntax that the computer expects and understands, but the style and flow of your program are ultimately up to you.

Most programming problems can be solved in many different ways and judging one as better than another can be tricky. Sometimes, things come down to personal preference, and other times one approach is just better than another. This could be for performance, conciseness, or readability.

This post explores two patterns that are more likely to be used by junior developers than senior ones. The examples below are written in JavaScript, but the general principles extend to other programming languages as well.

#1. Overuse of “if” and “else” Statements
Let’s say we are writing a class used to represent Simpsons characters. The constructor of the class accepts a first name, last name, and occupation for that character.
The code below creates the class and instantiates an example character, *edna*.
```
class Character {
  constructor (firstName, lastName, occupation) {
    this.firstName = firstName
    this.lastName = lastName
    this.occupation = occupation
  }
}
const edna = new Character(
  'Edna',
  'Krabappel',
  'Elementary School Teacher'
)
```
Now, let’s say that we want to add a getter property to our class that returns a boolean, describing whether the character is a member of the Simpson family or not.
Edna Krabappel is not a member of the Simpson family, but Lisa Simpson would be. Here is one way that this might be achieved, but it isn’t very good.
```
class Character {
  constructor (firstName, lastName, occupation) {
    this.firstName = firstName
    this.lastName = lastName
    this.occupation = occupation
  }
  
  get isSimpson () {
    if (this.lastName === 'Simpson') {
      return true
    } else {
      return false
    }
  }
}
const edna = new Character(
  'Edna',
  'Krabappel',
  'Elementary School Teacher'
)
console.log(edna.isSimpson) // Logs false, as expected
```
This code works as expected, but is unnecessarily verbose.
For starters, the *else* block isn’t needed. If the condition is found to be *true*, then the function will return a value and terminate — the *else* alternative will never be reached.

This fact allows us to simplify the method to the following:
```
get isSimpson () {
  if (this.lastName === 'Simpson') {
    return true
  }
  return false
}
```
Generally speaking, it’s stylistically preferable to avoid else blocks because it reduces code nesting. Although this isn’t always possible, it often is.

But even with that improvement, the method is still a bit silly. Since the getter intends to return a boolean as the output, an if statement isn’t needed at all.

This code does the same job:
```
get isSimpson () {
  return this.lastName === 'Simpson'
}
```
That’s much nicer. Comparison operators are often combined with if statements, but they don’t have to be. Sometimes, it’s better to just return a boolean directly.

#2. Using Functional Programming in a Nonfunctional Way
JavaScript arrays can be manipulated either procedurally or functionally.

A functional approach is often preferable because it avoids mutation and unnecessary variables, but a procedural approach can be appropriate in certain situations as well.

While your choice of paradigm may be a matter of taste, misuse of functional programming techniques can identify you as a beginner. To illustrate, here’s an example.

Let’s say that we have an array of *Character* objects available, and want to use this data to create an array of names.
```
// An example input array could look like this:
const characters = [
  new Character(
    'Edna',
    'Krabappel',
    'Elementary School Teacher'
  ),
  new Character(
    'Lisa',
    'Simpson',
    'Student'
  ),
  new Character(
    'Moe',
    'Szyslak',
    'Bartender'
  ),  
]
// In that case the output we are looking for would look like this:
[
  'Edna Krabappel',
  'Lisa Simpson',
  'Moe Szyslak'
]
```
The first step is going to be adding a getter to our *Character* class that returns the full name of the character:
```
get fullName () {
  return `${this.firstName} ${this.lastName}`
}
```
With that available, we can move on to getting an array of full names. Here is one solution that works, but leaves room for improvement:
```
const names = []
characters.forEach(character => {
  names.push(character.fullName)
})
```
This implements *forEach* and provides a callback function, but it might as well have been implemented procedurally.
Instead of returning a value, each iteration of the loop mutates the external *names* variable. A *for* loop could easily achieve the same thing:
```
const names = []
for (let character of characters) {
  names.push(character.fullName)
}
```
*forEach* just isn’t the right choice for this. To ensure that the callback function remains “pure”, we should use another array method — let’s try *reduce*.
```
const names = characters.reduce((names, character) => {
  return names.concat(character.fullName)
}, [])
```
This attempt avoids the problems associated with *forEach* but still isn’t great.

The problem lies with the verb “reduce”. As well as preventing externally declared variables and mutation, one important benefit of functional programming is readability.

A functional method like “filter” or “reduce” can make for more expressive and readable code when used correctly.

For example, when a programmer sees that an array is being “filtered” they can assume that a set of items are being inputted, and only a subset of those items will be outputted. The items that were not outputted were “filtered out”.

Likewise, when a programmer sees an array being “reduced” they can assume that the function will take the input set and “reduce it” to a more compact output. You might “reduce” a list of test scores to a single average.

This gives readers of your code a helpful hint of what it does. If the array was being operated on procedurally, then readers would need to dig into the code at a lower level to understand what is happening.

Getting back to the example, this solution is not ideal because the verb “reduce” does not accurately describe what is happening. Since the goal is to return one output item for each input item, “map” is a much better choice. It’s also much more concise:
```
const names = characters.map(character => character.fullName)
```

#Summary
Writing code that works is good but we should also strive to write code that is succinct, performant, and readable to others.

Eliminating redundant *if* and *else* conditions and selecting array methods appropriately are a good step towards this goal.

Seemingly small details such as these are one way that experienced programmers can be distinguished from less experienced ones.