Modular JavaScript Architecture

Enterprise software of the modern business world are becoming more critical due to the competitive edge they bring to organizations. Leading businesses continuously invest money to sustain their competitive advantage by improving and addressing deficiencies in their existing software platforms.

The demand for business-critical change and improvement in enterprise software often causes code deterioration and accidental production of bugs which led developers in search of architectures that can withstand future changes. Thus, giving birth to modular architectures.

Modular JavaScript Architectures

A high level diagram of Modular JavaScript Architectures.

The Modular JavaScript Architecture (MJA) was introduced to build modern web applications that can withstand future changes without deteriorating. It also reduces the probability of bug introductions caused by change to existing software. The goal of today's blog post is to introduce the components, guidelines and benefits that this architecture provide.

Architectural Pieces

  • Modules - The building blocks of the architecture. Modules are typically represented by an interface group (usually an element container). The role of modules is to manage the HTML, CSS and behaviors enclosed in the sandbox that encloses it. Modules are also responsible for containing business specific implementations in the code.
  • Mediator - The object responsible for handling the communication and dependency management between modules.
    • Publish / Subscribe - The most common communication pattern used for implementing this architecture. Using this communication pattern improves the capability of a web application to scale (upward and downward) due to the fact that it allows seamless addition of new subscribing modules without affecting the existing subscribers (listening modules) and publishers (event producers).
    • Dependency Injection - Technique used in software architecture to dynamically supply dependencies required by a component to function. Using dependency injection enables software developers to produce components that were not tightly coupled to existing framework code (Implementation details).
  • Services - Components that provide the critical abstraction required between modules and framework code. Writing services introduces the capability to inject dependencies and swap their implementations without affecting the consuming modules. As a bonus, implementing services eliminates redundancy and reduces the weight of the scripts.

Guidelines

To maximize the advantage that the architecture provides, a set of guiding principles should be followed in order to prevent developers from heading towards wrong directions when implementing this architecture.

  • Modules should take care of theirselves.

    Modules should be responsible of managing interface element and behaviors enclosed in their sandboxes. Abiding this rule ensures low effort required to locate code that manipulates interface components.

  • Modules should not modify other modules

    Modules should NEVER alter elements and components that belong to other modules. Abiding this rule ensures predictability and loose coupling between modules.

  • Modules should broadcast events to let other modules react

    Modules should publish events that other modules can subscribe to alter their states without knowing the implementation behind with the broadcasted event. This is commonly done using the publish / subscribe pattern because it allows seamless addition and removal of subscribers (listening modules) from the application without affecting existing modules. Thus, inducing scalability and maintainability to the application's architectural design.

  • Module code should never access toolkit framework code (jQuery, Angular JS, etc..)

    WTH?, How am I supposed to do this sh*t?
    ~ Narrow Developer
    Framework code should always be kept out of the business level code (Module Code). Abiding this rule would allow business to switch frameworks seamlessly, this is very useful in scenarios where a company wants to maximize the usage of an enterprise-grade framework like Kendo UI and Infragistics UI. For me, the capability to seamlessly change frameworks without causing issues to a software is the most overlooked and ignored architectural decision (Cheers to the few brilliant hearts out there!).

  • All framework code should be abstracted at the services layer

    To narrow developers, this is where you have to put your missing sh*t. As the SOLID principles states "Abstractions should never depend on implementations, implementations should depend on abstractions.".

  • Inject services to modules using Dependency Injection Tools

    To ease dependency management and handle future changes, utilize application core frameworks (Different from toolkit frameworks) that provide dependency injection mediums.

Benefits

  • High Level of Scalability

    Modular JavaScript Architectures are capable of scaling to the extremes. It allows development teams to introduce and remove modules withouth affecting other modules across a huge code-base.

  • Fitted for Agile Methodologies

    Modular JavaScript Architecture is the perfect architecture for agile teams! This architecture allows agile teams to build interface modules in the same page between sprints and tasks.

  • Lesser Maintenance Required

    Since modules live and manage their own interfaces, developers can easily locate code that produces behaviors in the interface. It is also most likely for bugs to exist in single modules since no module alter other modules' state.

  • Say goodbye to source control conflicts (Lesser Blood Spilled)

    Since modules would be typically residing on their own JavaScript file, developers working on the same page but different modules would most likely not be experiencing source control conflicts when committing changes to their repositories.

  • It is where the future of the web heads towards

    ECMA Script 6 and HTTP 2.0 encourages modularization of JavaSript Applications.

Comments

Popular posts from this blog

Building Simple API Gateways with Ocelot and ASP.net Core

API Gateway in a Nutshell

Replicating Netflix Part 1: Installing Raspbian Lite using Etcher

10 Steps to Setup and Containerize an Express Server