Voice Of A Developer: Decoupling Your Application - Part 35

Introduction

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

JavaScript

 
Javascript is the 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.
 
The 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 an 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.
     
  • The 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 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 passes value js/page1 to the attribute. 
 
page
 
The three components are,
  • Script the script tag to load JavaScript
  • data-main entry point attribute which refers 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 the Console & Network tab to see page2.html related files only.
 
Console 
 
Console
 
Network
 
Network
 

Summary

 
Please share your feedback/comments.