We can clean up our JavaScript code so that we can work with them more easily.
In this article, we’ll look at some refactoring ideas that are relevant for cleaning up JavaScript conditionals.
Pull Up Constructor Body
If we have multiple constructor bodies in our subclasses with overlapping code, we can move them to the superclass.
For instance, if we have the following code:
class Employee {
}
class Cook extends Employee {
constructor(name, level) {
this.name = name;
this.level = level;
}
}
class Manager extends Employee {
constructor(name) {
this.name = name;
}
}
We can move the common code in both constructors to the superclass as follows:
class Employee {
constructor(name) {
this.name = name;
}
}
class Cook extends Employee {
constructor(name, level) {
super(name)
this.level = level;
}
}
class Manager extends Employee {
}
In the code above, we move the code for setting the name
field to the Employee
class to avoiding duplicating that in the Cook
and Manager
classes.
Push Down Method
If we have superclass methods that are only used by an instance of one subclass, then we should move it to the subclass.
For instance, if we have the following code:
class Employee {
speak() {
//...
}
}
class Cook extends Employee {
}
class Manager extends Employee {
}
const cook = new Cook();
cook.speak();
Since speak
is only called by a Cook
instance, we can move it to the Cook
class:
class Employee {
}
class Cook extends Employee {
speak() {
//...
}
}
class Manager extends Employee {
}
const cook = new Cook();
cook.speak();
This way, we can reduce the clutter of our superclass.
Push Down Field
We push down a field that’s only used in one or a few subclasses to the subclass itself.
For instance, instead of writing the following code:
class Employee {
constructor(subordinates) {
this.subordinates = subordinates;
}
}
class Cook extends Employee {
}
class Manager extends Employee {
}
We can put the subordinates
field to the Manager
class as follows:
class Employee {
//...
}
class Cook extends Employee {
//...
}
class Manager extends Employee {
constructor(subordinates) {
this.subordinates = subordinates;
}
}
The subordinates
field only applies to Manager
so it should be there.
Extract Subclass
If we have a class that has features that are only used by some instances, then it should be extracted to its own subclass.
For instance, if we have the following code:
class Employee {
//...
getSubordinates() {
//...
}
}
Then since getSubordinates
isn’t used by all Employee
instances, we can extract it as follows:
class Employee {
//...
}
class Manager extends Employee {
//...
getSubordinates() {
//...
}
}
This way, we don’t have to clutter up the Employee
class with methods that not all instances need.
Extract Superclass
If we have 2 or more classes with similar features, then we should move the shared members to a superclass.
Then the existing classes can be subclasses of the superclass.
For instance, if we have the following code:
class Cat {
//...
speak() {
//...
}
}
class Dog {
//...
speak() {
//...
}
}
Then we can create a new class with the speak
method and make Cat
and Dog
subclasses of that class as follows:
class Animal {
//...
speak() {
//...
}
}
class Cat extends Animal {
}
class Dog extends Animal {
}
Now we don’t have any more duplication.
Photo by NeONBRAND on Unsplash
Collapse Hierarchy
If the subclass and superclass aren’t too different, then we can combine them into one.
For instance, if we have the following:
class Animal {
//...
speak() {
//...
}
}
class Cat extends Animal {
//...
}
We can combine them as follows:
class Animal {
//...
speak() {
//...
}
}
Since the Cat
class didn’t have many extra things we need, we can just remove it.
Any overly complex class hierarchy isn’t good.
Conclusion
We can remove duplicate from multiple classes by moving common code to a superclass.
If we don’t need much in a subclass, then we can remove it and combine all the members into one class.