Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Introduction This talk will cover strategies that can help streamline your application architecture. Thanks to Nicholas Zakas, Rebecca Murphey, Paul Irish and Justin Meyer for their previous work in this area.

Slide 3

Slide 3 text

What is a ‘large’ application? Some developers suggested: “Apps where the size of code is over over 100,000 LOC” Incorrect, because code size does not always correlate to complexity

Slide 4

Slide 4 text

What is a ‘large’ application? “Apps with over 1MB of JS code written in-house” Again, this could be very simplistic code. Can we get more clear?

Slide 5

Slide 5 text

What is a ‘large’ application? “A non-trivial application requiring significant developer effort to maintain” Correct.

Slide 6

Slide 6 text

SOME EXAMPLES GMail

Slide 7

Slide 7 text

SOME EXAMPLES Yahoo! Homepage

Slide 8

Slide 8 text

SOME EXAMPLES MobileMe

Slide 9

Slide 9 text

SOME EXAMPLES Aol Mail / Phoenix

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

Your Architecture MVC (Models/Views/Controllers) Application Core Modules Custom Widgets JavaScript Libraries & Toolkits Your current architecture likely resembles a mixture of the following:

Slide 12

Slide 12 text

Possible problems with this: How much of this architecture is instantly re-usable? Can single modules exist on their own independently? Are they self-contained?

Slide 13

Slide 13 text

Possible problems with this: How much do modules depend on other modules inside the same system? Does your app contain many modules that are tightly coupled?

Slide 14

Slide 14 text

Possible problems with this: How easily can you test individual modules? How certain are you that if specific parts of your application fail, it can still function?

Slide 15

Slide 15 text

Think long-term Developers often couple their DOM manipulation code quite tightly with the rest of their application Why is this not a good idea if we’re thinking long-term?

Slide 16

Slide 16 text

Think long-term You may decide to switch from using jQuery to Dojo or YUI for reasons of performance, security or design. Can this decision currently be made without rewriting your entire application?

Slide 17

Slide 17 text

Remember.. “The secret to building large apps is never build large apps. Break your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application” - Justin Meyer.

Slide 18

Slide 18 text

Also.. “The more tied components are to each other, the less reusable they will be, and the more difficult it becomes to make changes to one without accidentally affecting another” - Rebecca Murphey.

Slide 19

Slide 19 text

Let’s brainstorm. We want a loosely coupled architecture with functionality broken down into smaller modules that aren’t dependant on one another. You probably already use modules but we need them to be fully independent entities.

Slide 20

Slide 20 text

Some more ideas. To achieve this we need single modules to speak to the rest of the application when something interesting happens. We then use a different layer to interpret requests so that modules don’t directly access the core. This aids in preventing applications from falling over due to errors with a specific module.

Slide 21

Slide 21 text

and wrapping up.. Modules shouldn’t be able to access everything. They probably can in most current architectures. Having an intermediate layer handle permissions for which modules can access which parts of your framework gives you a layer of security. This means a module is only able to do at most what we’ve permitted it do.

Slide 22

Slide 22 text

Solution Module theory + Facade pattern + Mediator pattern = WIN

Slide 23

Slide 23 text

Module Theory “Anything can be defined as a reusable module” - Zakas. Modules should be considered independent units of functionality that can exist on their own

Slide 24

Slide 24 text

Module Theory Modules have very limited knowledge of what’s going on in the rest of the application Loose coupling is essential to this - modules should ideally not depend on other modules.

Slide 25

Slide 25 text

Loose Coupling Facilitates improved maintainability by removing code dependencies where possible In our case, modules should not rely on other modules in order to function correctly. When used effectively, it’s straight-forward to see how changes to one part of a system may affect another.

Slide 26

Slide 26 text

Applying Module Theory Any significantly non-trivial application should be built from modular components When a module is reusable it’s clear how to use or extend it In JavaScript, there are several options for defining modules, including:

Slide 27

Slide 27 text

The Module Pattern The well-known module pattern makes use of closures to bake privacy, state and organization into your objects. It’s quite similar to an IIFE with an object returned instead of a function. Commonly implemented as a singleton.

Slide 28

Slide 28 text

Object Literals Object literal notation is another option for structuring modules Basically consists of an array of key:value pairs Methods defined using object literal notation don’t exist until the execution of the script.

Slide 29

Slide 29 text

Facade Pattern Provides a convenient higher-level interface to a larger body of code, regardless of underlying complexity Hides the inner-workings of a library or set of modules, allowing the implementation to be less important. We thus only need to interact with the facade rather than the subsystem it encompasses.

Slide 30

Slide 30 text

The Mediator Pattern Encapsulates how disparate modules interact with each other by acting as an intermediary Promotes loose coupling by preventing objects from referring to each other explicitly, solving our module inter-dependency issues.

Slide 31

Slide 31 text

The Mediator Pattern Allows for actions of each module to vary independently, so it’s extremely flexible Somewhat similar to Observer/Pub-Sub, so it’s not difficult to understand how it fits in if you’ve used one of these patterns previously.

Slide 32

Slide 32 text

Why is it the bee’s knees? Allows modules to broadcast or listen for messages without worrying about the rest of the system Messages can be handled by any number of modules at once. Typically significantly more easy to add or remove features to systems which are loosely coupled like this.

Slide 33

Slide 33 text

Mediator downsides By adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop. Because of the nature of loose coupling, it’s difficult to establish how a system might react by only looking at the broadcasts. At the end of the day, tight coupling causes all kinds of headaches and this is one solution.

Slide 34

Slide 34 text

Mediator Metaphor Think of an airport control tower. The tower handles what planes can take off and land. All communications are done from the planes to the control tower, rather than from plane-to- plane A centralised controller is key to the success of this system as is the case with the mediator pattern.

Slide 35

Slide 35 text

The Facade Effectively, an abstraction of the application core that sits in the middle between it and modules Ensures a consistent interface to our modules is available at all times Should be the only thing modules are aware of - they shouldn’t know about other components.

Slide 36

Slide 36 text

The Facade Components communicate via the adapter so it needs to be dependable The adapter acts as a security guard, determining which parts of the application a module can access Components only call their own methods and shouldn’t interact with anything they don’t have permission to

Slide 37

Slide 37 text

NOTE: Nicholas Zakas refers to the facade here as a sandbox controller. Agrees that it could equally be considered the adapter, proxy or facade pattern. As Stoyan Stefanov defined an existing ‘sandbox’ pattern, I refer to the sandbox as a facade as IMO this pattern matches it’s purpose most closely.

Slide 38

Slide 38 text

The application core It’s job is to manage the module lifecycle. When is it safe for a module to start? When should it stop? Modules should execute automatically when started.

Slide 39

Slide 39 text

The application core It’s not the core’s job to decide whether this should be when the DOM is ready. The core should enable adding or removing modules without breaking anything. It should ideally also handle detecting and managing errors in the system.

Slide 40

Slide 40 text

Revised Architecture Application Core (Mediator) tied into MVC if using that pattern. Self-contained modules Libraries • Your new architecture could potentially look something like this: Adapter (abstraction of the core) Mediation Publishers Subscribers

Slide 41

Slide 41 text

Tying in: modules Modules want to inform the application when something interesting happens. eg. a new message has arrived.other modules related as necessary. Correctly publishing events of interest should be their primary concern.

Slide 42

Slide 42 text

Tying in: the facade The core (via the abstracted adapter) listens out for interesting events and says ‘Awesome. What happened? Give me the details’.

Slide 43

Slide 43 text

Tying in: the core The core will then react/start or stop other modules related as necessary.

Slide 44

Slide 44 text

Modules Should ideally not be concerned about: what objects or modules are being notified where these objects are based (client? server?) how many objects subscribe to notification

Slide 45

Slide 45 text

Module Communication Core Module 1 OrderPackager Adapter M Module 2 LabelManager ‘Tom’s order has been successfully packaged ‘Tom’s order has been labelled notify(‘orderPackaged’,‘Tom’,‘success’) notify(‘orderLabelled’,‘Tom’, ‘success’) Module 3 DispatchManager ‘Tom’s order has been dispatched notify(‘orderDispatched’,‘Tom’, ‘success’,’12-08-11’) Start LabelManager Start DispatchManager

Slide 46

Slide 46 text

Summary The core acts as like a ‘Pub/Sub’ manager using the mediator pattern. Responsible for module management. The facade abstracts the core to avoid modules touching it directly. Handles security. The modules contain specific pieces of functionality for your application.

Slide 47

Slide 47 text

Result Modules are no longer dependent on anyone. If you stick to a consistent API, you can easily replace a module using jQuery with one using dojo later on.

Slide 48

Slide 48 text

Result Modules can be easily tested and maintained on their own. Modules can be added or removed without the application falling over.