gwt@jazoon08 - part 1/6 - first impressions count
DESCRIPTION
A presentation about GWT which I presentaed at Jazoon '08Part 1/6 - First Impressions CountTRANSCRIPT
![Page 1: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/1.jpg)
LOGO SPEAKER‘S COMPANY
# 1first impressions count.
![Page 2: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/2.jpg)
LOGO SPEAKER‘S COMPANY
checking in at a hotel ...
![Page 3: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/3.jpg)
LOGO SPEAKER‘S COMPANY
choosing a puppy ...
![Page 4: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/4.jpg)
LOGO SPEAKER‘S COMPANY
unboxing your iPhone ...
![Page 5: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/5.jpg)
LOGO SPEAKER‘S COMPANY
unboxing your iPhone ...
![Page 6: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/6.jpg)
LOGO SPEAKER‘S COMPANY
unboxing your iPhone ...
![Page 7: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/7.jpg)
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
![Page 8: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/8.jpg)
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
![Page 9: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/9.jpg)
LOGO SPEAKER‘S COMPANY
annoying.
slow apps are annoying
buggy apps are annoying
slow, buggy apps are not worth using
![Page 10: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/10.jpg)
LOGO SPEAKER‘S COMPANY
irrelevant.
source code elegance and maintainability
how much fun it is to develop
choice of programming language
![Page 11: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/11.jpg)
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.”
![Page 12: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/12.jpg)
LOGO SPEAKER‘S COMPANY
page load.
1. download resources
2. run JavaScript startup code
3. render layout
![Page 13: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/13.jpg)
LOGO SPEAKER‘S COMPANY
![Page 14: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/14.jpg)
LOGO SPEAKER‘S COMPANY
resource issues.
50kb = 1200ms
25kb = 950ms
2 x 25kb = 2 x 950 ms
50kb = 1900ms
ms
kb
![Page 15: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/15.jpg)
LOGO SPEAKER‘S COMPANY
startup issues.
lazy loading
lazy loading
lazy loading
lazy loading
lazy loading
![Page 16: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/16.jpg)
LOGO SPEAKER‘S COMPANY
rendering issues.
![Page 17: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/17.jpg)
LOGO SPEAKER‘S COMPANY
GWTto the rescue
![Page 18: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/18.jpg)
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
![Page 19: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/19.jpg)
LOGO SPEAKER‘S COMPANY
compiler.
“Seperate maintainability of the source codefrom the effectiveness of the executable.”
- Bruce Johnson
![Page 20: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/20.jpg)
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
![Page 21: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/21.jpg)
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
![Page 22: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/22.jpg)
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)
![Page 23: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/23.jpg)
LOGO SPEAKER‘S COMPANY
stop! no more GWT introduction stuff
please...
![Page 24: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/24.jpg)
LOGO SPEAKER‘S COMPANY
so what makesGWT so fast?
![Page 25: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/25.jpg)
LOGO SPEAKER‘S COMPANYis it magic?
![Page 26: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/26.jpg)
LOGO SPEAKER‘S COMPANY
deferred binding.
![Page 27: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/27.jpg)
LOGO SPEAKER‘S COMPANY
only payfor what you see
![Page 28: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/28.jpg)
LOGO SPEAKER‘S COMPANY
![Page 29: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/29.jpg)
LOGO SPEAKER‘S COMPANY
right code.user agentlocaledebug vs. productionnetwork characteristicsloggingdebug id on html elements…anything that can make a difference for the user
![Page 30: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/30.jpg)
LOGO SPEAKER‘S COMPANY
modularize.
DOMImplIE6
DOMImplMozilla
DOMImplSafari
DOMImpl…
DOM
![Page 31: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/31.jpg)
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
![Page 32: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/32.jpg)
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();
![Page 33: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/33.jpg)
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; } --*/
}
![Page 34: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/34.jpg)
LOGO SPEAKER‘S COMPANY
advantages.right code
smaller code
better optimizations
fewer network roundtrips
metaprogramming
![Page 35: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/35.jpg)
LOGO SPEAKER‘S COMPANY
BETTER OPTIMIZATIONS
example
Label label = new Label(“test”);
output (not obfuscated)
Firefox e.textContent = s;
IE6 e.innerText = s;
![Page 36: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/36.jpg)
LOGO SPEAKER‘S COMPANY
deferred binding.[ dependency injection ]
![Page 37: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/37.jpg)
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”; }
}
![Page 38: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/38.jpg)
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>
![Page 39: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/39.jpg)
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>
![Page 40: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/40.jpg)
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”/>
![Page 41: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/41.jpg)
LOGO SPEAKER‘S COMPANY
SET PROPERTY VALUE AT RUNTIME (optional)
<property-provider name=“animal”><!CDATA[
return isCat(document.cookie) ? “cat” : “dog”/>
]]></property-provider>
![Page 42: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/42.jpg)
LOGO SPEAKER‘S COMPANY
deferred binding.[ generators ]
![Page 43: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/43.jpg)
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”; }
![Page 44: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/44.jpg)
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>
![Page 45: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/45.jpg)
LOGO SPEAKER‘S COMPANY
GWT REFLECTION VS JAVA REFLECTION
TypeOracle oracle = generatorContext.getTypeOracle();
![Page 46: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/46.jpg)
LOGO SPEAKER‘S COMPANY
deferred binding.[ demystified ]
![Page 47: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/47.jpg)
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)]
![Page 48: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/48.jpg)
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
![Page 49: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/49.jpg)
LOGO SPEAKER‘S COMPANY
deferred binding.[ use case: form generation ]
![Page 50: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/50.jpg)
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;
}
![Page 51: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/51.jpg)
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);
}
![Page 52: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/52.jpg)
LOGO SPEAKER‘S COMPANY
deferred binding.[ pages versus modules ]
![Page 53: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/53.jpg)
LOGO SPEAKER‘S COMPANY
SEARCH
100%
SEARCHEDIT
95%
ACCOUNT
5%
![Page 54: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/54.jpg)
LOGO SPEAKER‘S COMPANY
extreme graphics.
![Page 55: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/55.jpg)
LOGO SPEAKER‘S COMPANY
problems.
DOM operations are slow
CANVAS bails out at 1000 - 10000 DIV moves
JavaScript VM no match for JVM
![Page 56: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/56.jpg)
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
![Page 57: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/57.jpg)
LOGO SPEAKER‘S COMPANY
solutions.dual compile
measure average client side thresholdif too slow render on server bare HTML (StringBuffer) / Java2D
SVG / VML / flash
![Page 58: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/58.jpg)
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
![Page 59: GWT@Jazoon08 - Part 1/6 - First Impressions Count](https://reader033.vdocuments.us/reader033/viewer/2022060122/559533531a28ab865f8b46d0/html5/thumbnails/59.jpg)
LOGO SPEAKER‘S COMPANY
MAARTENVOLDERS.comPASSIONATE ABOUT PEOPLE AND TECHNOLOGY