Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Monday, September 19, 2016

React: Controlling state to accelerate development

I first started looking at the React JavaScript library from Facebook in early 2014. I had previously worked on sites using MVC frameworks like Angular and Backbone and at first it was hard to see what problem React was trying to solve. The other frameworks had an API for templating and even HTTP calls, but React could only render HTML in the browser. When I dug into the design it soon became clear what the goal of React is. It controls the amount of state required to render UI elements and it allows developers to create components with a single responsibility that can be safely composed into a whole system. The following is a high level overview of how React achieves this.

How React controls state

The core principle of React is to control and encapsulate the state of the user interface. React components do this by exposing two objects, Props and State.

Props

Props are supplied by a parent component to the children it creates. The props object is set at the time the component is created and it never changes, therefore it is immutable. This enforces one-way data binding so that an element, for example an input control on a form, can be populated with a value held in the props object.

However, when the user changes the value in the input field it will not change the value from the props object that it is bound to. The advantage of this is that values in the props object can be safely used anywhere in the UI and we know that they will not change the state of the application. The only place they can be changed is in the component that owns the original state. Components that only use props are stateless which means their behaviour is derived from the inputs given to them.

State

State is an object of a component and it is private to the component. The state can only be shared with child components by passing the values as props. The children can not change the state, only render it. If a child does need to mutate the state of the parent, the parent component provides a callback function in the props object. This allows the parent to decide how and when it will mutate the state. This builds upon the one-way data binding model into a one way data flow model for the application. With React, the user interface is composed of mainly stateless components with some stateful parent components controlling how state changes. With this model, the data flows down the tree of components and messages flow back up the tree in the form of callback functions to trigger state changes.

How React applies functional programming

The design of React is heavily influenced by principles common to functional programming. In fact the first prototype of React was created in OCaml. Stateless components are essentially pure functions and the encapsulation of the mutation of state is a core tenant of most functional programming languages. The building of a user interface by composing smaller components together in React is the same as function composition in functional programming. I am pleased to see the principles of functional programming forming the basis for a very popular library, as I believe that they lead to safer software that is quicker to develop.

Conclusion

React brought the principles of functional programming to the JavaScript ecosystem. It also captures a view that I have that software should be developed so that state is never changed in more than one location. I have seen many applications become brittle and impossible to extend because state is being changed in a number of places. The change becomes difficult because all the points of mutation must be found and checked to see that they still work with the change being made. A single point of mutation makes this problem go away.

React has now reached a point of maturity where the API has stabilized as have the supporting tools like Redux and react-devtools. It is the tool I now choose to build new web applications. It forces me to think up front about all the components I need for the user interface and which ones will hold state and which ones can be stateless. For more information look at Pete Hunt’s great post or try React using the new create react app tool.

Wednesday, November 27, 2013

Functional JavaScript book review

I was very excited to receive my copy of Functional JavaScript by Michael Fogus as I am interested in, and have views on, both Functional programming and JavaScript. My view  of the functional programming community is that it is full of very clever people who are focused on creating software which is robust and malleable. This is probably because the concepts behind functional programming are hard to understand. It is also because it has a closer relationship to various branches of mathematics. My opinion of JavaScript is that it is the most ubiquitous programming language we have ever known. It is a language with some good features, but it has to be handled with care. The need for care is even greater when using it to program the DOM as this is a very complex API.

The use of functional programming in JavaScript is not a new idea, indeed it has many influences from Lisp and Scheme. But it is very good to see someone write a book exploring the topic. The style of the book is very conversational and each chapter moves up through the complex layers of functional programming.

At the beginning the focus is on higher order functions (functions taking in other functions as parameters) all the way to flow based programming and a brief overview of monadic programming. This structure demonstrates very well how functions can be composed together to create bigger programs. Functions written in each chapter re-appear in later ones to be part of a bigger whole.

I have read this book once and I am working my way through it again. It is rich with ideas for any JavaScript programmer.  The concepts of functional programming certainly stretched my imperative programmers mind. Stretched as it was, I enjoyed seeing Michael Fogus take an imperative process and re-implement it as a series of functions composed together. Functional JavaScript is a very enjoyable read and I would recommend you pick up a copy.

Wednesday, October 05, 2011

The wonderful backbone.js

I recently gave a presentation on backbone.js at the Brighton Alt.net meeting. During this talk I demonstrated how Backbone.js can be used to organise JavaScript code into manageable layers. It’s Models and Collections manage the storing and retrieving of data. Views provide a mechanism for arranging the UI in to manageable chunks. It also has an event bus which helps reduce coupling between functions. Altogether, backbone brings order to the often chaotic world of client side development.

For the demonstration, I made a shopping list application which is available on github. Included is a web service which is used to manage the shopping list. You will need to install node.js to run the web service.

A traditional view of MVC

When first looking at backbone, I was thinking of an MVC framework in terms of the ASP.Net implementation. Here, the framework does not impose anything upon the model. The model is full of classes to capture the state and the behaviour of the system. For my shopping list it would contain types for an item, the list class, the price of the item and the state of the item. All of these would have methods which capture the behaviour. This model consists of a lot of small classes working together to define the system.

The controller is responsible for incoming requests. It will then validate the request and process it. If it is a query it will gather the required data and return it. If it was a command it will find a handler and update the model.

When complete it will load the correct view passing in the state required to render it.

The view uses the passed in data to create the representation requested by the client. Typically this will be an HTML page. The view is where we think of the client running server based MVC framework. Mainly as this is where we put all the client JavaScript.

Breaking with tradition

In backbone.js, the model object is very simple. It does not model the behaviour of a system accurately in fact, there may only be one model object. Therefore, it is not a system for building fully featured domain models.

What it does is apply the MVC pattern to browser development. Models, collections and views work together to create a wall. A wall which keeps all the AJAX code for dealing with data on one side, and all the code for building and rendering DOM elements on the other side. Without this boundary it is easy for JavaScript applications to have the same function calling a web service and updating the DOM. Over time this will lead to a system which is hard to maintain. By making a very clear separation between persistence code and UI code, backbone.js helps us to write better JavaScript.

Coding the data side

The first thing I did to find out how backbone can help my development was to create a model and a collection and point it at my web service.

I created a model object to represent an item in my shopping list:


There are three things happening above:
  1. I have created a model called ShoppingItem. This is told to use the Products collection in the constructor. It is also given some default values to be used by new instances.
  2. Here I create the collection of shopping items. In this simple demo I only have to set the endpoint for my web service and set the model object for the collection.
  3. Finally, I create a new instance of the collection.

The page itself has no real content, just a title. By using the console window in Firebug I can create, edit and delete new items in my shopping list

Here I can create a new item and when the save method is called, backbone sends a POST request to the service, creating the item.



Running this code in the browser will show backbone first POSTing the new item to the service. Then issuing a PUT to update the State, and finally a DELETE with the Id to remove it. Internally backbone uses either jQuery or Zepto for communication.

Collections

In backbone, a Model has to belong to a collection, in fact, it is a rare application where a single entity exists in isolation. Here is the Collection for my shopping list:



A very simple collection, it is told what type of Model it holds, and the URL for the web service to persist the objects to. The model object will use this URL when communicating with the web service. Finally it has method called toobuy which returns a list of all items in the collection where the state is “To buy”.

Summary

In this post I have created a shopping list in JavaScript. There is enough code here to run the application from the browser console where I can create, update and delete items from my list.

This highlights one of the first advantages of using backbone.js. I have concentrated on how my application will interact with the service before creating any UI components.

Look at the backbone.js site for more information and a growing list of examples.

Wednesday, September 14, 2011

Extending the JavaScript Array type

Here is how I created some expressive code by extending the basic types in JavaScript. This example extends the Array type whose content is often filtered or transposed. Through the use of function chaining complex operations can be very expressive and concise. I find this a great way to write code which is easy to follow.

I wanted to create a cross domain cookie based on the current domain of a page and I was provided with a list of sub domains where this should apply. Interestingly, this list included the name ‘uk’ and ‘cn’ which are also root level domain names.

Here are some example domains:
  • www.keithbloom.co.uk
  • landingpage.keithbloom.co.uk
  • uk.keithbloom.com
  • test.keithbloom.com

Here is a list of sub domains which can be removed:
  • www
  • landingpage
  • uk

Extending the Array

Arrays seemed the obvious choice to me. The domain string can be split on the full stop to create an array and the list of safe sub domains to be removed is already an array. Taking the first example, I end up with the following two arrays:

Now I wish to remove any items in the subDomains which form domainNameParts and return this result.

The subtract function loops over the input and compares each element with each element in the mask array. If it finds a match, the array splice function will remove it. It stops before it reaches the end of the input array though, to avoid removing any of the top level domains. Otherwise my example would return keithbloom.co - useless.

I now have a working function which can be used to create the domain for my cookie:

In the example I use the array function join to re-build my string and append a leading period to it. (For cross domain cookies to work, they must start with a period).

I found this cumbersome though and wanted a more more expressive method. Fortunately, JavaScript is a dynamic language so its internal types can be extended (a technique also know as Monkey Patching). I can add my subtract function to the Array objects prototype:

I now have a more expressive way to create my domain:

The final statement fits on one line. More importantly though it is concise and reads like a sentence. Creating code which is readable is more maintainable.

Pitfalls

This technique is a great way to extend the language and provide an expressive method for writing code. It can be dangerous though. As JavaScript runs as part of a web page there could be other scripts also running on that page. I may find that one of those scripts is also adding a subtract function to the array prototype. If this is a script I have access to, I can rename it. If it is an external script I may have to use a new name.

One way to avoid this is to prefix a namespace to my function:

Summary

Through the extension of the basic types in JavaScript it is possible to create expressive code. The Array type lends itself to this technique as they are often used as lists which we wish to manipulate in some way. Care must be taken though as we are changing code for all the programs being run in the session.