Replacing JavaScript Classes With The Module Design Pattern
Tags: javascript, oop, functional, codequality
Published: 2021-03-02 04:49:47

Hi.  My name is "Adam" and I'm a JavaScript developer.  I've been class-free now, for...  Oh, wait.  I think I'm mixing up my meetings.

My regular readers (both of them) know that I get annoyed by the JS community's irrational fear of the `class` keyword.  Some on here have even told me that I _love_ classes.  That's not actually true, but I understand why some jump to that conclusion.  Because unlike so many other JS devs, I don't start spitting and cursing any time I even _see_ a `class` keyword in code.

But I'm here to tell you that, for some time now, I just haven't written any classes in JavaScript.  At all.  My React code is _all_ function/Hooks-based.  And I'm OK with it.  _Really._  I don't even miss classes.

I'm happy moving along without classes for a few key reasons.  First of all, the `class` keyword is nothing but syntactic sugar in JS.  It doesn't provide _any_ new functionality that you didn't already have in the language.  It just makes some of that functionality... _cleaner_.

What do I mean by "cleaner"?  Well... call me cranky, but I don't ever wanna write more `.prototype`-style objects, where I'm jumping through JS hoops to accomplish that which just _fits_ under a `class` paradigm.  But with "modern" ECMAScript standards, you really don't need to bother with all that `.prototype` stuff anymore.  Specifically, I'm talking about the **Module Design Pattern**.
<br/><br/>


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b128ziv9whtjtc0evk6h.jpg)
## What IS It??
I know this will feel a bit _basic_ for many of you, but first let's define what I mean when I say "Module Design Pattern".  Like most discussions about design patterns, the literal definition of "Module Design Pattern" can be a bit... _fuzzy_.  And quite frankly, trying to come to a hard-and-fast consensus can be extremely _boring_.

Wikipedia defines the module pattern as:

> A design pattern used to implement the concept of software modules, defined by modular programming, in a programming language with incomplete direct support for the concept.

Wow.  That's incredibly... unhelpful.  Impossibly vague.  Pretty much useless.  

So let me show you what _I_ understand to be a "Module Design Pattern", specifically as it applies _to JavaScript_.

```javascript
export const MyModule = () => {
   return {};
};
```

That's... it.  No, _really_.  That's it.  Sure, most real-life examples will have significantly more detail to them.  But the example above actually qualifies.

It's really just a function - that returns an object.  (And yeah - the function could also return an array.  That still qualifies.  In JavaScript, an array _is_ an object.)

You may be thinking that it's just a plain ol' _function_ with some kinda-modern syntax (arrow function) and the modern `export` convention added to it.  And - you'd be right.

You may also notice that I named the module in Pascal-case, which is _not_ part of any standard for the Module Design Pattern.  But I'll explain later why I do that.

If you don't have some sorta ingrained affinity for the code sample above, maybe it's because you're not a React developer??  Lemme explain...
<br/><br/>


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3g2n41qgxfu2qfn7r1p4.jpg)
## React & the Module Design Pattern - A Perfect Partnership
In the horrible, no-good, bad-ol' days, we used to write React components like this:

```javascript
export class MyComponent extends React.Component {
  render() {
    return (
      <div>Here is some JSX</div>
    );
  }
}
```

I hate even having to type that sample.  It's _dirty_ right??  You probably feel kinda ashamed having even _looked_ at it.  And god forbid if you actually _wrote_ that kinda code...  It's the kinda stuff you wanna hide from your future grandkids.  I'm actually sorry that I even showed it to you here.

Thankfully, nowadays we've evolved out of the Dark Ages.  We no longer write shameful stuff like that example above.  Now we write our components like this:

```javascript
export const MyComponent = () => {
  return <>
    <div>Here is some JSX</div>
  </>
}
```

Ohhh, _mannn_!!  Just look at that gorgeous code!  It's _obviously_ so much better!  Thank god we've seen the error of our ways - and repented!  Now we write our _components_ in a way that looks a heckuva lot like... a _Module Design Pattern_.

(NOTE: The above example returns a bit of JSX, and in React we normally refer to this whole block of code as a "component".  But a block of JSX will yield a `typeof`... object.  So when you write a component like the one above, you're really just creating a function - that returns an object.)

And remember when I said that I (usually) write my Module-Design-Pattern functions with Pascal-case?  Well, React components are named in Pascal-case.  And if you look up "component" and "module" in most dictionaries, you'll have a hard time distinguishing the difference between those two terms.

Of course, I don't _always_ use Pascal-casing.  I use traditional Camel-casing when I'm writing... Hooks.  Like this:

```javascript
export const useSomething = () => {
  const [statefulValue, setStatefulValue] = useState('');

  return {
    statefulValue,
  }
}
```

In this case, we're not dealing with JSX, but this still fits perfectly in the Module Design Pattern.  We're exporting a function, which returns values that presumably represent some aspect of its own internal "state".  

In other words, AFAIK, nearly every single custom Hook I've ever seen complies with the (admittedly loose) standards of what comprises the "Module Design Pattern".  For that matter, nearly every functional component in React also meets these standards.

BTW, if you think this is just some snarky takedown of functions-vs-classes, _it's not_.  Because there _are_ some tangible benefits of the Module Design Pattern.  To understand what those are, we need to appreciate how JavaScript treats functions...
<br/><br/>


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2g2iz4r64ofb44fvgo8.jpeg)
## Functions: JavaScript's Magic Boxes
Ima be honest here:  It took me a number of _years_ before I really appreciated this about JS.  In JS, functions are "first class citizens".  What that means, in laymen's terms, is that they can be passed around like a string, or a number, or an object.  In JS (or any other language that features functions as "first class citizens"), the function isn't _a subroutine_, it is _a value in its own right_.

What does that mean with regard to our Module Design Pattern???

Well, take another look at that dead-simple custom Hook above.  It's returning an object.  And that object could contain... basically anything - _including functions_.  In other languages, can you think of something that also can _contain_ functions?? (HINT:  In other languages, those functions are typically called "methods".)

For example, in Java, a _class_ is a template that allows you to create (_instantiate_) objects.  In turn, those objects can contain... basically anything - _including functions (methods)_.

In JS, the `class` is just syntactic sugar.  But what is it syntactic sugar _for_???  Some people assume it's syntactic sugar for an object.  But that's not quite right.  `class` is just syntactic sugar for _a function_ - one that returns an object (which in turn can contain... basically anything).

In fact, if you wanna waste a night diving _deep_ down a JS rabbit hole, try writing a function that will determine whether the argument passed in is a function... _or a class_.  It's... damn-near impossible.  

Why did it take me a while to _truly_ appreciate this?? Well... it's very easy (maybe even _natural_) to look at any given function and assume that it returns some kinda scalar value - a string, a number, ...whatever.  Of course, I always understood that a function could also return objects, but I was still thinking of those objects in terms of scalar values (i.e., an object - that contains strings, or an array - that contains numbers).  

But it may not be immediately apparent to all programmers that, in JS, it's perfectly natural to have a function that:

1. Holds other functions _inside_ that function.
1. Uses some of those functions only for its own internal workings ("private").
1. Returns some of those functions to the caller ("public").

In other words, a JS _function_ can pretty much perform all the operations that other devs, in other languages, call _a class_.  And once you realize the power of JS's functions, you realize that JS's functions _are_ classes - they're just classes in sheep's clothing.

To put this into a different context, I remember when jQuery first gained widespread adoption.  And I'll be completely honest here - I thought it looked absolutely friggin foreign to me at the time.  Because jQuery is basically an entire library that's _built_ on the concept of anonymous functions.  And at that point in my programming life, the idea of an anonymous function just didn't make any damn sense to me.  (Like: _"Why in the world would I want to write a function with NO NAME??  That I can't call again at some point in the future???  THIS FEESL LIKE INSANITY!!!"_)

Even once I got comfortable with jQuery's syntax, I didn't immediately appreciate the extent to which it was highlighting JS's use of functions as first-class citizens.  Ironically, I didn't fully grasp some of jQuery's "lessons" until years after I'd stopped using it.
<br/><br/>


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwcjszsoocld6lzji098.jpg)
## "Self-Aware" Functions
One of the key benefits of OOP objects is that they have a kinda "self-awareness" about them.  No, I don't mean that they're gonna coordinate a counterstrike against humanity, leading to the Rise of the Machines.  I mean that they can reveal things about themselves - and _hide_ things about themselves.  

But you don't need OOP to accomplish this.  And this is where the Module Design Pattern shines.

Consider this example:

```javascript
export class MyClass {
  externalVariable = 'foo';
  internalTrackingVariable = 'bar';

  doExternalProcessing() {
    // function to be called by the instantiator
  }

  doInternalProcessing() {
    // internal helper function
  }
}
const myInstance = new MyClass();
```

In this example, `internalTrackingVariable` and `doInternalProcessing()` seem like prime candidates to be "private".  But `myInstance` has full access to them.  That's... not ideal.

[NOTE 1: There is a proposal - that's not yet finalized - to add private variables to JS classes.  But since it's still just a proposal, I'm not gonna spend any more time thinking about it here.]

[NOTE 2: It's perfectly possible to create "private" variables/methods inside a JS `class`.  It's called a _closure_.  But the syntax required for it is not really... "intuitive" and it doesn't really feel like it's part of the `class` spec in any way.]

Now let's look at the same example with a Module Design Pattern:

```javascript
export const MyModule = () => {
  const externalVariable = 'foo';
  const internalTrackingVariable = 'bar';

  const doExternalProcessing = () => {
    // function to be called by the instantiator
  }

  const doInternalProcessing = () => {
    // internal helper function
  }

  return {
    doExternalProcessing,
    externalVariable,
  }
}
const myInstance = MyModule();
```

In the `class` example, _everything_ is "public", unless we jump through some closure-hoops to ensure it's not so.  But in the module example, _everything_ is private, unless we specifically choose to expose it in the `return` object.  Suddenly, controlling the "self-aware" aspects of the product object feels soooooo much easier.

IMHO, this is a _huge_ argument in favor of the Module Design Pattern.  If the `MyModule` caller tries to access `myInstance.internalTrackingVariable` they'll find that _there is no `internalTrackingVariable` for them to reference_.

This also has huge ramifications if we're trying to control the _data integrity_ of our "class" members.  Specifically, when I'm writing custom Hooks, I frequently employ this type of pattern:

```javascript
export const useSomeHook = () => {
  const [counter, setCounter] = useState(0);

  const updateCounter = (newCounter = 0) => {
    // apply some validation to ensure that newCounter
    // can ONLY be a non-negative integer
    setCounter(newCounter);
  }

  return {
    counter,
    updateCounter,
  }
}
```

See what I did there?  I have a regular-ol' state variable.  And I'm exposing the _value_ in the `return` object.  But I'm not exposing the natural setter.  Instead, I'm only exposing my custom `update` function, which will first ensure we have a "proper" value before setting a new `counter` value.

Of course, you could just expose `setCounter` in the `return` object.  But this would mean that the caller could set the value of `counter` to `-5`.  Or `'zero'`.  Or `'chocolate strawberry banana'`.  By only exposing my custom updater function, I can then ensure that `counter` is only ever set to a "logical" value.
<br/><br/>


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aufkr5vcultcoytqp59s.jpeg)
## Shutting Up The Sycophants
I've laid out some practical reasons why the Module Design Pattern can be useful.  But I'll be honest:  There are also some _personal_ reasons why I've really gravitated toward this pattern over the last year-or-so.  Specifically, it's a fabulous way to shut up the dyed-in-the-wool, mindless, Functional Programming fanboys who can't help but fill their diaper any time they're affronted with that horrible no-good `class` keyword.

Years ago, JS-types would see me using a `class` and they'd cry that I should be mimicking all of their `.prototype` and closure techniques.  And I'd think, "Yeah, umm... nope.  Not gonna be doing that."

Then when I started getting heavy into React, some people would complain that I should be writing more functional components - even though functional components were (at the time) handicapped with far less functionality.  And I'd think, "Yeah, umm... nope.  Not gonna be doing that."

Recently, I've had some people around me even complain that a simple _utility class_ was somehow "wrong" because I had the audacity to deploy the JS `class` keyword.  And I'd think, "Yeah, umm... nope.  Not gonna be doing that."

But recently, I've been converting many of my remaining classes over to a Module Design Pattern.  Because the Module Design Pattern can honestly do _all of the same things_.  And it does it in a way that's syntactically just as elegant as a `class`.  And it does it in a way that undercuts all the whiny complaints of the FP fanboys.  So with that in mind, it's just easier... to switch.

Consider this example:

I have a utility class that I've written about previously.  It's a wrapper for localStorage.  It looks something like this:

```javascript
class Local {
  clear = () => {}

  getItem = itemName => {}

  removeItem = itemName => {}

  setItem = (itemName, itemValue) => {} 
}
export const local = new Local();
```

Honestly???  I think this is a _perfect_ use-case for a `class`.  Nevertheless, I'd get the occasional comment from someone asking why I'd made it a horrible, no-good, unconscionable `class`.  Some of those people _even stated that it seemed like a logical use-case for a `class`_!!!  But that didn't stop them from wondering why I made it... a `class`!

To be frank, those kinda comments used to exasperate me.  I mean, they'd basically _admit_ that it made perfect sense as a `class` - _and then they'd still whine about it being a `class`_!!!

But at this point, I've basically solved this "problem".  I recently turned this into an NPM package.  And when I did, I used this syntax:

```javascript
const Local = () => {
  const clear = () => {}

  const getItem = itemName => {}

  const removeItem = itemName => {}

  const setItem = (itemName, itemValue) => {}

  return {
    clear,
    getItem,
    removeItem,
    setItem,
  }
}
export const local = Local();
```
<br/>
 &nbsp;
> _There!  Are you happy now???_

<br/>
 &nbsp;