August 16, 2016

Learn why we believe that the rise of functional programming (FP) will prevent Angular 2.0 from being as successful as its predecessor. #

Angular 2.0 RC.5 was just released last week and is now really close the long-awaited 2.0 release.

After the success of Angular 1.0, it is normal to expect a huge success for Angular 2.0. However, we feel that there are reasons to believe that Angular 2.0 will not be as successful as its predecessor.

We believe this because we have been observing the front-end development trends and we have noticed a significant shift within the JavaScript community.

Let’s learn what this “shift” is about.

Note: JavaScript transpilers like Babel, TypeScript or Elm are out of the scope of this article. But you should really try Elm.

A little bit of history #

JavaScript is a multi-paradigm programming language. On its early days, it was mostly used as a scripting programming language. As the complexity of front-end application increased, the JavaScript community shifted towards a more object-oriented (prototype-based) style.

We can take a look to the API of many of the early single-page application (SPA) frameworks like Backbone.js to observe that they were heavily based on inheritance:

var Note = Backbone.Model.extend({ initialize: function() { ... }, author: function() { ... }, coordinates: function() { ... }, allowedToEdit: function(account) { return true; } });

At the time ES6 wasn’t around and many developers demanded a class-based object-oriented API. After some time the class-based API became a reality:

JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance. MDN

However, when the class-based API arrived it was already too late and many influential developers didn’t want it anymore:

Why? What happened between the arrival of the first SPA frameworks and the arrival of ES6?

The answer is simple: the JavaScript community is shifting towards a more functional programming style.

The rise of functional programming #

Functional programming has its roots in lambda calculus, a formal system developed in the 1930s.

FP is a “scary topic” because languages (especially purely functional ones) have largely been emphasised in academia rather than in commercial software development. However this is changing. JavaScript is a very accessible programming language and, as a result, FP in JavaScript is much more accessible than learning Haskell.

Many developers with a background on FP languages have started to work on SPA frameworks and today we can enjoy libraries like React, Redux, Cycle.js, MobX, Ramda or Immutable.js in our JavaScript applications. Some of these libraries have a more FP style API than others but they all share one thing: they try avoid OOP style on their APIs.

When we say “OOP style” we are referring to:

Inheritance over composition

Internal class state

Imperative state mutations

We all know that it is better to use composition over inheritance but when a framework gives you a classes that you can extend it means that the framework promotes inheritance over composition. Angular 2.0 is a bit “weird” because it seems to prefer the decorator pattern over inheritance. However the decorator pattern should not be not necessary in non-dynamic situations.

Some elements of the React API promote inheritance over composition. For example, we can extend the React.Component class:

import React from 'react'; class Contacts extends React.Component { constructor(props) { super(props); } render() { return ( <div></div> ); } } export default Contacts;

Dan Abramov shared his disagreement about APIs that favor inheritance over composition:

Don’t expect people to use your classes. Even if you choose to provide your classes as a public API, prefer duck typing when accepting inputs. Instead of instanceof checks, assert the existence of the methods you plan to use, and trust the user to do the right thing. This will make userland extensions and later tweaks easier, as well as eliminate the issues with iframes and different JavaScript execution contexts.

The React community is aware of the benefits of FP and new elements with a strong FP influence have been introduced into its API. For example, React.14 introduced a simpler way to define components called stateless functional components which introduced many benefits over its inheritance-based alternative.

Angular 2.0 uses RxJS with is a functional reactive programming (FRP) library. Reactive programming is not functional programming. Reactive programming is programming with asynchronous data streams (observables).

RxJS is reactive because it allows you to work with observables but is also functional because it includes an amazing toolbox of functions to combine, create and filter any of those streams. “That’s where the "functional” magic kicks in". We also have Cycle.js which is a framework highly influenced by FRP.

The official Angular 2.0 literature contains some reference to RxJS but it doesn’t emphasises enough in the ideas and benefits of reactive programming or mention the RxJS FP elements like the composition of observables. RxJS is used for things like fetching data from the server but not to do thing like user handling user input:

// SOURCE: https://angular.io/docs/ts/latest/guide/user-input.html @Component({ selector: 'click-me', template: ` <button (click)="onClickMe()">Click me!</button> {{clickMessage}}` }) export class ClickMeComponent { clickMessage = ''; onClickMe() { this.clickMessage = 'You are my hero!'; } }

Other frameworks like Cycle.js do a much more intensive usage of reactive data streams:

function ClickMeComponent({DOM}) { const msg$ = DOM.select('.btn') .events('click') .map(ev => 'You are my hero!') .startWith(''); return { DOM: msg$.map(clickMessage => div([ button('.btn', 'Click me!'), clickMessage ]) ) }; }

The angular.io docs are also full of examples of internal class state and imperative state mutations. We understand that many of this examples are very basic and using internal state simplifies the learning process but it feels quite different from reading the docs and examples of other libraries which strongly recommend following FP ideas like pure functions or immutability quite more often. You can of course use Angular 2.0 with these FP ideas but words like “pure”, “immutable”, “state”, “mutation”, “composition”, “reactive” or “observable” are much less common in the official Angular 2.0 literature than in the official Redux, React, RxJS or Cycle.js literature. This has lead us to think that the culture of Angular 2.0 as a community is much less aligned towards FP and FRP than the culture of other communities.

Many developers with an OOP background have been using libraries like React and Redux and slowly have been starting to understand the core FP principles:

How much of functional programming can I learn by learning AngularJS? Little to none. But, if you pick up React/Redux, you’ll actually encounter key functional concepts at the core of what you learn. Namely pure functions and immutability. - Quora

Understanding the basics about FP is is leading many developers to be eager to learn more about FP in JavaScript.

As developers learn more about FP we can observe the emergence of many libraries with a strong FP style like Cycle.js or Ramda and we believe that the shifting of the JavaScript community towards FP has just started.

How can the rise of FP influence the success of Angular 2.0? #

We believe that the Angular 2,0 API is highly influenced by OOP ideas and goes against the shifting of the JavaScript community towards FP that we have been explaining in this article.

Angular 2.0 is being advertised as a framework that gives you everything. However, some developers are using Angular 2.0 with Redux because after experiencing the benefits of FP in React they just simply don’t want to deal with an API with a strong OOP style. They like more the idea of triggering actions (pure functions) that will invoke a reducer (pure function) in Redux than invoking a method in a Service class in Angular 2.0:

// SOURCE: https://angular.io/docs/ts/latest/tutorial/toh-pt6.html import { Injectable } from '@angular/core'; import { Headers, Http } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import { Hero } from './hero'; @Injectable() export class HeroService { private heroesUrl = 'app/heroes'; // URL to web api constructor(private http: Http) { } getHeroes() { return this.http.get(this.heroesUrl) .toPromise() .then(response => response.json().data as Hero[]) .catch(this.handleError); } getHero(id: number) { return this.getHeroes() .then(heroes => heroes.find(hero => hero.id === id)); } save(hero: Hero): Promise<Hero> { if (hero.id) { return this.put(hero); } return this.post(hero); } delete(hero: Hero) { let headers = new Headers(); headers.append('Content-Type', 'application/json'); let url = `${this.heroesUrl}/${hero.id}`; return this.http .delete(url, {headers: headers}) .toPromise() .catch(this.handleError); } // Add new Hero private post(hero: Hero): Promise<Hero> { let headers = new Headers({ 'Content-Type': 'application/json'}); return this.http .post(this.heroesUrl, JSON.stringify(hero), {headers: headers}) .toPromise() .then(res => res.json().data) .catch(this.handleError); } // Update existing Hero private put(hero: Hero) { let headers = new Headers(); headers.append('Content-Type', 'application/json'); let url = `${this.heroesUrl}/${hero.id}`; return this.http .put(url, JSON.stringify(hero), {headers: headers}) .toPromise() .then(() => hero) .catch(this.handleError); } private handleError(error: any) { console.error('An error occurred', error); return Promise.reject(error.message || error); } }

We can use the Angular 2.0 components (even though they are not stateless functional components) together with some other libraries (like Redux or RxJS) to make Angular 2.0 feel “more functional”.

Note: Notice that we placed Redux closer to FP than React. Also notice how React on its own is closer to OOP than FP. If you use React with Redux you will be “closer to FP then OOP”. In a similar way, if you use Angular 2.0 with Redux and RxJS it will move a lot towards FP but we see Angular 2.0 closer to OOP than React that’s why it is located on the very far right. Also note that we are comparing FP influences in this diagram not reactive programming influences.

Why we need such a powerful framework then? Would it not be better to simply use a very light weight component library with Redux? This is something that is even happening to React components.

We believe that the “sweet spot” is somewhere between OOP and FP, maybe somewhere a bit closer to FP than OOP but maybe the right thing to do is to go fully functional. We have not tried to go pure functional yet but is something that we would like to experiment soon.

We are looking forward to find out what will bring us:

The aftermath of the “functional web frontend tsunami” React and friends brought about - Futurice

One week after publishing this article eslint-config-cleanjs was released on GitHub. This open-source project provide us with an eslint config which reduces JS to a pure functional language.

You can already find some examples online:

The examples have been written using eslint-config-cleanjs, to enforce a more functional style, which includes no-this and no-classes rules.

Frameworks with a strong functional programming influence like Cycle.js apps can pass the lint test easily:

The fact that this project exists is for us one more sign of the increasing interest of the JavaScript community in Functional Programming.

We believe that the Angular 2,0 API is less influenced by FP ideas than its competitors. This goes against the shifting of the JavaScript community towards FP that we have been explaining in this article.

As more and more people learn about functional programming techniques and try frameworks and libraries like React, Cycle.js, Redux, MobX, RxJS or Ramda they will be more likely to try to avoid classes, inheritance, imperative programming and other OOP elements as much as they can. This leads us to believe that the rise of FP within the JavaScript community will prevent Angular 2.0 from being as successful as its predecessor.

If you want to learn more about functional programming in JavaScript, a good way to get started is to use React with Redux and read some books:

Then you can introduce immutable.js and RxJS into your React applications and finally give a try to Cycle.js and Ramda.

Please feel free to share thoughts about this article with us via @WolkSoftwareLtd.

Don’t forget to subscribe if you don’t want to miss it out future articles!

1,943 Kudos