The Horror That Is React Native

Introduction

This is my story and experience with React Native development. It is meant to be a bit humorous and maybe a bit of a laying out of grievances as I come to the end of a very long and difficult development cycle for a complex and painful app. As such, there may be some things that are a bit exaggerated, and I’m only speaking for myself. So here goes ūüôā

A close friend of mine came to me with an app idea recently which I finished over the course of the Summer. The idea was decent but not groundbreaking, and I didn’t want to spend too much time on it. With that in mind, I knew I would need something that could bring my web experience into the mobile arena and speed up development. The first such development kit that I was referred to was React Native.

I gave it a quick once over and it appeared to be exactly what I was looking for. It has a quick start that only would take a few lines of code. It had libraries for routing, and if you used Expo, you would get all kinds of goodies like an image picker, natively supported across multiple platforms. Little did I know the deep dark secrets lurking unseen.

Humble Beginnings

To get started, you’re presented with a couple of options. You can either do the quick start, or you can “build projects with native code”. You’d be forgiven for completely missing the second option as I did. And anyways, I chose this library because I don’t want to work with native code, right???

Running their commands as specified seems to do the trick no problem, and off you are.

Getting Real

Well this is all great, but as you start to put together an app, you notice something glaringly absent… any kind of navigation. Obviously, you don’t want to manage this yourself, and you start on your quest for tools.

This is when you start to learn that in React Native, there is an Expo version, a React version, and an open source version of nearly every solution you can encounter.

I personally used the¬†react-navigation¬†package, and I found their example with the stack navigator to work for my purposes. You will find later on that there is no easy way to reset the stack (for instance, when you don’t want someone to navigate back to the login screen). To fix this issue, you’ll have to use StackActions¬†and NavigationActions to set the index back to zero. You’re welcome.

ES6 Confusion

If you’re not used to writing in ES6 JavaScript, then there’a quite a bit to learn. You will definitely learn to appreciate it in the end, but at the beginning it feels like quite the hassle.

For instance, let¬†and const. These are not words you’d be used to seeing in JavaScript, but they are common in React Native. Another example is classes, although these are generally easy to grasp and understand by looking at them.

Classes have to be imported differently depending on whether they are declared default or not, and importing something more than once will give you a meaningless error when you build the code that can take forever to track down.

Promises use an await/async syntax similar to C#.

You can assign the property name and value of an object simultaneously by using a local variable name like this:

let a = 5;
let obj = { a }; // obj has property 'a' with value 5

Oh and when you import JS libraries that are not ES6… well the rules are weird, you’ll want to keep Google handy.

Release Horror

This is more of a small aside, as you’re unlikely to release directly from Expo anyways, but your Expo release builds will be queued up on a remote server, and will generally finish in about 15 minutes if you go the Expo quick start route. This alone made me reconsider the decision to use Expo, as the only useful thing the library gave me was an image picker.

This also requires creating an account with Expo, and if you release from these builds and later detach, you will have to contact Google support to get your publishing certificates updated. Your Expo code is always public, although you can keep it from being searchable. Would be nice if React told us all this up front wouldn’t it?

Detaching Horror

So now you have many months of working hard to put together your app, but it debugs from your PC and all you have to do is make sure your PC and phone are on the same WiFi to test your app. This all seems wonderful and great, and you’re deeply satisfied with your good decision.

However, much like relationships, React Native has hidden her true nature from you until it’s much too late, and it is on the tail end of this journey that you discover her dark secrets, for it is now time to detach.

Detaching is the process of removing your app from the Expo environment dependency, and generating native apps that run your JS code.

Detaching is quite a process, and I had it go wrong a few times before I was able to detach successfully. If you used Expo as in the quick start, then you will need to detach using the Expo documentation and not the React Native documentation, as I figured out rather quickly.

Detaching is where I faced the brunt of my issues.

First, the Google Play libraries did not match the versions given in the imported libraries, which caused all kinds of hard to track down bugs. Next, the builds only worked if I had Expo running, but the build couldn’t complete with Expo started since they accessed the same files, which made starting the JS debugger a chore. Lastly, the generated code for Android was wildly out of date and nearly every library had to be upgraded, gradle had to be upgraded, the build tools had to be upgraded, and the syntax for the gradle files had to be changed.

Everything seemed to be going much better at this point, and I figured my hard work had paid off and I could go back to an easy development cycle. Well, I got some more surprises when I tried to use the payments library I had integrated (react-native-payments).

As it turns out, the main activity code wasn’t handling Intents correctly, and it had to be updated to contain an override that looks like this:


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  ((ReactInstanceManager)(Object)mReactInstanceManager.get()).onActivityResult(this, requestCode, resultCode, data );
}

So much for not writing any native code.

Now the payment module was working as expected, and I turned my eyes to the next task: push notifications. I had been originally handling this through Expo, but as it turns out that’s a complete waste of time, as you really need to use Firebase to get notifications in a production application once you detach.

The library I had moved into its place was react-native-notifications. It seemed to do everything I wanted, even though the documentation was a bit incomplete and confusing, much like react-native-payments.

At first, everything was good, I appeared to be getting the notification tokens and I happily pushed out the changes. This is when it all went wrong.

I noticed that my users weren’t receiving a single notification, even though Firebase was receiving them successfully (Oh, and Google’s terrible push notification documentation is another story).

I couldn’t for the life of me figure out why this was, not in the least because including the notifications library caused my builds to stop working with Expo, so I could no longer debug the application. I had to test full releases only. React Native was also not pushing any of my console.log¬†messages into the android logs, so I could get no hints that way.

This is when I stumbled upon an error in the logs. The notifications library seemed to be expecting my application to be of type ReactApplication¬†but it was instead of type ExpoApplication. Once again, Expo was breaking React through undocumented breaking issues that were incompatible with React. Of course this is React’s fault as well: they shouldn’t recommend using a library that isn’t compatible with the rest of their documentation.

I managed to find an issue on GitHub from someone else who had gone through similar horrors, and happily copied their code. But, it still didn’t work!

As I investigated the issue I found myself deep in the bowels of the React Native code, implementing obscure interfaces and overriding methods whose implementations did not fit well into the Expo model of doing things.

The final code looked something like this, and also required implementing a getReactInstanceManager() method in the main activity:

package host.exp.exponent;


import android.app.Activity;
import android.util.Log;

import com.facebook.react.ReactPackage;

import java.util.Arrays;
import java.util.List;

import expolib_v1.okhttp3.OkHttpClient;
import host.exp.expoview.Exponent;

// Needed for `react-native link`
// import com.facebook.react.ReactApplication;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
import com.reactnativepayments.ReactNativePaymentsPackage;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactInstanceManager;

public class MainApplication extends ExpoApplication implements ReactApplication {

  @Override
  public boolean isDebug() {
    return BuildConfig.DEBUG;
  }

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  // Needed for `react-native link`
  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        // Add your own packages here!
        // TODO: add native modules!

        // Needed for `react-native link`
        // new MainReactPackage(),
        new ReactNativePushNotificationPackage(),
        new ReactNativePaymentsPackage()
    );
  }

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

    @Override
    public ReactInstanceManager getReactInstanceManager(){
      Log.d("ReactNativeHost", "Fetching manager from Exponent (override)");
      Activity activity = Exponent.getInstance().getCurrentActivity();
      if(activity instanceof MainActivity){
        return ((MainActivity)activity).getReactInstanceManager();
      }
      Log.d("ReactNativeHost", "Activity was not main activity");
      return null;
    }

    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
        new ReactNativePushNotificationPackage(),
        new ReactNativePaymentsPackage()
      );
    }
  };

  @Override
  public String gcmSenderId() {
    return getString(R.string.gcm_defaultSenderId);
  }

  @Override
  public boolean shouldUseInternetKernel() {
    return BuildVariantConstants.USE_INTERNET_KERNEL;
  }

  public static OkHttpClient.Builder okHttpClientBuilder(OkHttpClient.Builder builder) {
    // Customize/override OkHttp client here
    return builder;
  }
}

Alas, everything is working, and on I can go, slowly building each change as a new release and pushing the full apk because React Native’s recommended SDK (Expo) is completely incompatible with their own implementations.

Tooling Issues

The above issues are not the only issues I encountered on this long and arduous journey. There were missing files (gradlew.bat, which I had to generate myself), and I had to run an Expo publish (which pushes my code to their servers) before assembling each release. In the end, nearly everything that made using it worthwhile fell to pieces, and I will be spending considerable time removing Expo and bringing my app back to pure React Native, to avoid all the pitfalls of mixing the two SDKs.

Positives

Not everything about React Native and Expo was bad. In fact overall it saved me a lot of time and effort, and will continue to do so. What was truly bad about it was the way React Native encouraged developers to use an SDK (Expo) that is clearly not well-tested with their tools.

Common Language

Having a common language is a huge positive (ES6 JavaScript) and makes life so much easier. I would hate to be writing all of my business logic for both iOS and Android. The extra efforts will be more than worth it when I release on iOS as well.

COmmon Design

That same language is used for the design/styling as well in a very clever CSS-like syntax that allows for similar, though simpler behavior. Designs are done using flex layouts, which generally provide all the behavior you would usually need. Fixed positioning doesn’t always work how you’d expect, but that’s a minor gripe.

Common Assets

There’s no need to have resources for Android and have assets for iOS. You can simply manage your assets from the same directory as your JS code. This is a huge time saver.

Quick Debugging

Up until I had detached, and ran into compatibility issues with Expo and React, debugging was extremely fast and easy. It took seconds to reload a new version and I could check the code as it ran from my browser. This was a huge convenience.

it Works

It’s alive. It does what it’s supposed to. The library itself has no glaring bugs, it’s more the integration with open source code that causes the issues.

Packages

Almost everything you could ever need is supported in some package if it is not a part of the React Native SDK. This makes development very easy, although the documentation for these libraries is not always that good.

Conclusion

Don’t use Expo. Seriously. I can’t imagine why anyone would. You are way better off writing packages for React Native and building things locally than you are shifting your builds onto some server somewhere for the privilege of having an image picker built in.

Yes this means you will have to manage an Android project, but you’re going to have to do that eventually anyways. I can see no real drawback and plenty of benefits to simply skipping the quick start, skipping Expo, and using React Native only.

If you have any comments on this article let me know. I’d be happy to go into more detail on some of the issues I faced, and track down more links for bugs and documentation that I came across.

I’ll also be revising this as time goes on to include more images of some of the issues I faced for illustration.

Bugs

These are just the bugs I could find, there were at least four or five others that came up in the course of development.

https://github.com/expo/expo/issues/2073
https://github.com/naoufal/react-native-payments/issues/111
https://github.com/zo0r/react-native-push-notification/issues/846
https://github.com/zo0r/react-native-push-notification/issues/845

Links

These are some of the links I used in the course of developing the app, which may show you some of the confusion I came across during development.

https://facebook.github.io/react-native/docs/getting-started.html
https://facebook.github.io/react-native/docs/navigation

Using JavaScript Web Workers for Asynchronous Tasks

Intro

JavaScript’s concurrency model until recently has been non-existent. Asynchronous calls like AJAX or event handlers are actually scheduled along a single execution thread, with each event waiting its turn. This is very useful in the browser, where you want to be absolutely sure that you are not manipulating the DOM in a haphazard fashion. UI developers don’t want to have to worry about locking resources, but would rather focus on the end result in the UI.

But what about when you do want to worry about concurrency? What about when you would really like to offload some long running process to your front-end, without having to interrupt the UI thread? What do you do when moving your code to the server and using some signaling method is inconvenient or completely impossible?

Lucky for us modern developers, JavaScript does now provide a solution. WebWorkers are genuinely concurrent thread objects that do not interrupt the UI thread. These objects create OS threads in the background, and can therefore take advantage of multiple cores and other hardware optimizations. This is what we’ll be looking at today.

Creating a Script

WebWorkers take a single JavaScript file and execute it in their own thread and execution context (i.e., self is not the window). This means that the first step is to write the script that you would like to run concurrently.

For this example, we will use a computationally intensive but simple task: number factorization. We’ll use a very basic algorithm since factoring numbers is not the point of this article.

Here is that script. You can call this worker.js.

var percentage = 0;
var factors = [];

// respond to messages from the main thread
self.onmessage = function(e) {
    percentage = 0;
    factors = [];
    findAllFactors(e.data);
};

// loop through all possible prime factors (we'll find non-prime factors as well)
function findAllFactors(num){
    // largest possible prime factor in square root of number
    var max = Math.sqrt(num);
    for(var i = 2; i < max; ++i){
        // our percent complete will be the number of numbers we've
        // checked out fo the total possible numbers
        percentage = Math.ceil((i / max) * 100);
        // this number divides num, so add it to the list
        if(num % i === 0){
            factors.push(i);
        }
        // this number either divides num, or we're done checking, so
        // signal the main thread with our status
        if(num % i === 0 || percentage === 100){
            // post back the list of factors, and our completion percentage
            self.postMessage({
                percentage: percentage,
                factors: factors
            });
        }
    }
}

This script simply takes a number (passed to the worker) and factors it by iterating through all the possible numbers. When it finds a number, it messages the main thread to let it know.

self in a web worker script refers to the worker itself. So by setting onmessage, we are telling the web worker to respond to any messages by factoring the given number.

postMessage does just the opposite. This method sends a message back to the main thread, allowing it to respond to any changes. We do this because the worker itself cannot access the DOM, and if it could, the DOM updates would not occur until after execution had completed, like any other script.

Creating the Main Thread Script

We’ll need a script to create the web worker, and respond to updates. This script will look like the script below.

(function(window, undefined){
    window.loadingIndicator = {
        // 720,720 is a highly composite number (lots of factors, perfect for this example)
        number: 720720 * 720720 * 720720,
        ui: { // our important DOM nodes
            loadingBar: null,
            button: null,
            factors: null
        },
        // our web worker instance
        worker: null,
        // call this from the page
        init: function(){
            this.bindEvents();
        },
        // bind document events
        bindEvents: function(){
            var self = this;
            document.addEventListener('DOMContentLoaded', function(){
                self.setUiElements();
                // bind click event for our button
                self.ui.button.addEventListener('click', self.buttonClicked.bind(self));
                // create the worker
                self.worker = self.createLoadingThread();
            });
        },
        // when we click the button, this adds a span, helping
        // demonstrate the 'non-blocking'ness of the worker
        buttonClicked: function(){
            var span = document.createElement('span');
            var br = document.createElement('br');
            span.innerHTML = 'You clicked me!';
            this.ui.button.parentNode.append(br);
            this.ui.button.parentNode.append(span);
        },
        // set our ui map to nodes
        setUiElements: function(){
            this.ui.loadingBar = document.getElementsByClassName('loading-bar-value')[0];
            this.ui.button = document.getElementsByTagName('button')[0];
            this.ui.factors = document.getElementById('factors');
        },
        // create our worker
        createLoadingThread: function(){
            var worker = new Worker('worker.js');
            worker.onmessage = this.respondToUpdate.bind(this);
            // send worker number to factor
            worker.postMessage(this.number);
            return worker;
        },
        //respond to messages from the worker (new factor found)
        respondToUpdate: function(event){
            // set width to percentage of completion
            this.ui.loadingBar.style.width = String(event.data.percentage) + '%';
            // loading completed
            if(event.data.percentage >= 100){
                this.completed(event);
            }
        },
        // clean up when worker is done
        completed: function(event){
            this.worker.terminate();
            // remove other elements except indicator
            this.ui.button.parentNode.removeChild(this.ui.button);
            // removing shifts entire list up, so we can just keep
            // removing the first element
            var spans = document.getElementsByTagName('span');                
            while(spans.length){
                spans[0].parentNode.removeChild(spans[0]);
            }
            var brs = document.getElementsByTagName('br');
            while(brs.length){
                brs[0].parentNode.removeChild(brs[0]);
            }
            this.ui.factors.innerHTML = 'Factors of ' + 
                this.number + ': ' + 
                event.data.factors.join(', ');
        }
    };
})(window, undefined);

Let’s look at the createLoadingThread method, since this is the most important thing going on here.

On the first line, it creates a web worker, passing it the name of the script we created earlier. Next, it sets the onmessage handler of the web worker to our respondToUpdate method. Don’t confuse this with onmessage in our worker.js file. This onmessage responds only to messages posted from the worker we create to the main thread. This respondToUpdate method in turn updates our loading indicator. When the task has completed, we call the completed method, which calls terminate on the worker.

Lastly, we post a single message to the worker that we created, passing it the number that we want to factor. This will trigger the onmessage handler of the worker, causing it to factor the number and begin posting messages back to our main thread.

Creating a Page

Of course, none of this can execute without a page to run in. The HTML for this example is below.

<!DOCTYPE HTML>
<html>
    <head>
        <style>
            .loading-bar-container {
                width: 200px;
                height: 25px;
                border: 1px solid lightgrey;
            }
            .loading-bar-value {
                background-color: green;
                height: 100%;
                width: 0%;
            }
            button {
                margin-top: 5px;
            }
        </style>
    </head>
    <body>
        <div class="loading-bar-container">
            <div class="loading-bar-value" />
        </div>
        <div id="factors"></div>
        <button>Click me, I still work!</button>
        <script src="main.js"></script>
        <script>
            window.loadingIndicator.init();
        </script>
    </body>
</html>

Putting it All Together

Great! So now we’ve got our worker script, and our script for the main thread. We also have a page to run all of this.

However, that’s not the end of it. In order to run this example without any error message, you will have to set this up under a running web server. Without the web server hosting the page, Chrome and other browsers may throw exceptions because there is no “host”.

Assuming the above is set up, here’s what the page will look like. To test the page, click on the button we created. You’ll notice that the UI is not being interrupted by our factorization. A message is appended for every button click, while the factorization algorithm runs in the background. The loading indicator continues to update as the factorization continues to run.

WebWorker Loading Bar
WebWorker Loading
WebWorker Finished
WebWorker Finished

Conclusion

WebWorkers provide a very simple but very useful API. They provide a clear benefit by allowing you to run computationally intensive tasks without blocking the UI. This leads to a much better user experience, and to much more interactive pages.

The factorization process above can be any long-running calculation that is slowing down your application. Rather than forcing the user to wait, simply put your long-running task into its own script, create a web worker, and respond to its messages until it is completed.

This is a much better user experience than having the UI blocked by some long calculation, so it’s well worth the relatively small effort required to make the change.

If long-running computations are significantly impacting your user’s UI experience, WebWorkers are a great solution, and relatively easy to implement.

Design Patterns in JavaScript ‚ÄĒ Revisited

Intro

My original post on this subject did not dive deep into true “design patterns” but rather on basic inheritance in JavaScript. Since inheritance can be done in multiple ways in JavaScript, how you choose to inherit is itself a design pattern.

This particular article will look into implementing common OOP design patterns in JavaScript, without violating the principles of those designs. Many online examples of design patterns in JavaScript violate these principles. For instance, many versions of the Singleton pattern are not inheritable, which defeats the purpose of the Singleton. And oftentimes, you can also create instances of them. This article assumes you already know these patterns and why they are used, and simply want to see their implementation in JavaScript.

JavaScript is an interesting language. It is itself based on a design pattern: prototypes. Prototypes are speed-conserving but memory-using instances of objects that define initial values for much of the object definition. This is exactly analogous to setting prototype properties on a new object in JavaScript.

Now this naturally leads to some limitations, which can become readily apparent in the implementations below. If you’d like to contribute to a library that tries to escape some of these limitations, you can contribute to ClassJS on GitHub. (Disclaimer: It’s my project).

I suggest you run all of these examples online as you read through.

Anyways, let’s get down to business. Here are the 10 common design patterns we will go over:

  1. Singleton
  2. Abstract Factory
  3. Object Pool
  4. Adapter
  5. Bridge
  6. Decorator
  7. Chain of responsibility
  8. Memento
  9. Observer
  10. Visitor

Singleton

Now, it’s easy enough to get something in JavaScript that¬†looks¬†like a Singleton. But I’ll show you how to write something that actually¬†behaves like one. I.e.:

  1. You cannot instantiate it
  2. It holds one single read-only instance of itself
  3. You can inherit from it

Nearly all implementations you’ll find miss out on one of these points, especially 1 or¬†3. To accomplish these in JavaScript, you’ll need to hide the instance in a closure, and throw an exception when the constructor is called from external code. Here’s how that works:

var Singleton = (function(){
	var current = {};
    
	function Singleton(){
   		if(this.caller !== this.getCurrent && this.caller !== this.copyPrototype){
        	throw 'Cannot instantiate singleton';
    	}
	}
    
  Singleton.prototype.sayHello = function(){
    	console.log('hi');
	};

	Singleton.getCurrent = function(){
  		// current is dictionary of type to instance
      // new this() creates new instance of calling prototype
    	current[this] = (current[this] || new this());
      return current[this];
	};

	// we have to relax the rules here a bit to allow inheritance
  // without modifying the original protoype
	Singleton.prototype.copyPrototype = function(){
    	return new this.constructor();
  };

	return Singleton;
})();


function SpecialSingleton(){
  // ensure calling from accepted methods
	Singleton.call(SpecialSingleton);
}

// copy prototype for inheritance
SpecialSingleton.prototype = Singleton.getCurrent().copyPrototype();

SpecialSingleton.getCurrent = Singleton.getCurrent;

SpecialSingleton.prototype.sayHelloAgain = function(){
	console.log('Hi again');
};

var singleton = SpecialSingleton.getCurrent();
// base class method
singleton.sayHello();
// derived method
singleton.sayHelloAgain();

// throws error
var special = new SpecialSingleton();

Notice that we also define a copyPrototype method. This is necessary so that the shared prototype does not get altered when we create other sub-classes. We could also serialize and deserialize the prototype with a special JSON reviver that handles functions, but that would make the explanation harder to follow.

Abstract Factory

A closely related pattern of course, is the Abstract Factory, which itself is generally a Singleton. One thing to note here is that we do not enforce the type that is returned. This is enforced at runtime as an error will be thrown if you call a method that does not exist.

//  Singleton from above

// create base prototype to make instances of
function Thing(){
}

Thing.prototype.doSomething = function(){
    console.log('doing something!');
};

// create derived prototype to make instances of
function OtherThing(){
}

// inherit thing prototype
OtherThing.prototype = new Thing();
// override doSomething method
OtherThing.prototype.doSomething = function(){
    console.log('doing another thing!');
};

function ThingFactory(){
    Singleton.call(ThingFactory);
}

ThingFactory.prototype = Singleton.getCurrent().copyPrototype();

ThingFactory.getCurrent = Singleton.getCurrent;

ThingFactory.prototype.makeThing = function(){
    return new Thing();
};

function OtherThingFactory(){
    Singleton.call(OtherThingFactory);
}

// need to use instance or prototype of original is overridden
OtherThingFactory.prototype = ThingFactory.getCurrent().copyPrototype();

OtherThingFactory.getCurrent = ThingFactory.getCurrent;

OtherThingFactory.prototype.makeThing = function(){
    return new OtherThing();
};

var things = [];
for(var i = 0; i < 10; ++i){
    var thing = ThingFactory.getCurrent().makeThing();
    things.push(thing);
}

for(var i = 0; i < 10; ++i){
    var thing = OtherThingFactory.getCurrent().makeThing();
    things.push(thing);
}

// logs 'doing something!' ten times, then 'doing something else!' ten times
things.forEach(function(thing){ thing.doSomething(); });

Object Pool

Our resource pool in this case is also a singleton. When a resource is requested and there are not enough to meet the demand, an exception is thrown back to the client, who is expected to then release a resource before calling again.

// ... singleton from first example

function Resource(){
}

Resource.prototype.doUsefulThing = function(){
	console.log('I\'m useful!');
};

var ResourcePool = (function(){
	var resources = [];
  var maxResources = Infinity;
  
  function ResourcePool(){
    // ensure calling from accepted methods
    Singleton.call(ResourcePool);
  }

  // copy prototype for inheritance
  ResourcePool.prototype = Singleton.getCurrent().copyPrototype();

  ResourcePool.getCurrent = Singleton.getCurrent;

  ResourcePool.prototype.getResource = function(){
    if(resources.length >= maxResources){
    	throw 'Not enough resource to meet demand, please wait for a resource to be released';
    }
    var resource = new Resource();
    resources.push(resource);
    return resource;
  };

  ResourcePool.prototype.releaseResource = function(resource){
    resources = resources.filter(function(r){
    	return r !== resource;
    });
  };
  
  ResourcePool.prototype.setMaxResources = function(max){
  	maxResources = max;
  };

  return ResourcePool;
})();

function NeedsResources(){
}

NeedsResources.prototype.doThingThatRequiresResources = function(){
	var lastResource;
  for(var i = 0; i < 11; ++i){
  	try{
         lastResource = ResourcePool.getCurrent().getResource();
         lastResource.doUsefulThing();
    }catch(e){
    	// requested too many resources, let's release one and try again
      ResourcePool.getCurrent().releaseResource(lastResource);
      ResourcePool.getCurrent().getResource().doUsefulThing();
    }
  }
};

ResourcePool.getCurrent().setMaxResources(10);

var needsResources = new NeedsResources();
needsResources.doThingThatRequiresResources();

Adapter

Our adapter is rather simple. We only interface with the modern door, but when we tell that door to open, it interfaces with the ancient door, without us having to understand the underlying implementation.

function AncientDoorway(){

}

AncientDoorway.prototype.boltSet = true;
AncientDoorway.prototype.counterWeightSet = true;
AncientDoorway.prototype.pulleyInactive = true;

AncientDoorway.prototype.removeBolt = function(){
	this.boltSet = false;
};

AncientDoorway.prototype.releaseCounterWeight = function(){
	this.counterWeightSet = false;
};

AncientDoorway.prototype.engagePulley = function(){
	this.pulleyInactive = false;
};

function DoorwayAdapter(){
	this.ancientDoorway = new AncientDoorway();
}

DoorwayAdapter.prototype.open = function(){
	this.ancientDoorway.removeBolt();
  this.ancientDoorway.releaseCounterWeight();
  this.ancientDoorway.engagePulley();
};

DoorwayAdapter.prototype.isOpen = function(){
	return !(
  	this.ancientDoorway.boltSet || 
    this.ancientDoorway.counterWeightSet || 
    this.ancientDoorway.pulleyInactive
  );
};

var someDoor = new DoorwayAdapter();
// false
console.log(someDoor.isOpen());
// uses ancient interface to open door
someDoor.open();
// true
console.log(someDoor.isOpen());

Bridge

Our bridge object delegates its responsibilities to some other class. The only thing it knows about this class is which methods it supports. At runtime, we can swap out various implementations, which have different behavior in the client class.

function BaseThing(){

}

BaseThing.prototype.MethodA = function(){};
BaseThing.prototype.MethodB = function(){};

// if you wanted this to be truly private, you could check
// calling method, or wrap whole prototype definition in closure
BaseThing.prototype._helper = null;

BaseThing.prototype.setHelper = function(helper){
	if(!(helper instanceof BaseThingHelper)){
  	throw 'Invalid helper type';
  }
	this._helper = helper;
};

function Thing(){

}

Thing.prototype = new BaseThing();

// delegate responsibility to owned object
Thing.prototype.methodA = function(){
	this._helper.firstMethod();
};

Thing.prototype.methodB = function(){
	this._helper.secondMethod();
};

function BaseThingHelper(){

}

BaseThingHelper.prototype.firstMethod = function(){};
BaseThingHelper.prototype.secondMethod = function(){};


function ThingHelper(){

}

ThingHelper.prototype = new BaseThingHelper();

ThingHelper.prototype.firstMethod = function(){
	console.log('calling first');
};
ThingHelper.prototype.secondMethod = function(){
	console.log('calling second');
};

function OtherThingHelper(){

}

OtherThingHelper.prototype = new BaseThingHelper();

OtherThingHelper.prototype.firstMethod = function(){
	console.log('calling other first');
};
OtherThingHelper.prototype.secondMethod = function(){
	console.log('calling other second');
};

var thing = new Thing();
// set helper for bridge to use
thing.setHelper(new ThingHelper());

thing.methodA();
thing.methodB();
// swap implementation
thing.setHelper(new OtherThingHelper());

thing.methodA();
thing.methodB();

Decorator

Our decorator prototypes delegate responsibility to their base classes, while adding additional functionality. They are instantiated by passing an object of the same type for them to wrap. When the calls propagate all the way to the base class, the original wrapped object’s method is called.

// LCD prototype
function BaseThing(){}

BaseThing.prototype.doSomething = function(){};

// implementation (client code)
function Thing(){}

Thing.prototype = new BaseThing();
Thing.prototype.doSomething = function(){};

// wrapper classes for decoration
function ThingWrapper(wrappedObject){
	if(!wrappedObject){
  	return;
  }
	if(!(wrappedObject instanceof BaseThing)){
  	throw 'Invalid wrapped prototype type';
  }
	this._wrappedObject = wrappedObject;
}

ThingWrapper._wrappedObject = null;
ThingWrapper.prototype = new Thing();
ThingWrapper.prototype.doSomething = function(){
	// delegate to wrapped class
  this._wrappedObject.doSomething();
};

function CoolThing(wrappedObject){
	ThingWrapper.call(this, wrappedObject);
}

CoolThing.prototype = new ThingWrapper();
CoolThing.prototype.doSomething = function(){
	ThingWrapper.prototype.doSomething.call(this);
	console.log('doing something cool!');
};

function AwesomeThing(wrappedObject){
	ThingWrapper.call(this, wrappedObject);
}

AwesomeThing.prototype = new ThingWrapper();
AwesomeThing.prototype.doSomething = function(){
	ThingWrapper.prototype.doSomething.call(this);
  console.log('doing something awesome!');
};

var wrappedThing = new AwesomeThing(new CoolThing(new Thing()));
wrappedThing.doSomething();

var x = new ThingWrapper();

Chain of Responsibility

With chain of responsibility, various handlers are created for different events. Multiple handlers can handle multiple events, and multiple handlers may exist for the same event. All handlers keep a reference to the next handler, and handlers delegate their responsibility to the base class if they cannot handle an event. In this case, the base class will then ask the next handler to handle the event, and so on. The last handler handles all events, so we don’t have to worry about an event going nowhere and the cycle continuing forever.

var EventTypes = {
	Magic: 0,
	Cool: 1,
  Awesome: 2
};

function Handler(){}

Handler.prototype._nextHandler = null;

Handler.prototype.addHandler = function(handler){
	if(!(handler instanceof Handler)){
  	throw 'Invalid handler type';
  }
  // if it already has a handler, append the handler to the next one
  // this process will propagate to the end of the chain
  if(!this._nextHandler){
		this._nextHandler = handler;
  }else{
  	this._nextHandler.addHandler(handler);
  }
};

// tell the next handler to try to handle the event
Handler.prototype.execute = function(eventType){
	this._nextHandler.execute(eventType);
};

function CoolHandler(){}
CoolHandler.prototype = new Handler();
CoolHandler.prototype.execute = function(eventType){
	if(eventType !== EventTypes.Cool){
  	console.log('delegated uncool event');
        // tell the base handler to pass it to another handler
  	return Handler.prototype.execute.call(this, eventType);
  }
  console.log('handled cool event');
};

function AwesomeHandler(){}
AwesomeHandler.prototype = new Handler();
AwesomeHandler.prototype.execute = function(eventType){
	if(eventType !== EventTypes.Awesome){
  	console.log('delegated non-awesome event');
  	return Handler.prototype.execute.call(this, eventType);
  }
  console.log('handled awesome event');
};

function AnythingHandler(){}
AnythingHandler.prototype = new Handler();
AnythingHandler.prototype.execute = function(eventType){
  console.log('handled any event');
};

var root = new Handler();
root.addHandler(new CoolHandler());
root.addHandler(new AwesomeHandler());
root.addHandler(new AnythingHandler());

root.execute(EventTypes.Cool);
root.execute(EventTypes.Awesome);
root.execute(EventTypes.Magic);

Memento

Memento’s can be very useful in JavaScript, such as when storing the application state in localStorage to be loaded when the session starts again.

In this case, we are simply saving a count variable, and restoring that count when we want. This causes the count to start all over again, before we call increment a few more times.

function Saveable(){
	this._count = 0;
}

Saveable.prototype.save = function(){
	return new SavedState(this._count);
};

Saveable.prototype.restore = function(savedState){
	this._count = savedState.getState();
  console.log('count reset to ' + String(this._count));
};

Saveable.prototype.increment = function(){
	++this._count;
};

Saveable.prototype.logValue = function(){
	console.log(this._count);
};

function SavedState(count){
	this._count = count;
}

SavedState.prototype.getState = function(){
	return this._count;
};

// state manager holds reference to thing that can be saved, and acts on it
function StateManager(){
  this._saveable = new Saveable();
}

StateManager.prototype.getSavedState = function(){
	return this._saveable.save();
};

StateManager.prototype.setSavedState = function(savedState){
	this._saveable.restore(savedState);
};

StateManager.prototype.increment = function(){
	this._saveable.increment();
  this._saveable.logValue();
};

// logs 1,2,3
var stateManager = new StateManager();
for(var i = 0; i < 3; ++i){
	stateManager.increment();
}
// state is now 3
var memento = stateManager.getSavedState();
// logs 4,5,6
for(var i = 0; i < 3; ++i){
	stateManager.increment();
}
// state restored to 3
stateManager.setSavedState(memento);
// logs 4,5,6 again
for(var i = 0; i < 3; ++i){
	stateManager.increment();
}

Observer

Observer is a competing pattern in JavaScript with pub/sub. Pub/sub is oftentimes somewhat easier to implement given the event-driven nature of JavaScript.

Use observer over pub/sub when you want the handlers and subjects to be more closely integrated, when your events flow in one direction, or when you want shared functionality in all observing or observed objects.

function Person(name){
	this._observers = [];
}

Person.prototype.name = '';

Person.prototype.setName = function(name){
	this.name = name;
  this._observers.forEach(function(observer){
  	observer.update();
  });
};

Person.prototype.observe = function(observer){
	this._observers.push(observer);
};

function Observer(subject){
	this._subject = subject;
}

Observer.prototype.update = function(){};

function NameObserver(subject){
	Observer.call(this, subject);
}

NameObserver.prototype = new Observer();

NameObserver.prototype.update = function(){
	console.log('new name: ' + this._subject.name);
};

function NameLengthObserver(subject){
	Observer.call(this, subject);
}

NameLengthObserver.prototype = new Observer();

NameLengthObserver.prototype.update = function(){
	console.log('new length of name: ' + this._subject.name.length);
};

var person = new Person();
person.observe(new NameObserver(person));
person.observe(new NameLengthObserver(person));
// all observers all called for each change
// logs new name, then length of 8
person.setName('deadpool');
// logs new name, then length of 9
person.setName('wolverine');

Visitor

The visitor pattern relies on polymorphism to cause correct handlers to be called. Since JavaScript does not have type-based method signatures, we instead create methods like so: ‘visit’ + elementTypeName, and call these on the visitor classes.

This also means that we need to check that the methods exist, and log or throw an exception when there is no valid handler; and that we need to store the type names of each prototype, since JavaScript provides no easy way to see the most-derived type.

This pattern allows us to handle each element in a list in a different way depending on its type, without having to add various method implementations to each one; and to handle each element in multiple ways depending on what visitor is visiting the element.

function Visitor(){}

Visitor.prototype.visit = function(element){
  if(!(('visit' + element.typeName) in this)){
  	return console.log('No handler for element of type ' + element.typeName);
  }
  // redirect to type-specific visit method
  this[('visit' + element.typeName)](element);
};

function Element(){}

Element.prototype.typeName = 'Element';

Element.prototype.accept = function(visitor){
	visitor.visit(this);
};

function CoolElement(){}

CoolElement.prototype = new Element();
CoolElement.prototype.typeName = 'CoolElement';

function AwesomeElement(){}

AwesomeElement.prototype = new Element();
AwesomeElement.prototype.typeName = 'AwesomeElement';

function CoolAwesomeVisitor(){}

CoolAwesomeVisitor.prototype = new Visitor();

// define type-specific visit methods to be called
CoolAwesomeVisitor.prototype.visitCoolElement = function(element){
	console.log('cool awesome visitor visiting cool element');
};

CoolAwesomeVisitor.prototype.visitAwesomeElement = function(element){
	console.log('cool awesome visitor visiting awesome element');
};

function AwesomeVisitor(){}

AwesomeVisitor.prototype = new Visitor();

AwesomeVisitor.prototype.visitAwesomeElement = function(element){
	console.log('awesome visitor visiting awesome element');
};

var visitors = [
	new CoolAwesomeVisitor(),
  new AwesomeVisitor()
];

var elements = [
	new CoolElement(),
  new AwesomeElement()
];

elements.forEach(function(element){
	visitors.forEach(function(visitor){
    element.accept(visitor);
  });
});

Conclusion

So that’s all for patterns now! I think this is the longest post I’ve ever written, and I intend to keep expanding on this as a good resource.

If you want to know more about these patterns in general, and what they’re used for, I highly recommend sourcemaking.

Notes

Oftentimes, you’ll see me wrap a class definition in a module like so:

var Class = (function(){
   var private = {};
   function Class(){}
   Class.prototype.setPrivate = function(value){
       private[this] = value;
   };
   Class.prototype.getPrivate = function(value){
      return private[this];
   };
})();

The reason for this is fairly intuitive. In JS, you have to choose between two things: inheritance, and data hiding. You can’t have something akin to a private variable inherited by sub-classes. I’ll show you two common patterns that illustrate this.

function Class(){
    var private;
    this.setPrivate = function(value){
        private = value;
    };
    this.getPrivate = function(value){
        return private;
    };
}

Well… the variable is private. However, those getters and setters won’t be inherited, because they’re not on the prototype. You can technically solve this by calling the parent constructor with the sub-class as the caller, but I prefer the pattern I use.

The other possibility is this:

function Class(){}

Class._private = null;
this.setPrivate = function(value){
    this._private = value;
};
this.getPrivate = function(value){
    return this._private;
};

This is a little better is some ways, and worse in others. Our data is no longer hidden, and we’re relying on the developer, and naming convention to deter programmers from accessing it. The properties will be inherited from the prototype, however.

Because of the reasons above, I tend to use the first pattern as a best practice, but depending on the situation any one of these may work fine.

OOP in JavaScript

Intro


In this article I will introduce you to some common design patterns in JavaScript, including patterns commonly seen in OOP languages, with some compare and contrast after each explanation when useful.

Background


There’s a common thread in the programming community that JavaScript isn’t a¬†real language. After all, it doesn’t appear to support inheritance, data protection, or any of the other things programmers are used to seeing in modern programming languages.

It’s my opinion that this is a fallacy. I believe that people are so used to the “way things are done” that college courses teach you, that they simply reject the “new way” without giving it a chance. JavaScript is that new way, and it’s capable of nearly all the things that OOP languages are.

I will show you how to do those things and more in this post.

Basic Inheritance


In JavaScript, the concept of inheritance is implemented through the idea of shared “prototypes”. A prototype is exactly what it says. This is our definition of our object and what we believe it should do.

The prototype is set via the prototype property of an object, as such:

function Thing(){
}

Thing.prototype.doSomething = function(){
  console.log('I\'m doing something!');
};

If you’re new to JavaScript, your first question might be why a function has properties in the first place. In JavaScript everything is an object ‚ÄĒ ’nuff said.

Now, what does this have to do with inheritance? Well, if we want object SubThing to do something that object Thing already does, then we should say that Thing is SubThing’s prototype, based on what we said above. This is how we do that:

function SubThing(){
}

SubThing.prototype = new Thing();

This is basic inheritance in JavaScript. It works because the new keyword calls the function definition that follows it, then returns an object with a hidden [[prototype]] property based on the visible prototype property that we set.

Creating Instances in JavaScript


Creating instances in JavaScript is done in much the same way as any other language, but someone coming from a more classic OOP language may not understand where exactly the object to instantiate is here.

Any function definition can be used with the new keyword in JavaScript to initialize an object. Using one of our function definitions above, that would look like this:

var subThing = new SubThing();

As stated above, what this really does is create an object with a hidden [[protoype]] property based on the prototype we defined (in this case inherited from Thing).

Accessing Properties of an Object


So far, we’ve explained what a prototype is, and how to define properties on this prototype, but we haven’t actually shown how these properties are eventually used.

Any property access, specified with the dot operator (obj.property) or dictionary syntax (obj[‘property’]), will begin by looking at the objects direct properties, and then begin crawling up the¬†prototype chain.

This protoype chain is the hidden [[prototype]] property set on the object we instantiated when using the new keyword.

It is called a chain, because it will check the current object’s prototype, then any inherited prototypes, in the order they were inherited.

As an example suppose we redefined SubThing this way:

function SubThing(){
}

SubThing.prototype = new Thing();
SubThing.prototype.doSomethingElse = function(){
  console.log('I\'m doing something else!');
};

var subThing = new SubThing();

Calling subThing.doSomethingElse() will call the method above, as the instance has the hidden [[prototype]] property we talked about before, created using new.

What does calling subThing.doSomething() do? It first looks at subThing’s prototype. Finding no property with this name, it looks for inherited prototypes. It will find the inherited Thing protoype and call the appropriate method. This is the final step in JavaScript inheritance.

Of course, inheritance of properties is only one aspect of OOP. Following is methods for implementing other common patterns.

Instance Properties


This section only exists to distinguish between static and instance properties in JavaScript. Inheriting instance properties works in exactly the same way as inheriting methods. Anything placed on the prototype essentially becomes treated as a direct property of any instances.

Static Properties


To create a static property, you simply add a property to the function definition itself. This property will be the same for all instances. This works because everything, even functions, are objects in JavaScript.

function Thing(){
}

Thing.property = 'STATIC! :D';

console.log(Thing.property); // logs 'STATIC! :D'

Unlike some OOP languages, however, the property must always be accessed and set on the function (class) itself. It’s instances do not have access to the property.

Private Data


Private variables are implemented as variables which are initialized in the constructor of the function (class definition).

These variables are scoped to the constructor and can only be accessed within the constructor.

Methods which will access private data are created inside the same constructor.

function Thing(){
  var private = "private";
  // this refers to the instance in this case
  this.setPrivate = function(value){
    private = value;
  };
  this.getPrivate = function(){
    return private;
  };
}

var thing = new Thing(); // calls constructor
console.log(thing.getPrivate()); // logs "private"
thing.setPrivate("exposed!");
console.log(thing.getPrivate()); // logs "exposed!";

Public Data


Public data is any data either declared as part of the prototype, or added to the instance during the constructor call.

function Thing(){
  this.public = "I'm public!";
}

var thing = new Thing();
console.log(thing.public); // Logs "I'm public!"

function Thing(){
}

Thing.prototype.public = "Me too!";

var thing = new Thing();
console.log(thing.public); // Logs "Me too!"

Bonus: Static Inheritance


Here’s something you can’t do in most classical OOP languages: static inheritance.

function Thing(){
}

Thing.static = "I'm static!";

function SubThing(){
}

SubThing.static = Thing.static;

It’s really that simple!

For methods, you can use the following pattern:

function Thing(){
}

Thing.static = "hi";

Thing.staticMethod = function(){
  // 'this' refers to the caller
  console.log(this.static);
};

Thing.staticMethod(); // logs "hi"

function SubThing(){
}

SubThing.static = "hi again!";

SubThing.staticMethod = Thing.staticMethod;

SubThing.staticMethod(); // logs "hi again!"

The reason this works is that “this” refers to the caller in JavaScript, so it uses the “static” property of the current caller, which is Thing, then SubThing, respectively.

Conclusion


Thanks for reading! Hope this helps anyone interested in writing maintainable code in JavaScript, and even more so that it helps people get rid of the mindset that JavaScript isn’t a “real” language and finally start treating it like one instead of writing spaghetti code!

I tried to write this all to work as-is, but please let me know if you find any errors.