DEV Community

Duncan McArdle
Duncan McArdle

Posted on

4 2

SOLID principle #1: Single responsibility (JavaScript)

The single responsibility principle says that a class or module should have only a single purpose. For example, if you have a wallet class, that class should only implement wallet functionality. It’s fine to call other functionality, but it shouldn’t be written there.

Let’s look at a bad example. In the code below, the Car class has a single method; start. When this method is called the car may or may not start, depending on some logic which isn’t included here as it’s not important. The class will then log some information depending on the outcome. But notice how the logging functionality is implemented as a method of this class:

class Car {
constructor(make, model) {
this.make = make;
this.model = model;
}
start() {
if (...) { // Logic to determine whether or not the car should start
this.errorLog(`The car ${this.make} ${this.model} started.`);
return true;
}
this.errorLog(`The car ${this.make} ${this.model} failed to start.`);
return false;
}
errorLog(message) {
console.log(message);
}
}

This violates the single responsibility principle, because the logic for logging the information should not be a responsibility of the Car class.

There are a number of readability and code management issues that are caused by this, but the easiest issue to describe is actually refactoring.

Let’s say your logger logs to a file, and this works great for several months. Suddenly, an update occurs on the underlying system that the car class is running on, and you need to change the way you write to files. Suddenly you now need to update every file writing instance of every class you’ve ever implemented a logger inside of. The task would be huge! But what if you’d followed the single responsibility principle?

class ErrorLog {
static log(message) {
console.log(message);
}
}
class Car {
constructor(make, model) {
this.make = make;
this.model = model;
}
start() {
if (...) { // Logic to determine whether or not the car should start
ErrorLog.log(`The car ${this.make} ${this.model} started.`);
return true;
}
ErrorLog.log(`The car ${this.make} ${this.model} failed to start.`);
return false;
}
}

As you can see here, we wouldn’t have this problem. The logger is stored in a separate class, which means its functionality is separate to the Car class. The Car class can be changed, moved around or even deleted without affecting the logger class. Likewise, if a change is required to the logger class, it only needs to be carried out in a single place.

Sentry blog image

How to reduce TTFB

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

In this article, we’ll see how we can identify what makes our TTFB high so we can fix it.

Read more

Top comments (2)

Collapse
 
parenttobias profile image
Toby Parent

People often get confused, thinking that "single responsibility" means "doing one thing." It doesn't.

I tend to use the analogy of being a parent: I am responsible for my sons. This doesn't mean I'm responsible for seeing to it that they eat a certain amount of green leafies each day, or that I'm responsible for making sure they're in bed by a reasonable hour - I am responsible for the health, safety and well-being of my sons. There are many behaviors associated with meeting that responsibility, things I am capable of doing - single responsibility does not mean single-use.

In the same way, a Car instance deals with coordinating all the responsibilities of the systems that make up the Car. Might be accellerating, might be steering, might be ignition, might be radio. These are all components of that Car, and they all make up things over which that Car has oversight... or responsibility.

Its single responsibility is managing its subsystems.

Collapse
 
jwp profile image
JWP

This principle is the single most important one in all of programing. Not just for classes but for methods too.

It even translates to Javascript using functions or pure functions.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay