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.
- 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.
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?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!).
~ Narrow Developer
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.
High Level of Scalability
Fitted for Agile Methodologies
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)
It is where the future of the web heads towards
ECMA Script 6 and HTTP 2.0 encourages modularization of JavaSript Applications.