Voice Of A Developer: Decoupling Your Application - Part 35

Before moving further, let us look at the previous articles of the series

Javascript is a language of the Web. This series of articles will talk about my observations learned during my decade of software development experience with JavaScript. 

What is coupling?

In computer systems, coupling refers to the degree of direct knowledge that one component/class has of another. In a way, it is the degree of interdependence between the software modules. Our Application quality metrics depend upon the degree of interdependence components.

Types of coupling

Primarily, there are two types of coupling, i.e., loose and tight.

coupling
                                 Source: Wikipedia

Loose coupling is a better design, as it promotes single-responsibility and separation of the concerns principle. A loosely coupled module can be consumed and tested independently of other modules. In OOPS programming languages, interface is a powerful tool to use decoupling. Classes communicate via interface rather than other concrete classes.

In general, tight coupling is bad and not preferred because the modules are dependent on each other. If you want to change one module then it is not easy if it is tightly coupled with the other modules.

What is modularity?

An Application is modular, when it is composed of decoupled pieces stored in the modules. As developers, we shall aspire for loose coupling. Hence, our Application will be easy to maintain, update code, and make changes.

Module writing in JavaScript

If you remember, I mentioned in ES6 v2 (article 20), that we have a module available where we can export and import JavaScript functions. The popular concept in loading the module is AMD.

Asynchronous Module Definition (AMD)

The overall goal for the AMD format is to provide a solution for the modular JavaScript, that the developers can use today. It loads the module and dependencies asynchronously. There are many advantages associated with AMD and these are:

  • Improved performance loads files when require / needed.
  • Define dependencies: Allow the developers to define dependencies that must load before a module is executed.
  • This pattern is useful, where synchronous loading of the modules incurs performance issues.

amd
                                   Source: Wikipedia

There are various implementations of AMD, i.e., CommonJS, RequireJS, Dojo Toolkit.

Key concepts with the Modules

Here are the key concepts.

Loader loads the JavaScript code that handles the logic behind defining & loading modules. You need an AMD loader like dojo.js or require.js

Define function Here is the signature of this function.

define (id?, dependencies?, factory);

  • Id is optional string literal.

  • Dependencies is an array which defines dependencies required by the module. These dependencies must be resolved prior to the execution of the next factory function. It is also optional to say if this module is not dependent on any other module. It loads the dependencies asynchronously.

  • Factory Mandatory argument is executed only once.

Sample

  1. define  
  2. ([  
  3.     'require',  
  4.     'dependency'  
  5. ], function(require, factory)   
  6.  {  
  7.     'use strict';  
  8. });  
Require function

The require() function takes two arguments: an array of the dependencies and a callback function to execute once, all the dependencies are loaded.

Sample
  1. require(['calc''math'], function(calc, math)  
  2. {  
  3.     // you code   
  4.     calc.getData();  
  5.     math.calculate();  
  6. });  
Play with RequireJS

RequireJS is the most widely used implementation of AMD. It is a JS file and a module loader. You can download RequireJS from here.

You can refer to my GitHub repository https://github.com/sumitjolly/create-template and the structure of the project is:

structure

Download above repository using below command:

git clone https://github.com/sumitjolly/create-template.git

Project explanation

The intent is to showcase how RequireJS is useful and how we can write a better code with it. There are various directories, underneath www folder, i.e., app, js, lib. The lib is where,I have kept the require.js file. Let us deep dive into the other details which are as follows:

Load JavaScript files

Generally, we use <script src> format to add all our JavaScript files. RequireJS takes a different approach to load the modules. Look at Page1.html,

Page1.html  is an HTML, that includes require.js and pass value js/page1 to the attribute.

page
The three components are,

 

  • Script the script tag to load JavaScript
  • data-main entry point attribute which refer to load a javascript file
  • src base URL for require.js file

In our directory structure, you can see three files,

  • common.js
  • page1.js
  • page2.js

Now data-main attribute will load js/page1.js.

Note RequireJS assumes that file ends with .js. Both js/page1 & js/page1.js work fine.

Define module

There is a module that we created messages.js in and defined a dependency in lib/print.js file. The purpose of the messages is to include dependency and return a callback function.

function

print.js file returns a callback print function.

function

Calling module

Page1.js- This page1.js has a dependency on App/messages and uses require() form, that just uses the string name of the module to fetch it.

function

Run www/page1.html in your Browser and review Network & Console Developer (F12).

Console

Console
Network tab

Network tab

bote

You can also try www/page2.html and check Console & Network tab to see page2.html related files only.

Console

Console

Network

Network

Summary

Please share your feedback / comments.

Up Next
    Ebook Download
    View all
    Learn
    View all