Is Ethereum Dying?

Or is it already dead?

The once-promising blockchain and beloved smart contract project seemed to be at the top of the world. From a high of $1431 in January 2018 to its current low of $126, it seems whatever hopes people have for Ethereum have faded quite a bit.

Despite the fact that Ethereum still holds the number two spot on Coin Market Cap Ethereum has fallen out of the limelight somewhat with developers. On State of The DApps, Ethereum accounts for only three of the top ten applications. Klaytn accounts for four of them, Steem accounts for two and NEO just one. In the top five, Ethereum only has one DApp.

Vanity metrics aside, given Ethereum was one of the first smart contract platforms and holds the coveted #2 spot, you would expect more popular applications to be using it. However, over the last two or so years, many projects and exchanges have moved away from Ethereum to their own solutions.

Ethereum used to be ICO blockchain. Almost every ICO in 2017 was an ERC20 token. Fast forward to 2019 and the projects that are still alive, quite a few of them have moved away from Ethereum. Crypto.com (formerly known as Monaco Card) previously used Ethereum, until they created their own blockchain called Crypto.com Chain (CRO). In early 2019, Binance famously ditched Ethereum for their own solution as well Binance Chain.

Tron and EOS are also two other blockchains which received their funding through Ethereum and then subsequently created their own competing blockchain. It seems Ethereum has become the gateway to other blockchains.

One of Ethereum’s biggest problems is that it has serious scaling issues. I am sure you all remember CryptoKitties which famously crippled Ethereum a couple of years ago. It also turns out that Tether may also be to blame for Ethereum’s high network usage and problems.

Having said that, many blockchains have the same scaling problems. Bitcoin is also quite full, EOS recently experienced some serious problems with their network as well.

While the anticipated Ethereum 2.0 release will alleviate some of the problems by moving away from proof-of-work to proof-of-stake, nobody can agree on anything. There has been a tonne of infighting within the Ethereum team and associated entities contributing to the blockchain.

Allegedly the first upgrade will be happening in January 2020, but given the turbulence, Ethereum has experienced with nobody seemingly able to agree on anything, I would actually be surprised if that happens. People are afraid of Ethereum 2.0 and the changes being proposed.

Even one of the co-founders of Ethereum recently sold off 90,000 ETH worth $11 million US dollars. Another nail in the coffin of an already fractured and turbulent cryptocurrency project.

Given Ethereum was one of the first general-purpose smart contract blockchains, perhaps it was inevitable that it would eventually lose some of its popularity in favour of other more modern solutions who have the luxury of beginning from scratch without having to worry about an entire legacy ecosystem built around them.

I don’t think Ethereum will truly die, but there are so many better options out there now ranging from Steem to EOS, to Stellar, Tron and Klaytn that make Ethereum look antiquated and clunky. Ethereum is no longer the first choice that comes to mind for many DApp developers.

Select Change Event Not Firing When Using Characters On Keyboard

Here is a nice bug-not-bug to close out in 2019. One of my Trello cards detailed what sounded like an error:

When toggling between two options (yes and no) in a dropdown, entering “y” changes to yes and quickly entering “n” does not switch to no. However, waiting a second you can change between them.

Some initial debugging suggested this was not actually a bug in our application. But, I knew if I was going to get the ticket closed off as not a bug, I had to have an explanation.

It turns out that browsers (well at least in Chrome and Firefox) select dropdowns are searchable by offering a delay allowing you to type in long values. The way I highlighted this was creating a dropdown with four options:

  • Yes
  • No
  • YNo
  • NYes

To highlight the error I created a JSFiddle demo here. The first dropdown contains the above options. Try pressing “Y” and then “N” quickly after, the selected value will then be “YNo” highlighting the searchability. Similarly, entering “N” followed by “Y” will yield “NYes” selected.

There is also a second dropdown with some years from 1988 to 1993 in the above linked JSFiddle demo. Try selecting the dropdown and then entering 1993 (which is the last option) you will see the searching feature in the browser selects 1993.

So, not a bug, just a browser feature. Admittedly, I didn’t actually know you could search values in a dropdown this way. I usually use my mouse to select values in a dropdown. We have some people on our team who shun the mouse and navigate through our main app using their keyboard.

Quick & Easy Way To Reset Mocks & Spies In Jest

When working with mocks and spies in Jest, it is quite easy to fall into a trap where they become stale (especially in cases where pure functions are not being used). Heading to the documentation for Jest yields a lot of similar-looking methods for restoring mocks, clearing mocks and resetting mocks.

This is where confusion sets in. What is the best practice? Which ones should I call to ensure my tests don’t have stale mocks or spies? Even I struggled with this aspect.

In my Aurelia applications, Jest is my prefered means of test tool. In my trial and error, I have settled on the following in my tests which ensures all mocks and spies are reset between tests being run.

  afterEach(() => {
    jest.resetAllMocks();
    jest.restoreAllMocks();
  });

The jest.resetAllMocks method resets the state of all mocks in use in your tests. It is the equivalent of manually calling mockReset on every mock you have (which can be tedious if you have a lot of them).

The jest.restoreAllMocks method restores all mocks back to their original value, ONLY if you used jest.spyOn to spy on methods and values in your application. It is important that you use spyOn where you possibly can.

Boeing Is Too Big Too Fail

People once thought the banking industry was too big to fail, some seriously big financial institutions ultimately proved that wrong during the Global Financial Crisis of 2008/2009 which saw many seemingly unsinkable companies go out of businesses.

Early 2019, after two deadly crashes of the allegedly bigger and better 737 MAX, the plane was grounded by countries around the world as people scrambled to find answers for what happened. After numerous investigations, the culprit turned out to be MCAS also known by its non-abbreviated mouthful of a name Maneuvering Characteristics Augmentation System.

The issue with the 737 MAX was engineers were tasked with fitting larger and heavier engines under the wing of the plane. The engines had to be moved slightly higher and moved forward, which ultimately caused a dynamically unstable airframe. The solution was MCAS which used a single sensor to determine if the nose of the plane should be pushed down (as a safety measure).

While the 737 MAX continues to collect dust in parking lots and warehouses, Boeing is bleeding money. Just recently, they announced they’re halting production of the MAX (which will only slow, not stop the money bleeding). The solution Boeing has come up with involves comparing data from two AOA (Angle of Attack) sensors and comparing the difference if both sensors cannot agree, the MCAS does not override the plane as detailed here.

The company was hoping to have the 737 MAX recertified by the end of 2019, but this has been pushed back to 2020. Understandably, this entire situation does not just reflect badly on Boeing, but also the FAA who allowed this to happen in the first place.

Too Big, Too Influential

For any other company, two tragedies and a grounding going on for almost a year would be enough to plunge them into bankruptcy and put them out of business. For Boeing, their stock has been affected a bit, but they’re still okay.

Boeing is a company that has been around for over one-hundred years. When it comes to the aerospace industry, you don’t get any bigger than Boeing. Since the ’90s, the presidential fleet of planes consists of two Boeing VC-25’s which are military versions of the workhorse Boeing 747.

In terms of employment size, Boeing is one of the largest American employers. They employ over 150,000 people, many of those work in the US. If Boeing were to go out of business, the US economy would be affected. Not to mention the supply chain Boeing has created rivals even that of a company like Amazon and its supply chain.

Fly on any major airline in most parts of the world and chances are you are flying on a Boeing built plane, most likely a variant of the Boeing 747.

To get an understanding of just how influential Boeing is and its importance to the US, look no further than the fact the CEO of Boeing (Dennis Muilenburg) still has his job (CEO’s have been fired or forced to step down over less) and has not been summoned to Washington to be grilled before the senate over the tragedies and mismanagement of the 737 MAX.

You don’t get any more influential than not being held accountable or even being questioned on why two tragedies in such a short space of time even took place (the 737 MAX tragedies were unprecedented). When the banking industry collapsed, bankers were dragged before congress to be held accountable.

Still Waters Run Deep, Boeing Runs Deeper

When you and I think of Boeing, we think of a company that makes passenger planes. However, Boeing has its fingers in many pies, it’s producing the pies, it’s eating them, it owns the pie factory, it owns the supply chain that is shipping the pies to stores and restaurants.

Not many people realise Boeing also props up other companies and industries. Their subcontracts with General Electric (GE) and United Technologies and Spirit Aerosystems are some of the biggest. You best believe Boeing is adding a few zeroes to the books of those contractors.

Boeing is entrenched in both civilian and military sectors. They sell planes, rockets, satellites, telecommunications equipment and even missiles. They are the largest exporter by dollar value in the US. As far as size is concerned, Boeing is a juggernaut, a core pillar of the aerospace industry.

They are already saying that the halting of the 737 MAX could affect the US’s GDP in 2020. Not many companies can lay claim to being so big they contribute to the overall GDP of a country.

Even if Boeing were to get into serious financial trouble, the US government would not even hesitate to bail them out. It would probably be considered a national security risk if Boeing were to go under given their influence and reach in the defence sector alone. Quite simply, Boeing could sustain many more missteps and accidents before it really affected them and forced the government to step in.

Google Chrome v79 Broke The Ability To Hover Variables In Developer Tools

Well, this is a pretty frustrating bug. The other day I and a few other people in my team noticed something peculiar while debugging some Javascript. The ability to hover over variables and function arguments in Chrome Developer Tools had stopped working.

At first, we thought this might have been a Webpack configuration issue or an update to one or more of our packages breaking the way in which Chrome parses our Javascript. The issue turned out to be Chrome itself. There is an issue recently created where many voice their frustration (myself included) over this bug.

As a developer, the ability to debug is everything. As a result of this simple bug, the time required to debug has increased exponentially.

Fortunately, this bug appears to have been fixed in Chrome Canary Version 81.0.4001.2. Even many of the developers I know do not use Canary because it can at times be unstable or introduce new features that seemingly get removed. So, until an update is released in the next couple of weeks, frustration will ensue for many.

All of this has just motivated me to consider moving back over to Firefox as my primary browser, given Google’s anti-ad stance and now a bug that should not have been introduced, I am driven by frustration.

Crash Course: The Bindable Element In Aurelia 2

In Aurelia 2, a new element called bindable has been introduced which is leveraged in HTML only custom elements. If you want a HTML only custom element which has one or more bindable properties, then you use the bindable element to specify them.

The ability to create bindables for HTML only custom elements existed in Aurelia 1, but was limited. The constraint being the bindable keyword had to be specified on the template element.

<template bindable="user">...</template>

In Aurelia 2, this now becomes something much more simple and clean because template is no longer a requirement for HTML only custom elements.

<bindable name="user" />

Besides the semantics changing, you can now also specify the binding mode for the defined variable. This was not possible in Aurelia 1 when creating HTML custom elements.

Now, simply adding a mode property and valid binding mode value, you can change how the binding works just like you can when configuring the binding mode inside of a view-model.

<bindable name="user" mode="one-way" />

Creating HTML Only Custom Elements In Aurelia 2

If you are already familiar with Aurelia and have worked with Aurelia 1, then HTML custom elements are not a new concept to you. If you’re starting out with Aurelia 2, they might be a new concept to you.

How HTML Only Custom Elements Looked In Aurelia 1

We have a custom element called user-info.html which accepts a user object through a bindable property called user and we display their name and email.

<template bindable="user">
  <p>${user.name}</p>
  <p>${user.email}</p>
</template>

How HTML Only Custom Elements Look In Aurelia 2

The constraint of needing a template tag has been removed in Aurelia 2. It is now automatically handled for you by the framework, so now our HTML components look like this.

<bindable name="user" />

<p>${user.name}</p>
<p>${user.email}</p>

Because there is no template tag, you need to create your bindable properties using the bindable element and the name property to specify what it should be called.

Just like Aurelia 1, the file name itself (in our case it is user-info.html) becomes the name of our HTML tag without the .html file extension. If we called it user-block.html our element would be referenced using that name instead.

Importing & Using It

You created a HTML only custom element in Aurelia, now what? Now, you import the component.

<import from="./components/user-info.html"></import>

<user-info user.bind="user"></user-info>

If you want to follow along with a tutorial for creating a simple weather application in Aurelia which involves creating a HTML only custom element and importing it, I have a weather application tutorial here.

Building A Weather Application With Aurelia 2

While Aurelia 2 is still not quite ready for release, you can use it right now as the basic core pieces are functional. I thought it would be fun to build a weather application using Aurelia 2.

If you don’t want to run through a tutorial and just want the final result, all of the code for the weather application can be found on GitHub here.

What Are We Building?

In this tutorial, we are going to be building an Aurelia 2 application that displays weather information. Original, right? You will learn how to create new Aurelia 2 applications, as well as work with the OpenWeatherMap API where we will consume JSON for the information.

Before we can continue, head over to the OpenWeatherMap website here and create a free account. This application will only be for personal use, so the limits of 60 calls per minute are perfect for us.

You will then want to generate an API key by heading over to the API Keys section once you are signed up and logged in.

A Note On Code In This Tutorial

Aurelia allows you to leverage conventions for things such as custom elements, value converters and whatnot. It also allows you to be more explicit in how you name and import dependencies.

For the purposes of this tutorial post, we will be leveraging conventions, but the code in the repository will leverage no conventions and use decorators for describing components. My personal preference is to be quite explicit in my Aurelia applications.

Getting Started

Unlike Aurelia 1, there is nothing to install globally (the aurelia-cli is not a dependency you need any more). To bootstrap a new Aurelia 2 application, you simply open up a terminal/PowerShell window and run:

npx makes aurelia

Because TypeScript is the future, I recommend choosing the “Default TypeScript Aurelia 2 App” option in the prompt. Then choose, “npm” for the package installer option and wait for your app to be created.

To confirm everything installed correctly, open up the generated application directory (in my case it is weather-app) and then run the application using npm start a browser window should open and point to port 9000.

Create A Weather Service

In an Aurelia application, using singleton service classes is a great habit to get into too. Singletons are easy to test and work well with Aurelia’s dependency injection (DI).

In the src directory create a new folder called services and a file called weather-api.ts which will handle making calls to the OpenWeatherMap API service.

import { HttpClient } from '@aurelia/fetch-client';
import { DOM } from '@aurelia/runtime-html';

const http = new HttpClient(DOM);

export class WeatherApi {
    private apiKey = '';
	private units = 'metric';

    public async getWeather(address) {
        const req = await http.fetch(`https://api.openweathermap.org/data/2.5/forecast?q=${address}&units=this.units&APPID=${this.apiKey}`);

        return req.json();
    }
}

This simple service will allow us to query the API for weather information. But, we are not using TypeScript to its full potential here. Let’s write some interfaces and type the response.

import { HttpClient } from '@aurelia/fetch-client';
import { inject } from 'aurelia';

@inject(HttpClient)
export class WeatherApi {
    private apiKey = '';
    private units = 'metric';

	constructor(private http: HttpClient) {

	}

    public async getWeather(latitude: number, longitude: number): Promise<IWeatherResponse> {
        const req = await this.http.fetch(`https://api.openweathermap.org/data/2.5/forecast?lat=${latitude}&lon=${longitude}&units=${this.units}&APPID=${this.apiKey}`);

        return req.json();
    }
}

interface IWeatherResponse {
    cod: string;
    message: number;
    cnt: number;
    list: IWeatherResponseItem[];
}

interface IWeatherResponseItemWeather {
    id: number;
    main: string;
    description: string;
    icon: string;
}

interface IWeatherResponseItem {
    dt: number;
    main: {
        temp: number;
        feels_like: number;
        temp_min: number;
        temp_max: number;
        pressure: number;
        sea_level: number;
        grnd_level: number;
        humidity: number;
        temp_kf: number;
    };
    weather: IWeatherResponseItemWeather[];
    clouds: {
        all: number;
    };
    wind: {
        speed: number;
        deg: number;
    };
    rain: {
        '3h': number;
    };
    sys: {
        pod: string;
    };
    dt_txt: string;
}

Now, there is one thing I want to point out with the above example. We’re hard-coding the API key into the singleton class, in a real application, you would and should never do this. Anyone who has your API key will be able to make requests and blast through your limits quickly. Never store API keys client-side.

We now have the class we will use to query for weather information. I won’t go into super specifics around markup and whatnot as those things can be seen in the GitHub repository for this tutorial here.

Leveraging Dependency Injection (DI) To Import Our Service

Now that we have our weather API service, we need to include it for use in our application. We will be editing the generated my-app.ts file as part of the Aurelia application creation process.

We want to replace the entirety of our my-app.ts file with the following:

import { WeatherApi } from './services/weather-api';

export class MyApp {
  private weather;

  constructor(private api: WeatherApi) {

  }

  attached() {
    navigator.geolocation.getCurrentPosition((position) => this.success(position), () => this.error());
  }

  async success(position: Position) {
    const latitude  = position.coords.latitude;
    const longitude = position.coords.longitude;

    this.weather = await this.api.getWeather(latitude, longitude);
  }

  error() {

  }
}

Because my-app.ts is a rendered custom element (as can be seen inside of index.ejs we get DI automatically when we use TypeScript. This means we don’t have to use the inject decorator to inject things.

All dependencies get passed through the constructor and using TypeScript with a visibility keyword, they get hoisted onto the class itself for use. It’s a nice touch and one of my favourite things about TypeScript.

The attached method is a lifecycle method that gets called in components once the DOM is ready. This is where you handle interacting with the DOM or calling various API methods. We call the getCurrentPosition method here to request the users latitude and longitude.

The success callback is called via the navigation position callback on success. This is where we get the latitude and longitude values, then we make a call to our injected API class and call the getWeather method.

You might also notice we are using async/await here which allows us to wait for the results of a promise and get the data. We assign the value to the class variable weather which will be referenced in the view template shortly.

Creating A Value Converter For Formatting Dates/Times

We are going to use the date-fns library for working with dates and formatting them. One of the values the weather API returns is a date string which we will parse and then format for display purposes.

You might not have worked with date-fns before, but it is similar to Moment.js which is a heavier and often unnecessary option to go with.

To install date-fns all we need to do is run:

npm install date-fns

In Aurelia, a value converter is exactly what it sounds like. It converts values to something else (either to the view or from the view). In our use case, we only want to convert a value in the view.

For resources, I highly recommend creating a resources directory which exports an array of resources to make global.

Create a file called src/resources/value-converters/date-format.ts and add in the following:

import { valueConverter } from '@aurelia/runtime';
import { format } from 'date-fns';

export class FormatDateValueConverter {
    toView(date): string {
        return date ? format(new Date(date), 'MM/dd/yyyy - h:mm bbbb') : date;
    }
}

Inside of the resources directory create a file called index.ts with the following:

import { FormatDate } from './value-converters/format-date';

export const resources = [
    FormatDate
];

This exports an array of one or more resources. For the purposes of this tutorial, we are only exporting one resource to make global. In a real application, you might have several. If you worked with Aurelia 1, this paradigm will look familiar with you with an array of resources that get globalised. Except, globalResources is no longer a thing.

Inside of src/main.ts we want to import those resources and register them:

import Aurelia from 'aurelia';
import { MyApp } from './my-app';
import { resources } from './resources';

Aurelia
    .register(resources)
    .app(MyApp)
    .start();

The Markup

We now have the basics in place, let’s start with our markup and styling. We are going to use Bootstrap 4 because it has a good grid system and will make styling things easier.

Install and Configure Bootstrap

npm install bootstrap

Before we start adding in any HTML, we need to import the main Bootstrap CSS file into our application.

At the top of src/main.ts add the following import:

import 'bootstrap/dist/css/bootstrap.css';

We now have the styling we need for marking up our columns and aspects of the grid system.

Creating A Weather Component

Breaking your application into components is a great way to create applications. Smaller components are easier to test, they are also easier to maintain and neater.

Inside of the src directory create a new folder called components and create a component called weather-item which we will import and use to display our weather information.

Now, we want to create the HTML file for our custom element: src/components/weather-item.html

<bindable name="data" />

<p><strong>Date:</strong> ${data.dt_txt | formatDate}</p>
<p><strong>Clouds:</strong> ${data.clouds.all}%</p>
<p><strong>Temperature:</strong> ${data.main.temp}&deg;</p>
<p><strong>Feels Like:</strong> ${data.main.feels_like}&deg;</p>
<p><strong>Humidity:</strong> ${data.main.humidity}%</p>

A brief explanation of what is happening here, we just created a HTML only custom element. The bindable element at the top is telling Aurelia that we have a custom element which accepts a bindable property called data which allows data to be passed through.

You will notice below when we import and use our element, we are binding on the data property by specifying data.bind. Inside of our custom element, we reference this bindable value specifically to get pieces of data passed in.

If you have experience working with other frameworks or libraries such as React, you might know of these as “props” in Aurelia they’re bindable properties.

If you want to build custom elements with business logic that extends beyond simple bindables, you will want to consult the documentation on creating custom elements that leverage a view-model (something we do not need to do here).

<import from="./components/weather-item.html"></import>

<div class="container spacer-v">
    <form class="mb-4">
        <h2 class="mb-3">Weather. Whenever.</h2>
    </form>

    <div if.bind="weather && weather.cod === '404'">
        <h3>Error</h3>
        <p>${weather.message}</p>
    </div>

    <div class="row" if.bind="weather && weather.cod !== '404'">
        <div class="col-md-3">
            <div class="row">
                <div class="col-md-3"><img src="http://openweathermap.org/img/wn/${weather.list[0].weather[0].icon}.png"></div>
                <div class="col-md-8">
                    <h3>${weather.city.name}, ${weather.city.country}</h3>
                </div>
            </div>
        </div>
        <div class="col-md-8">
            <div class="row">
                <weather-item data.bind="item" class="col-md-4 mb-3" repeat.for="item of weather.list"></weather-item>
            </div>
        </div>
    </div>
</div>

The first line is simply using the import element to include our component for use in our view. The import element works like a Javascript import, except it can also import HTML files as well as CSS files. If you have experience with Aurelia 1, this is the same element as require.

The rest is standard Aurelia templating, if you’re familiar with Aurelia v1, this will look familiar to you already.

If you’re new to Aurelia, I highly recommend reading the documentation to get a better understanding of how to author Aurelia templates and work with the templating.

To complete the styling, open up my-app.css which is a CSS file included automatically by Aurelia (matching the name of my-app.ts using conventions).

.spacer-v {
    padding-top: 50px;
}

Running The App

Provided you followed all of the steps correctly, to run the application simply type the following in the project directory:

npm start

A browser window should open and you should see an application that requests your current location and shows you the weather. It should look like this.

There are some improvements you could make on your own like a field that allows users to type addresses, a map or more detailed weather information, adding in routing to view specific fine-grain information. This is a quick and basic tutorial showing you how easy it is to build in Aurelia 2.

Learn Javascript First

The front-end space over the last six years or so has really heated up, you could say superheated. As browsers become more powerful, devices continually improved and innovation a constant thing, no language is more popular and widely used than Javascript.

And yet, as learning resources have become more easily accessible and coding boot camps have become a thing, newcomers are being taught to lean on frameworks and libraries straight out of the gate.

This puts some newcomers into an interesting situation. They might have a good grasp of React or Vue, but lack basic fundamental knowledge of the language itself. It is all well and good to rely on a library, but the moment it can’t do something you want to do, you’re stuck.

While React and Vue might seem like safe bets, I can assure you that people said the same things about Knockout, ExtJS, AngularJS, jQuery and a whole list of other frameworks and libraries that have come and gone over the years.

People will tell you things are different these days, maybe they are. But what happens when Hype.js becomes the popular option and you’re forced to learn a new library with limited Javascript knowledge? You get left behind, that’s what happens.

The only constant is Javascript

The common theme here amongst these rising and falling trends when it comes to technology on the front-end is Javascript. While WebAssembly has high hopes of shifting some responsibility from Javascript, it will remain the number one choice for client-side scripting.

As tempting as it might be to learn React Hooks or try Vue 3, the more you rely on a tool and use it as a language crutch, the further you’re falling behind. Learn Javascript and the rest comes naturally.

If you are an experienced developer, you should be learning new frameworks and libraries, leverage your knowledge of Javascript to widen your skillset and pad out your C.V. If you’re a junior who graduates college or a coding boot camp, learn the language first.

Are Classes in Javascript Bad?

Staunch functional proponents will fire up at the mere mention of classes or any form of object-oriented programming. These arguments go way back to before Javascript was even a thing or as popular as it is now.

Let’s clear the air and point out that classes in Javascript are not real classes. They’re often compared to the likes of Java and other languages that promote OOP-style programming, but classes in JS are unlike those implementations. Javascript has prototypes and prototypes are not classes.

When the ES2015 Javascript standard was released (its biggest update ever), a plethora of new and exciting features came with it. New syntax and API’s, in the mix, was classes (sugar over conventional prototypal inheritance). Perhaps the most controversial addition of them all.

Here is the one thing that class opponents forget: classes in Javascript are optional. They’re not being forced on developers, you either use them or you don’t use them. It is really that simple. And yet, the arguments and noise around their inclusion (especially 2015/2016) you would be forgiven for thinking they’re a requirement to program in Javascript.

Inheritance

One of the biggest downsides to object-oriented programming and classes is inheritance. I am a fan of OOP style programming and even I agree that inheritance can be a nightmare and paint you into a corner.

But here is a secret that functional programming proponents don’t want you to know: inheritance is optional.

I use classes in my Aurelia applications and I avoid inheritance whenever possible. If I do use inheritance (which sometimes I do) I will be strict about it and only have one level of inheritance (parent-child relationship). More than one level of inheritance is a recipe for a bad time. I also try and avoid super calls as well.

Not all uses of inheritance are bad, it can be useful when you want to avoid duplicating code between multiple classes. If you’re building a widget-based component UI and your components all share similar implementation details except for a few configuration-specific pieces of data, inheritance works well here.

In many cases, I use classes as structs for modelling specific pieces of data in my applications, for example:

export class UserModel {
    constructor(name, email) {
        this.name = name;
        this.email = email;
    }
}

I actually prefer the aesthetics of a class over a function. I also love how I have to use the new keyword to explicitly create a new instance of my UserModel.

But the argument that you shouldn’t use classes because it is easier to fall into certain traps is nonsense. Javascript is a language full of traps that extend beyond the likes of classes which are quite low on the scale of JS gotchas.

If you are also working with TypeScript, the benefits of classes are even better when you throw collections and generics into the mix. The development experience just makes sense. I let the TypeScript compiler decide if my classes should be transpiled to functions, prototypes or classes.

I’ve read quite a lot on the subject of OOP and the main argument always seems to boil down to inheritance, followed by personal preference.

Composition <> Inheritance

Whenever the classes vs functions debate arise, people take sides and stances on one side or the other. The truth is you should not and do not have to choose a side, you can use both.

You can still use classes where they make sense and in other parts, use functions where they make sense. Sometimes you just need simple functions and other times, you might like the semantics of a class for organising your code.

If you are implementing a feature/writing code and a function feels appropriate, write a function. If a class feels more appropriate, use a class instead.

Web Components

If you head over to the Google fundamentals for creating custom elements or Mozilla MDN in Web Components, surprise surprise you will find classes are what you use to author custom elements.

Sure, you could just directly write the prototype chain yourself, but it’s going to result in ugly code that is just painful to maintain. The sweet syrupy abstraction that classes provide here is immediately obvious from an aesthetics perspective.

I think classes make a lot of sense when creating custom elements. You’re extending the inbuilt element type and creating your own variant of it. One of the things that classes do well.

Frameworks + First-Class Citizens

Angular and Aurelia are two fully-featured front-end frameworks that have leveraged Javascript classes since the beginning in 2015. I have quite a few Aurelia applications in production, all leveraging classes, sprinkled with a function or two.

The rewrite of Angular (Angular 2+) also treats classes as a first-class citizen. While React might be the most popular option out there, in the enterprise and government sectors, Angular is the king. A lot of Australian government agency applications are built using Angular.

I have not seen or heard of any developer, agency or company running into any kind of problem as a result of classes being a requirement to build Aurelia or Angular applications. If you have, I would love to know.

In instances where classes cause problems, it is because the developer using them is to blame. A bad mechanic blames their tools.

Ignore The Noise, Form Your Own Opinions

I don’t pretend to have all of the answers or be the worlds greatest coder, but I know what works for me based on my years of experience. Be wary of anyone who argues there is only one right way to develop in Javascript because there isn’t.

There are quite a few prominent figures in the JS community who will vehemently argue against classes. They will tell you they have seen companies lose millions, go bankrupt and projects completely scrapped because of classes.

Most of the anti-class crowd have an agenda. You will discover the common thread amongst most anti-class dev-influencers is they’re selling training courses and other material. They will tell you there is only one way to do something and to signup for their “Right Way of Doing Things” course for developers.

One person’s right is another person’s wrong.