gwt@jazoon08 - part 1/6 - first impressions count

59
LOGO SPEAKER‘S COMPANY # 1 first impressions count.

Upload: maarten-volders

Post on 02-Jul-2015

1.897 views

Category:

Technology


3 download

DESCRIPTION

A presentation about GWT which I presentaed at Jazoon '08Part 1/6 - First Impressions Count

TRANSCRIPT

Page 1: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

# 1first impressions count.

Page 2: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

checking in at a hotel ...

Page 3: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

choosing a puppy ...

Page 4: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

unboxing your iPhone ...

Page 5: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

unboxing your iPhone ...

Page 6: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

unboxing your iPhone ...

Page 7: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

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

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

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

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

LOGO SPEAKER‘S COMPANY

Page 14: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

LOGO SPEAKER‘S COMPANY

rendering issues.

Page 17: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

GWTto the rescue

Page 18: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

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

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

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

LOGO SPEAKER‘S COMPANY

stop! no more GWT introduction stuff

please...

Page 24: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

so what makesGWT so fast?

Page 25: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANYis it magic?

Page 26: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

deferred binding.

Page 27: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

only payfor what you see

Page 28: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

Page 29: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

LOGO SPEAKER‘S COMPANY

modularize.

DOMImplIE6

DOMImplMozilla

DOMImplSafari

DOMImpl…

DOM

Page 31: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

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

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

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

LOGO SPEAKER‘S COMPANY

deferred binding.[ dependency injection ]

Page 37: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

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

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

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

LOGO SPEAKER‘S COMPANY

deferred binding.[ generators ]

Page 43: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

LOGO SPEAKER‘S COMPANY

GWT REFLECTION VS JAVA REFLECTION

TypeOracle oracle = generatorContext.getTypeOracle();

Page 46: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

deferred binding.[ demystified ]

Page 47: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

LOGO SPEAKER‘S COMPANY

deferred binding.[ use case: form generation ]

Page 50: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

LOGO SPEAKER‘S COMPANY

deferred binding.[ pages versus modules ]

Page 53: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

SEARCH

100%

SEARCHEDIT

95%

ACCOUNT

5%

Page 54: GWT@Jazoon08 - Part 1/6 - First Impressions Count

LOGO SPEAKER‘S COMPANY

extreme graphics.

Page 55: GWT@Jazoon08 - Part 1/6 - First Impressions Count

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

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

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

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

LOGO SPEAKER‘S COMPANY

MAARTENVOLDERS.comPASSIONATE ABOUT PEOPLE AND TECHNOLOGY