Two JavaScript Coding Patterns That Give You Away as a Junior Developer

Computer programming is somewhere between an art and a science

Chris Geelhoed
Nov 4 · 5 min read
Photo by Pixabay from Pexels

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.

Better Programming

Chris Geelhoed

Written by

Software developer and teacher

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade