LOGO SPEAKER‘S COMPANY # 1 first impressions count.
Jul 02, 2015
LOGO SPEAKER‘S COMPANY
# 1first impressions count.
LOGO SPEAKER‘S COMPANY
checking in at a hotel ...
LOGO SPEAKER‘S COMPANY
choosing a puppy ...
LOGO SPEAKER‘S COMPANY
unboxing your iPhone ...
LOGO SPEAKER‘S COMPANY
unboxing your iPhone ...
LOGO SPEAKER‘S COMPANY
unboxing your iPhone ...
LOGO SPEAKER‘S COMPANY
start fast.“Every web usability study I have conducted since 1994 has shown the same thing: Users beg us to speed up page downloads.”
- Jakob Nielsen
LOGO SPEAKER‘S COMPANY
human attention.0.1 seconds - perceived as instantaneous
1 second - maintains the feeling that a single task is being carried out
10 seconds - limit for keeping user’s attention
LOGO SPEAKER‘S COMPANY
annoying.
slow apps are annoying
buggy apps are annoying
slow, buggy apps are not worth using
LOGO SPEAKER‘S COMPANY
irrelevant.
source code elegance and maintainability
how much fun it is to develop
choice of programming language
LOGO SPEAKER‘S COMPANY
GWT manifesto.
“To radically improvethe web experience for usersby enabling developersto use existing Java toolsto build no-compromise Ajaxfor any modern browser.”
LOGO SPEAKER‘S COMPANY
page load.
1. download resources
2. run JavaScript startup code
3. render layout
LOGO SPEAKER‘S COMPANY
LOGO SPEAKER‘S COMPANY
resource issues.
50kb = 1200ms
25kb = 950ms
2 x 25kb = 2 x 950 ms
50kb = 1900ms
ms
kb
LOGO SPEAKER‘S COMPANY
startup issues.
lazy loading
lazy loading
lazy loading
lazy loading
lazy loading
LOGO SPEAKER‘S COMPANY
rendering issues.
LOGO SPEAKER‘S COMPANY
GWTto the rescue
LOGO SPEAKER‘S COMPANY
goal.
reduce # HTTP request by reducing file count
cache until the sun explodes
cross browser, cross platform at no cost
min usability compromises due to impl changes
extreme JavaScript code optimizations
LOGO SPEAKER‘S COMPANY
compiler.
“Seperate maintainability of the source codefrom the effectiveness of the executable.”
- Bruce Johnson
LOGO SPEAKER‘S COMPANY
compiler.
handwritten JavaScript has a conflict of interest
long, useful identifiers = bigger, slower apps nice formatting = bigger, slower apps comments = bigger, slower apps
zero-cost abstraction
LOGO SPEAKER‘S COMPANY
compiler.
user feedback and usability testing are vital
you will never get it right the first N times
being able to iterate quickly is key
developers need tools with lots of leverage
LOGO SPEAKER‘S COMPANY
compiler.
again, JavaScript has a conflict of interest
JavaScript = difficult to refactorrefactoring difficulty = maintenance worrymaintenance worry = the need to “get it right” the first time (framework-itis)
LOGO SPEAKER‘S COMPANY
stop! no more GWT introduction stuff
please...
LOGO SPEAKER‘S COMPANY
so what makesGWT so fast?
LOGO SPEAKER‘S COMPANYis it magic?
LOGO SPEAKER‘S COMPANY
deferred binding.
LOGO SPEAKER‘S COMPANY
only payfor what you see
LOGO SPEAKER‘S COMPANY
LOGO SPEAKER‘S COMPANY
right code.user agentlocaledebug vs. productionnetwork characteristicsloggingdebug id on html elements…anything that can make a difference for the user
LOGO SPEAKER‘S COMPANY
modularize.
DOMImplIE6
DOMImplMozilla
DOMImplSafari
DOMImpl…
DOM
LOGO SPEAKER‘S COMPANY
problems.
dynamic modules over HTTP suckslow to start
awful network utilizationslow to execute
requires polymorphic dispatch at runtimeimpossible to eliminate dead code
hard to maintain“DLL Hell” for the web
LOGO SPEAKER‘S COMPANY
magic.DOMImpl dom = GWT.create(DOMImpl.class);
generates permutations at compile time: DOMImpl dom = new DOMImplMozilla(); DOMImpl dom = new DOMImplIE6(); DOMImpl dom = new DOMImplSafari();
LOGO SPEAKER‘S COMPANY
DOMIMPL EXAMPLE
abstract class DOMImpl {
abstract void setInnerText(Element e, String s);
}
public class DOMImplMozilla extends DOMImpl {
native void setInnerText(Element e, String s)
/*-- { e.textContent = s; } --*/
}
public class DOMImplIE6 extends DOMImpl {
native void setInnerText(Element e, String s)
/*-- { e.innerText = s; } --*/
}
LOGO SPEAKER‘S COMPANY
advantages.right code
smaller code
better optimizations
fewer network roundtrips
metaprogramming
LOGO SPEAKER‘S COMPANY
BETTER OPTIMIZATIONS
example
Label label = new Label(“test”);
output (not obfuscated)
Firefox e.textContent = s;
IE6 e.innerText = s;
LOGO SPEAKER‘S COMPANY
deferred binding.[ dependency injection ]
LOGO SPEAKER‘S COMPANY
CREATE AN INTERFACE / BASE CLASS
public interface Animal {
String makeSound();
}
CREATE IMPLEMENTATIONS
public class Dog implements Animal {
public String makeSound() { return “bark”; }
}
public class Cat implements Animal {
public String makeSound() { return “miauuwww”; }
}
LOGO SPEAKER‘S COMPANY
USE IT
Animal animal = GWT.create(Animal.class);
Window.alert(animal.makeSound());
DECLARE REBIND RULES
<replace-with class=“org.animal.Cat”>
<when-type-is class=“org.animals.Animal”/>
</replace-with>
LOGO SPEAKER‘S COMPANY
DECLARE PROPERTY / ENUMERATED SET OF VALUES
<define-property name=“animal” values=“cat,dog”/>
DECLARE REBIND RULES
<replace-with class=“org.animal.Cat”>
<when-type-is class=“org.animals.Animal”/>
<when-property-is name=“animal” value=“cat”/>
</replace-with>
<replace-with class=“org.animal.Dog”>
<when-type-is class=“org.animals.Animal”/>
<when-property-is name=“animal” value=“dog”/>
</replace-with>
LOGO SPEAKER‘S COMPANY
DECLARE REBIND RULES (other conditions)
<when-type-is class=“...”/><when-type-assignable class=“...”/>
<when-property-is name=“...” value=“...”/><any><all><none>
EXTEND PROPERTY VALUES (optional / inheritance)
<extend-property name=“animal” values=“fish”/>
SET DEFAULT PROPERTY VALUE (optional)
<set-property name=“animal” values=“dog”/>
LOGO SPEAKER‘S COMPANY
SET PROPERTY VALUE AT RUNTIME (optional)
<property-provider name=“animal”><!CDATA[
return isCat(document.cookie) ? “cat” : “dog”/>
]]></property-provider>
LOGO SPEAKER‘S COMPANY
deferred binding.[ generators ]
LOGO SPEAKER‘S COMPANY
CREATE A NEW GENERATOR
public class CatGenerator extends Generator {
public String generate(TreeLogger logger, GeneratorContext ctx, String requestedClass) {
PrintWriter pw = ctx.tryCreate(logger, “test”, “EvilCat”); pw.println(“package test;”); pw.println(“public class EvilCat implements Animal {“); pw.println(“public String makeSound() { return “Gshhh”; }”); pw.println(“}”);
return “test.EvilCat”; }
LOGO SPEAKER‘S COMPANY
DECLARE REBIND RULES
<generate-with class=“org.animals.CatGenerator”>
<when-type-is class=“org.animals.Animal”/>
</generate-with>
DECLARE REBIND RULES (other conditions)
<when-type-is class=“...”/>
<when-type-assignable class=“...”/>
<when-property-is name=“...” value=“...”/>
<any>
<all>
<none>
LOGO SPEAKER‘S COMPANY
GWT REFLECTION VS JAVA REFLECTION
TypeOracle oracle = generatorContext.getTypeOracle();
LOGO SPEAKER‘S COMPANY
deferred binding.[ demystified ]
LOGO SPEAKER‘S COMPANY
runtime.request generated selection script .nocache.js
property providers run to decide prop values
property values imply a permutation:
map([‘de, ‘ie6’, …], ‘blabla.cache.html’) map([‘nl’, ‘ie6’, …], ‘ababab.cache.html’) map([‘nl’, ‘safari’, …], ‘xyxyxy.cache.html’) strongName = answers[computePropValue(‘locale’)] [computePropValue(‘’user.agent)]
LOGO SPEAKER‘S COMPANY
permutations..cache.html allows for perfect caching
cache until the sun explodes
never fail to get the newest when updated
never ask if it hasn’t been updated
not even an If-Modified-Since check
disk space is cheap
bandwith and user attention is expensive
LOGO SPEAKER‘S COMPANY
deferred binding.[ use case: form generation ]
LOGO SPEAKER‘S COMPANY
GOAL
less boilerplate code no more listener overhead / memory leaks alternative for traditional MVC + GWTX (PropertyChangeListener)
DATA OBJECT + FORM ANNOTATIONS
@form.service (value=“com.WishService”)
public class Wish implements FormDataObject {
@form.field (length = 50, label = “name”, order = 2, required = true)
private String name;
@form.field (length = 200, label = “description”, order = 1, required = true)
private String description;
}
LOGO SPEAKER‘S COMPANY
BINDING
<generate-with class=“com.FormGenerator”>
<when-type-assignable class=“com.FormDataObject”/>
</generate-with>
USAGE
public void onModuleLoad() {
Form wishForm = GWT.create(Wish.class);
RootPanel.get().add(wishForm);
}
LOGO SPEAKER‘S COMPANY
deferred binding.[ pages versus modules ]
LOGO SPEAKER‘S COMPANY
SEARCH
100%
SEARCHEDIT
95%
ACCOUNT
5%
LOGO SPEAKER‘S COMPANY
extreme graphics.
LOGO SPEAKER‘S COMPANY
problems.
DOM operations are slow
CANVAS bails out at 1000 - 10000 DIV moves
JavaScript VM no match for JVM
LOGO SPEAKER‘S COMPANY
solutions.display lists (OpenGL concept)
recorded + compiled sequence of callsreplay sequence like a macro
fastest method to draw static datacompiler can do performance optimizationscache results as bitmap where possible
LOGO SPEAKER‘S COMPANY
solutions.dual compile
measure average client side thresholdif too slow render on server bare HTML (StringBuffer) / Java2D
SVG / VML / flash
LOGO SPEAKER‘S COMPANY
solutions.small enhancements
replace DOM.setStyleAttribute with CSS filesdon’t use widgets when all you need is HTMLavoid many listenerssingle listener on root -> DOM.sinkEvents
LOGO SPEAKER‘S COMPANY
MAARTENVOLDERS.comPASSIONATE ABOUT PEOPLE AND TECHNOLOGY