Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Cleaning up our JavaScript code is easy with default parameters and property shorthands.
In this article, we’ll look at the best practices when we create classes and functions.
Avoid Creating God Classes
God classes are classes that are all-knowing. If a class is mostly used for retrieving data from other classes using get and set methods, then we don’t need the class.
So if we have something like this:
class Foo {
getBar() {}
setBar() {}
getBaz() {}
setBaz() {}
getQux() {}
setQux() {}
}
We can remove the class, and access the things we need directly.
Eliminate Irrelevant Classes
If we need a class, then we should remove it.
This applies to classes that only have data. If we have members that are in the class, then we should consider if they should be members of another class instead.
Avoid Classes Named After Verbs
We shouldn’t name classes with verbs since a class that has only behavior but not data shouldn’t be a class.
For instance, if we have:
class GetFoo {
//...
}
Then it should be a function instead of a class.
When Should We Create Functions?
We should create functions to make our code better. The following are the reasons for creating functions.
Reduce Complexity
Reducing complexity is one of the most important reasons for creating functions.
We got to create them so that we don’t repeat code and minimizing code size.
If we write all procedures without functions, then we would have lots of similar code.
For instance, if we have:
const greet1 = `hi joe`;
const greet2 = `hi jane`;
Then we can make a function to generalize that:
const greet = (name) => `hi ${name}`;
const greet1 = greet('joe');
const greet2 = greet('jane');
Now we can call greet
anywhere to create similar strings.
Introduce an Intermediate, Understandable Abstraction
The code above is also an abstraction. We generalized the code for returning greeting strings.
We can pass in different values of name
and return a new string.
Avoid Duplicate Code
Avoiding duplicate code is also a good reason for creating functions.
Again, as we can see from the example above, we can call greet
to create many more of the same strings.
Then we don’t have to repeat the hi
part everywhere.
Support Subclassing
We can create a method in a subclass to override a method in the superclass.
For instance, we can write the following code to do that in JavaScript:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} speaks`;
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
return `${super.speak(this.name)} in dog language`;
}
}
We have overridden the speak
method in Dog
by calling super.speak
.
Therefore, we can keep the speak
method in Dog
simpler.
Photo by Danielle Cerullo on Unsplash
Hide Sequences
Functions are good for hiding implementations of procedures.
For instance, we can have a function that calls other functions and do something with them.
We can write:
const calcWeight = () => {
//...
}
const calcHeight = () => {
//...
}
const calcWidth = () => {
//...
}
const getAllDimensions = () => {
const weight = calcWeight();
//...
const height = calcHeight();
//...
const width = calcWidth();
//...
}
We called multiple functions in the code above. But other parts of our program won’t know the order that they’re called.
This reduces the implementation that is exposed and reduces coupling.
Improve Portability
Functions can be moved anywhere easily. We can move it and anything else that depends on it easily.
Simplify Complicated Boolean Tests
If we have long boolean expressions, then we should put them into their own function.
For instance, if we have:
const isWindowsIE = navigator.userAgent.toLowerCase().includes('windows') &&
navigator.userAgent.toLowerCase().includes('ie');
Then we can put the whole thing into a function by writing:
const isWindowsIE = () => {
const userAgent = navigator.userAgent.toLowerCase()
return userAgent.includes('windows') &&
userAgent.includes('ie');
}
It’s just much cleaner than having long boolean expressions.
Conclusion
God classes, classes that only data or behavior are all bad. We should make sure that we have a mix before creating both.
We create functions to reduce complexity, remove duplicate code, and make abstractions.
They’re good for creating anything.