Google Developer Fest 2010

77
Chris Ramsdale Developer Relations, Google Google Web Toolkit Building Web Apps Sanely

Transcript of Google Developer Fest 2010

Chris RamsdaleDeveloper Relations, Google

Google Web ToolkitBuilding Web Apps Sanely

Between us and lunch

• Overview

• Deeper dive

• Optimizations for developers

• Optimizations for users

• Intro to GWT & MVP

From 25,000 feet

• Development toolkit, not a framework

• Code in Java, run as Javascript

• One codebase, any browser

• Makes Ajax a piece of cake...and faster

• Used within many Google products, including Google Wave and Ad Words

The GWT Family

GWT SDK Google PluginFor Eclipse

Speed Tracer

It’s a loving relationship

It’s a loving relationship

Develop

It’s a loving relationship

Develop Debug

It’s a loving relationship

Develop Debug

Optimize

Focus on the users

Our users - developers• Leverage existing IDEs and tools

• Minimize refresh time between codes changes

• Automate where possible

Your users - customers

• Minimize startup time

• Make it a comfortable experience

• Allow them to select the browser

Different Goals

Different Goals

Developers• Next killer feature

• Making it look good

• Code refactoring

Different Goals

Developers• Next killer feature

• Making it look good

• Code refactoring

Customers• Make it fast

• ...oh, and don’t charge my credit card twice

Different Goals

Developers• Next killer feature

• Making it look good

• Code refactoring

Customers• Make it fast

• ...oh, and don’t charge my credit card twice

No plugins required

VML Flash

Silverlight

Nothing against them, but...

Foo Player not available for your device

We restrict use of technologies required by products like Foo Player...

Quirkiness

14800 ms4836 ms1997 ms7148 msDOM manipulation

2469 ms1520 ms918 ms2477 msinnerText=...

-1386 ms908 ms-textContent=...

4078 ms2053 ms1276 ms2876 msTypical portable setInnerText()

IEOperaWebkit (Safari)Firefox

Quirkiness

14800 ms4836 ms1997 ms7148 msDOM manipulation

2469 ms1520 ms918 ms2477 msinnerText=...

-1386 ms908 ms-textContent=...

4078 ms2053 ms1276 ms2876 msTypical portable setInnerText()

IEOperaWebkit (Safari)Firefox

Improvement 39%32%29%14%

Quirkiness

14800 ms4836 ms1997 ms7148 msDOM manipulation

2469 ms1520 ms918 ms2477 msinnerText=...

-1386 ms908 ms-textContent=...

4078 ms2053 ms1276 ms2876 msTypical portable setInnerText()

IEOperaWebkit (Safari)Firefox

Improvement 39%32%29%14%

http://quirksmode.org/blog/

function getMax(values) { var maximum = values[0]; for (var i = 0; i < values.length; ++i) { if (values[i] > maximum) { maxinum = values[i]; } } return maximum;}

Can you find the bug?

function getMax(values) { var maximum = values[0]; for (var i = 0; i < values.length; ++i) { if (values[i] > maximum) { maxinum = values[i]; } } return maximum;}

Can you find the bug?

Hint: Javascript is a dynamic language

Our plugin can

Java is a static language

13

A Java to Javascript compiler right?

function rd(a,b){var c;if(b.b){b.b=false;b.c=null}c=b.c;b.c=a.f;try{++a.c;Cd(a.e,b,a.d)}finally{--a.c;a.c==0&&sd(a)}if(c==null){b.b=true;b.c=null}else{b.c=c}}function Hb(b,c){yb();$wnd.setTimeout(function(){var a=$entry(Eb)(b);a&&$wnd.setTimeout(arguments.callee,c)},c)}function ih(a,b){var c,d;if(b.e!=a){return false}try{Vg(b,null)}finally{c=b.f;(d=(hc(),c).parentNode,(!d||d.nodeType!=1)&&(d=null),d).removeChild(c);ki(a.b,b)}return true}function hj(c){if(c.length==0||c[0]>ao&&c[c.length-1]>ao){return c}var a=c.replace(/^(\s*)/,cn);var b=a.replace(/\s*$/,cn);return b}function qj(a){var b,c,d,e;b=0;d=a.length;e=d-4;c=0;while(c<e){b=a.charCodeAt(c+3)+31*(a.charCodeAt(c+2)+31*(a.charCodeAt(c+1)+31*(a.charCodeAt(c)+31*b)))|0;c+=4}while(c<d){b=b*31+a.charCodeAt(c++)}return b|0}function Bj(a){var b,c,d,e;e=this.v();a.length<e&&(a=Pd(a,e));d=a;c=this.p();for(b=0;b<e;++b){Ud(d,b,c.s())}a.length>e&&Ud(a,e,null);return a}function xl(a){var b,c,d;a.length<this.c&&(a=(c=a,d=Qd(0,this.c),Sd(c.aC,c.tI,c.qI,d),d));for(b=0;b<this.c;++b){Ud(a,b,this.b[b])}a.length>this.c&&Ud(a,this.c,null);return a}function Ud(a,b,c){if(c!=null){if(a.qI>0&&!ee(c.tI,a.qI)){throw wi(new ui)}if(a.qI<0&&(c.tM==gm||c.tI==2)){throw wi(new ui)}}return a[b]=c}function hi(a,b,c){var d,e;if(c<0||c>a.c){throw Qi(new Oi)}if(a.c==a.b.length){e=Rd(we,47,8,a.b.length*2,0);for(d=0;d<a.b.length;++d){Ud(e,d,a.b[d])}a.b=e}++a.c;for(d=a.c-1;d>c;--d){Ud(a.b,d,a.b[d-1])}Ud(a.b,c,b)}function th(b,c){var i;rh();var a,e,f,g,h;e=null;for(h=b.p();h.r();){g=fe(h.s(),8);try{c.q(g)}catch(a){a=Ge(a);if(ie(a,11)){f=a;!e&&(e=Fl(new Dl));i=Sj(e.b,f,e)}else throw a}}if(e){throw sh(new oh,e)}}function Tj(j,a,b,c){var d=j.b[c];if(d){for(var e=0,f=d.length;e<f;++e){var g=d[e];var h=g.y();if(j.x(a,h)){var i=g.z();g.A(b);return i}}}else{d=j.b[c]=[]}var g=Ul(new Sl,a,b);d.push(g);++j.e;return null}function bk(a){var b,c,d;if((a==null?null:a)===this){return true}if(!(a!=null&&de(a.tI,18))){return false}c=fe(a,18);if(c.v()!=this.v()){return false}for(b=c.p();b.r();){d=b.s();if(!this.u(d)){return false}}return true}function Cd(a,b,c){var d,e,f,g,h,i,j;g=b.j();d=(h=fe(Nj(a.b,g),4),!h?0:h.c);if(c){for(f=d-1;f>=0;--f){e=(i=fe(Nj(a.b,g),4),fe((Nk(f,i.c),i.b[f]),13));b.i(e)}}else{for(f=0;f<d;++f){e=(j=fe(Nj(a.b,g),4),fe((Nk(f,j.c),j.b[f]),13));b.i(e)}}}function Fb(a){var b,c,d,e,f,g;b=false;d=a.length;f=(new Date).getTime();while((new Date).getTime()-f<100){for(c=0;c<d;++c){g=a[c];if(!g){continue}if(!g[0].h()){a[c]=null;b=true}}}if(b){e=[];for(c=0;c<d;++c){if(!a[c]){continue}e[e.length]=a[c]}return e}else{return a}}function cf(){cf=gm;af={};bf=[];af[pn]=[lg,kg,mg];af[qn]=[tg,sg];af[rn]=[xg,wg];af[sn]=[Bg,Ag,Cg];_e(bf,se,pn);_e(bf,te,qn);_e(bf,ue,rn);_e(bf,ve,sn)}function Ok(a){var b,c,d,e,f;if((a==null?null:a)===this){return true}if(!(a!=null&&de(a.tI,4))){return false}f=fe(a,4);if(this.v()!=f.c){return false}d=Vk(new Sk,fe(this,4));e=Vk(new Sk,f);while(d.b<d.c.c){b=Xk(d);c=Xk(e);if(!(b==null?c==null:U(b,c))){return false}}return true}function Sg(a){var b;if(a.c){throw Ni(new Li,Rn)}a.c=true;a.f.__listener=a;b=a.d;a.d=-1;b>0&&(a.d==-1?_f(a.f,b|(a.f.__eventBits||0)):(a.d|=b),undefined);a.l();a.n()}

14

More like assembly-level JS

15

I can haz pretty print plz

Simply adjust the output style of the compiler via the plugin

function init(){ $GreetingService_Proxy(new GreetingService_Proxy); $add_0(($clinit_99() , get_0(null)), $Label(new Label, 'Foo')); $wnd.alert('foo');}

function caught_0(e){ if (e != null && canCast(e.typeId$, 11)) { return e; } return $JavaScriptException(new JavaScriptException, e);}

function $RemoteServiceProxy(this$static){ return this$static;}

function RemoteServiceProxy(){} 16

Yes, a Java to Javascript compiler

17

But wait...thereʼs more

18

Juan Carlos Campos MartínezDeveloper - GWT User

Don’t take my word for it

19

A deeper dive

From Eclipse to your browser

20

package com.google.gwt.samples.eclipsecon.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;

@SuppressWarnings("unused")public class EclipseCon implements EntryPoint {

public void onModuleLoad() { Window.alert("foo"); }}

CodeServer

JettyServer

Eclipse

Bro

wse

r Plu

gins

TCP

HTTP

package com.google.gwt.samples.eclipsecon.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;

@SuppressWarnings("unused")public class EclipseCon implements EntryPoint {

public void onModuleLoad() { Window.alert("foo"); }}

From Eclipse to deployment

21

Generators Translators LinkersYour code...

package com.google.gwt.samples.eclipsecon.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;

@SuppressWarnings("unused")public class EclipseCon implements EntryPoint {

public void onModuleLoad() { Window.alert("foo"); }}

From Eclipse to deployment

22

Generators Translators LinkersYour code...

Generators

23

Provide the power behind your GWT app

Automate away boilerplate code

Foundation for permutations

Use Case: GWT RPCs

24

Client XHR

Serialization Code

Server

Serialization Code

Typical Ajax call

Use Case: GWT RPCs

25

Client XHR

Serialization Code

Server

Serialization Code

GWT-enabled AjaxG

WT

Pro

xyG

WT P

roxy

Use Case: GWT RPCs

26

• Serialization code begone

• RPCs like theyʼre meant to be - interface methods

• Make it fast to boot

Goals:

@RemoteServiceRelativePath("suggest")public interface SuggestService extends RemoteService { String getSuggestions(String str) throws IllegalArgumentException;}

27

You write code that looks like this:

Use Case: GWT RPCs

28

Simple enough.

29

He’s an Ajax pro

package com.google.gwt.samples.eclipsecon.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;

@SuppressWarnings("unused")public class EclipseCon implements EntryPoint {

public void onModuleLoad() { Window.alert("foo"); }}

From Eclipse to your browser

30

Generators Translators LinkersYour code...

31

Javascript

Java

package com.google.gwt.samples.eclipsecon.client;

import com.google.gwt.core.client.EntryPoint;import com.google.gwt.core.client.GWT;

@SuppressWarnings("unused")public class EclipseCon implements EntryPoint {

public void onModuleLoad() { Window.alert("foo"); }}

From Eclipse to your browser

32

Generators Translators LinkersYour code...

33

Entry points for your GWT app

34

-gen will output a copy of the generated classes

GWT Tips and Tricks

GWT Tips and Tricks

-draftCompile• Skip all optimizations• Development only

Reduce optimizations, reduce compile time

GWT Tips and Tricks

-draftCompile• Skip all optimizations• Development only

Why worry about compiling at all?

Reduce optimizations, reduce compile time

A more efficient SDLC

Refresh Does it work?

Develop

No

Yes Compile

Deploy

37

We’re happy

38

But what about our users?

Optimize for the user

•Bundle resources•Split code

Resource Bundling

• Example - associating icons with a contact

Resource Bundling

Image image = new Image("images/image1.gif");image.setHeight("50px");image.setWidth("50px");imagesPanel.add(image);

One at a time

Resource Bundling

Initial download

Call to display images

Resource Bundling

public interface Resources extends ClientBundle { public static final Resources INSTANCE = GWT.create(Resources.class); @Source("Contacts.css") public ContactsCss contactsCss(); @Source("images0.gif") public ImageResource image0();

@Source("images1.gif") public ImageResource image1();

...

}

All at once

Resource Bundling

Call to display images

Initial download

Code splitting

Initial download

Not needed on startup

@UiHandler("showImagesButton")void onOkClicked(ClickEvent event) { GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { showImagesDialog(); } });}

Code splitting

Split points - runAsync()

Code splitting

Initial download

Call to display images

Real world results - Google Wave

26-Nov 29-Apr 18-Jun 28-Jul 12-Sep 27-Oct 24-Dec 16-Mar

Siz

e of

Initi

al J

avaS

crip

t Dow

nloa

d (K

B)

375

750

1125

1500

0

7x Decrease InInitial Download Size

1400 KB

200 KB

Creating GWT apps - “Direct” approach

Write a bunch of widgets with self-contained logic

Problems:• Hard to test - need GWTTestCase• Mocks not encouraged - harder to write smaller tests• Platform specific UI code - limits code reuse• Too many dependencies - difficult to optimize

Creating GWT apps - MVP approach

Goals:• Be practical• Avoid rigid patterns• Put the complex logic in your Presenters• Put the widget code in your Views• Make the Views as dumb as possible

Cast:• Model - DTOs, and business logic• View - The display• Presenter - Application logic

MVC

MVP

MVP

The MVP Relationship

Model Presenter View

The MVP Relationship

Model Presenter View

The MVP Relationship

Model Presenter ViewHistory

The MVP Relationship

Model Presenter ViewHistory

RP

C

The MVP Relationship

Model Presenter ViewHistory

RP

C

Cac

he

The MVP Relationship

Model Presenter ViewHistory

RP

C

Event Bus

Cac

he

The MVP Relationship

Model Presenter ViewHistory

RP

C

Event Bus

Cac

he

History

Event Bus

RP

C

The MVP Relationship

Model Presenter ViewHistory

RP

C

Event Bus

Cac

he

History

Event Bus

RP

C

View

Making the Cloud a Reality

Making the Cloud a Reality

Email

Calendar

Contacts

Sales Force Automation

CollaborationBankingSocial Network

Your next big idea

Making the Cloud a Reality

The right languages and tools are key

Making the Cloud a Reality