Take this

Software Development / Web Development

Mastering JavaScript Design Patterns: A Practical Introduction to Building Better Applications

A practical introduction to writing better and more maintainable code using JavaScript design patterns


As the language of the web, JavaScript is used prolifically by developers building new applications every day. However, some developers still lack the knowledge about how to write things in a simpler, clearer and more maintainable way. Design patterns are proven solutions to common development problems, and can boost code quality and application maintainability, as well as improve developer efficiency.

Mastering JavaScript Design Patterns demonstrates how to apply design patterns in real life situations, whether that's for new, or already existing projects. It will help you to make your applications more flexible, perform better, and easier to maintain.

We’ll begin by building a simple music player application, and then we’ll build and add more and more functionality to our music player application. We’ll also cover different ways to modularize the application.

In the next two sections we’ll build a server and will load data from it. We’ll cover different techniques for caching, fallbacks, optimizing memory consumption and deferred actions.

In the last section we’ll cover code maintainability improvement techniques by using less known, yet powerful JavaScript techniques.

Full details


  • Introduction
    The Course Overview
    Introduction of all the sections of the course. • Have a look at what will be built • Explore the prerequisites for the course • Know the list of patterns covered in this course
    Software Design Patterns and Antipatterns
    Understand what a design pattern is and why it is important to know them. • Learn about a software design pattern • Expound the strong points of the design patterns • Learn about common JavaScript anti-patterns
    JavaScript Patterns Specifics
    How patterns are different in JavaScript? Different versions of ECMAScript used in this course. • Design patterns are simpler in dynamic languages compared to static languages • There are many ECMAScript implementations widely used, and we have to know our target audience • Explore ECMAScript 6 features that are used in this course
  • Starting the Project
    Bootstrapping the Project
    Rendering the tracks list. • List down the course software prerequisites • Initialize the project • Render the list of tracks
    Adding the Play Functionality
    Adding play functionality to the player. • Avoid global pollution • Add the play functionality • Add the pause functionality
    Encapsulating Information
    Hide the specifics of components by encapsulating information into modules. • Encapsulate the information into modules • Expose a limited set of modules' functionality • Use getters and setters
    Abstracting Manipulation with DOM Events and Elements
    Browsers represent complex systems. In order to simplify their use, a facade pattern can be used. • Move manipulation with DOM events and elements into a separate file • Abstract and simplify DOM manipulations • Use the Module and the Facade pattern
    Creating an Adapter to Set Intervals Using Seconds
    Use adapter pattern to simplify the usage of setInterval and setTimeout functions. • Create a file with timeout and interval adapters • Define setTimeout and setInterval adapters • Replace original setTimeout and setInterval with adapters
    Using Different Ways to Match Conditions
    Sometimes, there are alternative ways to match for conditions. • Match conditions using an object literal • Support creation of DOM text elements • Match conditions using an array literal
  • Modularizing the Application
    Modularizing the Application Using Namespaces
    The application grew quite a bit, so it has become hard to manage it. Separating it into smaller modules will make it more manageable. • Split the application into multiple files • Use Namespace pattern as a technique to manage and modularize application objects • Use a singleton object as the namespace root
    Modularizing the Application Using AMD and Require.js
    The Namespace pattern exposes modules through a global variable and does not resolve dependencies. • Replace the Namespace pattern with the AMD module • Load only one script in the HTML file • Use Require.js to load AMD modules
    Communication Between Modules
    It is hard to establish a communication between modules using classical methods. We’ll use PubSub for communication between modules. • Use a PubSub object as a communication channel between modules • Display the player status in the header and action button • Display the title of the currently playing track in the header
    ES6 Modules
    A new standard was established for defining and using modules - that is, ECMAScript 6 modules. • Review ECMAScript 6 modules syntax, usage, and how it is used currently • Define and use few ECMAScript 6 modules • Load and use ECMAScript 6 modules using Require.js and Babel.js libraries
  • Organizing the Application Through Separation of Concerns
    Decoupling the Tracks Queue from the Tracks Player
    Make the application more robust by decoupling tracks queue from tracks player. • Decouple the tracks queue from the tracks player • Use PubSub pattern for communication between queue and player • Use a Configuration Object to initialize the queue controller
    Treating Each Track as a Separate Component
    Treating each track as a separate component will allow an easier separation of concerns. • Treat each track as a separate component • Split track into model, view, and controller • Use Prototypal Inheritance to store common functionality in parent objects
    Adding the PubSub Functionality to Tracks
    In MVC, communication between model and view happens through a PubSub pattern. • Add the PubSub functionality to tracks • Use the PubSub pattern as a mixin • Display the title of the track that is currently playing in the header
    Enabling Track Play and Highlighting the Active Track
    MVC is one of the most used patterns that separates the internal representation of information from the UI with which user interacts. • Highlight the active track • Enable the track play button • Fully implement and review the MVC pattern
    Decoupling the Track Model from the View
    MVP is another commonly used pattern that is used to organize the UI elements. • Decouple the track model from view • Implement and review MVP pattern • Review the difference between MVC and MVP
    Formatting Track Time: Two-way Data Binding
    Often, before being rendered, model data has to formatted. For such cases, patterns such as MVVM are used. • Format the track time • Implement two-way data binding • Implement and review the MVVM pattern
  • Enhancing the Tracks Functionality and Adding Nested Tracks
    Adding a Few Types of Tracks
    We'll add multiple types of tracks and we'll use Factory pattern to create them. Also we'll implement lazy initialization that will defer initialization of objects until they are necessary. • Add few types of tracks • Use a Factory pattern to initialize tracks • Implement lazy initialization
    Implementing Track Removal
    Track removal was not implemented. In this video we'll do that. Also we'll add methods chaining • Implement track removal • Unhook events defined by removed tracks • If an active track was removed, then automatically play next track
    Iterating Over Tracks Using a Generator
    The collection should be the only entity that manages its state. Thus, we'll move the collection iteration logic into the collection module. • Review the generator function and the generator object • Delegate current track monitoring to collection • Iterate over tracks using a generator
    Iterating Over Tracks Using an Iterator
    Generators are powerful but have a limited set of functionality. An alternative to generators are iterators that use the same iteration protocol. • Review and implement iterator protocol • Decorate the iterator with some useful methods • Fix previously broken functionality
    Adding Nested Tracks and Displaying Them
    We'll add nested tracks. As each track can be both a parent and a child, we'll use the Composite pattern to make adding of nested tracks work. • Add nested tracks • Treat each track as both a parent and a child • Render nested tracks with a padding
    Fixing the Queue to Work with Nested Tracks
    After adding nested tracks, only their rendering worked as expected. Play and remove functionality worked in a wrong way. We'll fix that using an iterator that works with nested iterators. • Review the iterator pattern and exemplify iterating over the nested element • Fix queue to work with nested tracks • Create an iterator mixin with support for child iterators
  • Building the Server and Loading Data from It
    Creating the Server Using Node.js
    Storing the data in application code is a bad practice. We’ll defer that to the server. • Ensure that Node.js and npm are installed and install the Express module • Create a simple Node.js server • Run the server
    Returning the Tracks Queue from the Server
    Server will return a list of parent tracks, where child tracks would be embedded into parent tracks. • Use CommonJS modules • Return the tracks queue from the server • Embed child tracks into the tracks queue
    Loading Tracks from the Server
    AJAX requests are asynchronous. This requires that you use callbacks in order to continue application execution only after the data becomes available. • Load tracks from the server • Use an error-first callback to wait for the server response • Render tracks only after tracks data is loaded from the server
    Replacing Callbacks with Promises
    Callbacks often lead to a complex code. Also, managing errors has to be done in each callback. Promises help to overcome these complications. • Replace a callback with Promise • Chain successful callbacks • Handle callback errors in one place
    Binding a Function to a Custom Context
    Passing context scope into callbacks may lead to bugs. A much cleaner approach is to find callbacks to certain contexts. • Bind functions to custom contexts using the Proxy pattern • Use the JavaScript 'apply' method • Get rid of variables that hold context references
  • Loading Tracks' Additional Data
    Loading Tracks' Additional Data from the Server
    Until now, we loaded only main data about track. Now, we need more data about each track. So, on track play, we’ll ask the server for more data about active track. • Return secondary data for each track from server • Load secondary data only on demand • Render tracks' secondary data
    Caching Data Loaded from the Server
    Making the same request multiple times is inefficient. We'll optimize this by implementing a caching mechanism. • Cache data from server responses • Use the Memoization pattern • On secondary requests, return cached data
    Checking for Track Data with a Fallback
    Relying on a single source of data is fault-prone. We’ll implement a mechanism that will allow us to use multiple sources for tracks' additional data. • Use the Chain of Responsibility pattern • Use a fallback if server data is not available • Add a fallback image
    Storing Common Tracks Data in Shared Objects
    Having multiple objects consumes memory. In case of objects that have many similar attributes, a Flyweight pattern can be used to decrease memory footprint by using shared objects with data. • Implement the Flyweight pattern • Minimize the application memory usage • Create a utility for comparing two objects by value
  • Improving Code Maintainability
    Adding Different Skins for the Player Header
    We’ll use the Template method pattern that will allow to have an object with main functionality and subclassed objects with a specific functionality. • Create a base object for the player header view • Extend the base object to implement specific views • Use duck typing to detect single tracks
    Improving Testability by Inversion of Control
    We'll use inversion of control that is a widely used pattern in applications with tests. • Create an Injector module • Update render additional data function to load dependencies only when called • Review Inversion of Control
    Forcing Function Argument Types
    JavaScript live post-processing is a feature that may be used to validate, log, or even update arguments passed into functions. • Use live post-processing • Create a utility to check for arguments types • Test live post-processing validation using different types of objects
    Fixing Models to Support Any String as Attribute Name
    We'll enable tracks’ models to support any string as attribute name. • Find the problem with tracks' models • Borrow Object.prototype methods • Use Dictionary object


  • JavaScript
  • MVC

Similar Courses

More Courses by this Instructor