Categories
Refactoring

Cleaning Up Our JavaScript Code by Refactoring Them — Encapsulation

Spread the love

JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to write a piece of clean JavaScript code.

In this article, we’ll look at ways to refactor our code by encapsulating our API calls in their own React component, and use factory functions to provide polymorphism in our JavaScript code.

Encapsulate APIs in Our React Components

To decouple API calls from our components, we can call one API per component.

This way, if one API changes, it won’t break other components. It also keeps components simple because at most they use one API.

For instance, we can create components and use them as follows:

import React, { useState, useEffect } from "react";

const Person = () => {
  const [person, setPerson] = useState({});
  const getData = async () => {
    const res = await fetch("https://api.agify.io?name=michael");
    const p = await res.json();
    setPerson(p);
  };
  useEffect(() => {
    getData();
  }, []);

  return <p>{person.name}</p>;
};

const Dog = () => {
  const [dog, setDog] = useState({});
  const getData = async () => {
    const res = await fetch("https://dog.ceo/api/breeds/image/random");
    const d = await res.json();
    setDog(d);
  };
  useEffect(() => {
    getData();
  }, []);

  return <img src={dog.message} alt="" />;
};

export default function App() {
  return (
    <div className="App">
      <Person />
      <Dog />
    </div>
  );
}

In the code above, we have 2 components, each of which calls a single. The Person component calls one and Dog calls another. They only render something simple.

Then in App , we use them both at the same level. This way, we can combine them into one place without creating one large component.

If we have to share data between these components, then we can use some state management solutions like Redux or Mobx to share data in a centralized place in a way that’s decoupled from the component.

Replace Conditional with Polymorphism

Polymorphism is a provision of creating a single interface of entities to different types.

In JavaScript, there’re no interfaces, but we can still use this principle to let us create functions that returns objects of different class instances that have the same methods that we can call by calling one function instead of instantiating multiple classes ourselves and calling the methods ourselves.

For instance, we can create a factory function that instantiates multiple classes and return one by checking the arguments that we pass into the factory function.

Instead of writing:

const meow = (animal) => {
  //...
};
const bark = (animal) => {
  //...
};
if (animal === 'cat') {
  meow(animal);
}

if (animal === 'dog') {
  bark(animal);
}

We can instead create classes and instantiate them with a factory function as follows:

class Cat {
  speak() {}
}

class Dog {
  speak() {}
}

const Animal = (type) => {
  if (type === 'cat') {
    return new Cat();
  } else if (type === 'dog') {
    return new Dog();
  }
}

const cat = Animal('cat');
const dog = Animal('dog');
cat.speak();
dog.speak();

In the code above, we have 2 classes, Cat and Dog . They have the same speak method instead of the meow and bark functions.

Then we created an Animal class, which has the type parameter to let us specify the type of animal to instantiate. If the type is 'cat' , then we return a new Cat instance. If the type is 'Dog' , then we return a new Dog instance.

After that, we can use the same Animal function to create these 2 class instances and call the speak method on the returned object.

This way, we only have to depend on the Animal function rather than a bunch of different functions. So we don’t have to worry about anything other than Animal having breaking changes.

This is a commonly used principle to reduce coupling. We reduce the number of dependencies that we have to rely on to reduce coupling so that we have fewer chances of breaking our code when anything changes.

This makes our code more robust.

Conclusion

To keep our React components simple, we should break them up so that they only do one thing. One way to do that is to only have each component call a maximum of one API.

Polymorphism is also a good way to reduce coupling. We can create a factory function that instantiates classes for us and have the class include the same method names so that they implement one interface and we don’t have to worry about the implementation of those classes.

Even though JavaScript has no interfaces, we can still make sure that classes have the same methods included.

Leave a Reply

Your email address will not be published.

If you like the content of this blog, subscribe to my email list to get exclusive articles not available to anyone else.