Modules vs Classes - How to Manage Privacy in JS
Tags: javascript, tutorial
Published: 2020-02-21 17:05:53

The **Object-Oriented Paradigm** made a huge shake in the way developers think and write code even if you don't like it or don't like its premises. This _not so new_ paradigm of encapsulating data and procedures in form of **attributes** and **methods** influenced a lot of recent languages even if some of them are not using it as its main paradigm.

Languages like: C++, Java, Python, and even JavaScript are considered and declared languages that implement the Object-Oriented Paradigm (OOP). As will be discussed, JavaScript has its own way of dealing with Objects with some specificities. But first, there is a starting point that should be discussed: there's one essential fact in JavaScript that goes in the wrong direction of OOP: non-existence of **encapsulation**.

_There's a repo with some tests too! [Check it out](https://github.com/caian-gums/modules-vs-classes-post)!_

## Classes and Objects

**Classes** are definitions of data-types: what data they will **store/hide** and how it **should behave**. An instance of one Class will be able to execute functions as methods and store data as attributes. Those instances are the so-called **Objects** that lives inside the runtime execution of a program.


![Photo by Dan Dimmock on Unsplash](https://dev-to-uploads.s3.amazonaws.com/i/y51exh459iveu5owao7m.jpeg)
<figcaption>Photo by Dan Dimmock on Unsplash</figcaption>


One of the important features in OOP is the fact that the Objects should have the ability to **encapsulate**(hide) its data. That means that if someone tries accessing some information from the Object, it should **not** be able to do it if the Class says so. Consider the following example:

Let's say that Elon Musk 🧑‍💼 created an awesome `Trash Can` that can perform 3 simple tasks:
- Throw _one_ 'junk' item into the Trash Can
- Clean all items inside the Trash Can, all at once
- One button that shows at the display if the Trash Can is fully empty or not

The interface for that `TrashCan` is something like:

```js
TrashCan {
  throwAway(item);
  clean();
  isEmpty();
}
```

As JavaScript has the `class` keyword, it's possible to consider one implementation of this `Trash` as the following

```js
class TrashCan {
  constructor() {
    this.items = [];
  }

  throwAway(item) {
    this.items = [...this.items, item];
  }

  clean() {
    this.items = [];
  }

  isEmpty() {
    return this.items.length === 0;
  }
}

var elonTrashCan = new TrashCan();
```

Now the `elonTrashCan` is empty and ready to start doing its work. But what happens with the execution of

```js
elonTrashCan.throwAway('paper ball');
elonTrashCan.throwAway('empty Starbucks cup of coffee');
elonTrashCan.throwAway('empty package of Cookies');

elonTrashCan.clean();

elonTrashCan.items = ['SpaceX secret project'];

console.log(elonTrashCan.isEmpty()); // --> ???
```

1. Elon Musk 🧑‍💼 will be mad at us that we broke his Trash Can
2. `elonTrashCan.isEmpty()` will return `false`, because we defined `elonTrashCan.items` with 1 item inside
3. `elonTrashCan.items` is not accessible, so the `elonTrashCan.isEmpty()` call will returns `true`

The answer is **option 2**. It is possible to access `items` inside the Object instance even without explicit `items` declaration outside `constructor`.

Using that example and considering an ideal Object-Oriented language implementation, the execution of `elonTrashCan.items` should result in an error of the program trying to access a **private attribute**. In JavaScript, these calls are possible, valid ones, and results in **no error**.

So, isn't it possible to create **Privacy** in JavaScript? Is there a way of hiding data from outside the Object and exposing just `public` data?

![Photo by Folco Masi on Unsplash](https://dev-to-uploads.s3.amazonaws.com/i/ghpswvj6jgx2bz892rqf.jpeg)
<figcaption>Photo by Folco Masi on Unsplash</figcaption>

## Module Pattern

The good news is there's one behavior in JavaScript that provides something related to **privacy**: **Closures**. There's this post written about Closures in case of interest {% post caiangums/closures-in-js-and-why-it-matters-pb9 %}

Using **Closures** for hiding variables and functions is a good approach for encapsulate data inside one instance and just expose the desired interface of it.

_But how do actually this works?_

Let's create the same Elon Musk 🧑‍💼 `TrashCan` Object writing a Function and returning just the public interface of it as the following code

```js
const TrashCan = () => {
  let items = [];

  const throwAway = item => {
    items = [...items, item];
  }

  const clean = () => {
    items = [];
  }

  const isEmpty = () => {
    return items.length === 0;
  }

  return {
    throwAway,
    clean,
    isEmpty,
  }
}

var elonTrashCan = TrashCan();
```

And for the new `elonTrashCan` let's try to execute the same code as above

```js
elonTrashCan.throwAway('paper ball');
elonTrashCan.throwAway('empty Starbucks cup of coffee');
elonTrashCan.throwAway('empty package of Cookies');

elonTrashCan.clean();

elonTrashCan.items = ['SpaceX secret project'];

console.log(elonTrashCan.isEmpty()); // --> ???
```

1. Elon Musk 🧑‍💼 will be even madder at us that we broke his second Trash Can
2. `elonTrashCan.isEmpty()` will return `false`, because we again defined `elonTrashCan.items` with 1 item inside
3. `elonTrashCan.items` is not accessible, so the `elonTrashCan.isEmpty()` call will returns `true`

Actually something very strange happens:
- `elonTrashCan.isEmpty()` returns `false` because our internal `items` are empty
- `elonTrashCan.items` has 1 item in it

![Photo by Scott Gummerson on Unsplash](https://dev-to-uploads.s3.amazonaws.com/i/inb6jyfktbdjb5tc70wk.jpeg)
<figcaption>Photo by Scott Gummerson on Unsplash</figcaption>

Using this approach, it is possible to 'limit' the outside world on accessing just the desired interface and has hidden content inside it. On the other hand, JavaScript lets the definition of new properties in runtime execution, even with the same names used by its Closure.

The code inside of the Closure will not depend on those new properties, as the original ones are stored inside that Closure, unaccessible. And, the original mission is now accomplished: **Privacy**. The Module Pattern is viable for attributes and can be used for hiding methods too.

For the side-effect with the creation of new properties, it's hardly suggested not to change the original interface and even make some tests before using those properties like

```js
if(typeof elonTrashCan.items === 'undefined') {
  console.log('No exposed items!') // --> No exposed items!
}
```

## Wrap up

After some discussion about the Object-Oriented Paradigm and the Class implementation of JavaScript, maybe the JS Class is not the best choice for creating Objects with private data if you are not using a transpiler like Babel.

Using **Closures** and the **Module Pattern** it is possible to accomplish **Privacy** in JavaScript in a simple and reusable way. If the `class` implementation is inevitable, consider using a transpiler or a more robust approach with some use of the Module Pattern. The use of transpilers is hardly incouraged!

Even with some apparent losses like `inheritance`, there are still valid ways of implementing that benefits even with **Modules**.


Did I miss something? Is there a thing that you think it's not clear? Feel free to reach me at the comment section or by message and discuss it!

## References

- Cover Photo by [Ciprian Boiciuc](https://unsplash.com/@ciprian?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
- [Article at MDN about Class fields(attributes) options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_fields)
- [Closures in JS and Why It Matters](https://dev.to/caiangums/closures-in-js-and-why-it-matters-pb9)
- [Babel](https://babeljs.io/)
- [GitHub repo with tests](https://github.com/caian-gums/modules-vs-classes-post)