Laurens Van Den Oever Xopus Presentation

  • View
    3.679

  • Download
    3

  • Category

    Business

Preview:

DESCRIPTION

 

Citation preview

The Challenges and Rewards of Writinga 100K line JavaScript Application September 16th 2009Laurens van den OeverCEO, Xopus BV

The Challenges and Rewards of Writinga 120K line JavaScript Application September 16th 2009Laurens van den OeverCEO, Xopus BV

Agenda

1. Background

2. Framework

3. Architecture

Background: Xopus Overview

• Browser based XML editor

• Non-technical target audience

• MVC

– XML

– XSL

– XSD

• 100% JavaScript & XSL

• Since 2001

Background: Xopus Demo

• http://xopus.com/demos

Background: WYSIWYG View

Background: Prevalidation

HTMLDOM

XMLDOM

XSD

Validator UI

Background: Metrics

• 986 classes

• 1,159 source files (js, xml, xsl)

• 3,411 KB / 1,411 KB obfuscated

• 8,143 functions

• 120,935 lines

Framework: Why?

AFLAX AJAX.NET AJAXGear Toolkit AJFORM AjaxAC AjaxRequest Ajaxcaller Bajax Behaviour CPaint DOM-Drag Dojo Toolkit Engine FlashObject Flexible AJAX JSPkg MochiKit Moo.FX Nifty Corners OSFlash Flashjs PAJAJ PEAR:: HTML AJAX Plex Toolkit Prototype RSLite Rico SACK SAJAX Sardalya Sarissa Scriptaculous Solvent Symfony TOXIC Taconite ThyApi Tibet WZ DradDrop WZ jsGraphics XAJAX XHConn XOAD ZK Zephyr Zimbra dp.SyntaxHighlighter jQuery jWic libXmlRequest moo.ajax overLIB qForms qooxdoo 1

1 from: http://edevil.wordpress.com/2005/11/14/javascript-libraries-roundup/

Framework: Why?

• We needed an application development framework

• Focus:– Performance

– Robustness

– Code re-use

– Automatic Testing

• Ease of development less important

Framework: Design

• Java/C# like object orientation

• JavaScript syntax for backward compatiblity– Incremental migration!

• On-the-fly server-side compilation

• Client-side compilation for– Dynamic loading

– Debugging

• Namespacing and typchecking prevent errors

Framework: Source Example

Package("com.xopus.code");

Import("com.xopus.code.Food");

Extends("com.xopus.code.Animal");

Class(

function Monkey (name) { this.name = name; },

function getName () { return this.name; },

function favorite () { return new Food("banana"); },

Static, function kind () { return "chimp"; }

);

Framework: Source Example

Package("com.xopus.code");

Import("com.xopus.code.Food");

Extends("com.xopus.code.Animal");

Class(

function Monkey (name) { this.name = name; },

function getName () { return this.name; },

function favorite () { return new Food("banana"); },

Static, function kind () { return "chimp"; }

);

Framework: Language constructs

• Fully qualified package names.

• Regular classes.

• Interfaces and abstract classes.

• Multiple inheritance

• Static & dynamic decoration

• Methods, put on prototype.

• Constructors, always the first method.(mandatory, constructor name defines class name)

Framework: Inheritance vs Decoration

• A subclass chooses it’s superclass:Extends("com.xopus.code.SuperClass");

Class(function SubClass (…) { … }, …)

• A decorator chooses it’s decoratee interface:Decorates("com.xopus.core.command.Command")

Decorator(function UndoableCommand() …)

• Other code can combine decorators at runtime:

UndoableCommand.decorateClass(

ChangeTrackingAcceptCommand);

Framework: Multiple inheritance

• Extend two classes:Extends(

"com.xopus.lui.components.Component",

"com.xopus.lui.focus.Focusable“

)

• Call super constructor:this.Component(…);

• Call super method:this.Component$destroy();

• Conflict resolution is developer responsibility

Framework: Classloader

• Server side compilation uses SpiderMonkey & PHP.– Windows, OS X and Ubuntu

• Compilation entirely written in the JS framework.

• Uses reflection, only possible compile time.

• Compiler extensions for profiling, coverage, dependency visualization.

Framework: Classloader

Browser

PHPSpiderMonk

ey

.js.js

.js.js

Classloader.js

Framework: Classloader

Framework: Testrunner

• Tests are linked to the modules they testTests(“com.xopus.editor.EditingContext”)

• Allows tracking of module quality and browser compatibility.

• Manual runner for development

• Automated server side runner for browser testing

Framework: Testrunner

Framework: Obfuscator

• Protect codebase

• Improve loading performance

• Java based

• Resticts JavaScript identifiers– No string manipulation of identifiers

• Knows classloader $ constructs

• Byte optimized Unicode output

Framework: Obfuscator

• Mixes RTL and LTR languages

function է() { var (خ!)this.դ.getElementsByTagName('xml')[0]; if=خreturn; var د=this.( خ( .this ;ذ د= ).this ;ر د( ;زthis.( د( ).this ;س د( for(var ;شM=0;M<this.ե.length;M++) ɛ.ص(this.ե[M],this.window); }, function ( د( ض{ Ý.Ť(د.selectNodes( "//@src|//@xml|//@xsd|//@xsl|//@url"),this.ũ); }

Architecture

• Two main problems:– Many tasks take too long to wait for

– Lot of code to sync application state with UI

Architecture: Conductor

• JavaScript execution

Event Event EventsetTimeou

t(0)Event

setTimeout(0)

Architecture: Conductor

• JavaScript execution

Event Event EventsetTimeou

t(0)Event

setTimeout(0)

Browser Rendering

Architecture: Conductor

• Capture all user input in event code

• Execute all code that affects future event

• Postpone the rest

Architecture: Conductor

• Skipping code for perceived performance

• Drag example– User drags object

– 10 mouse events per second

– Move takes 150 ms

– If you execute every move, you have a 0.5s delay after a second

– Feels better if object is moved at lower frequency but higher accuracy

• Delay move to timeout, move to last location

Architecture: Conductor

• ‘Threading’ in JavaScript

• Predefined Prioritized Phases

• Code can register method call on phase

• And cancel if request is outdated

• No parameters for simplicity and performance

Architecture: Conductor

• Code example:function start() {

Conductor.request(Conductor.UPDATE_PHASE, this);

},

function UpdatePhase() {

/* Do work */

if (!done)

Conductor.request(Conductor.UPDATE_PHASE, this);

},

function stop(){

Conductor.cancel(Conductor.UPDATE_PHASE, this);

}

Architecture: LUI

• LUI: Lazy User Interface– (Or: Laurens User Interface if it doesn’t work...)

• Functional Reactive Programming User Interface Framework

• Combines Conductor threading with

• Easy binding of application state with user interface

Architecture: LUI

• Component States:– Active: currently busy

– Attention: has keyboard focus or mouse over

– Checked: applies to current context

– Enabled: can be activated

• Abstraction for mouse and keyboard events

Architecture: LUI

• Button template example

<span class="button">

<span class="{active}-button

{attention}-button

{label}-button">

<span>{label}</span>

</span>

</span>

Architecture: LUI

• Component code

XMLResource("Button.uit.xml")

this.declare(“active“, false);

this.set(“active", true);

var active = this.get(“active");

Architecture: LUI

• UI config example

<toolbargroup>

<button command="SpellCheckerCommand"/>

...

</toolbargroup>

Architecture: LUI

• Formulasthis.declareFormula(“enabled“, getEnabled);

function getEnabled(scope) {

var node = scope.get(“node”);

return node.getName() == “example”;

}

<span class="{enabled}-component”/>

Final notes

• We have not reached the limits of the browser, but it is getting increasingly harder to make the next step.

• We are willing to share parts of our platform with other projects.

Please complete an evaluation.

Questions?

Recommended