Google I/O 2009 – Best Practices for Architecting GWT App


Ryan:
Hello. My name is Ray. And I’ll be talking
to you today about GWT application
architecture best practices. We tried to find a drier title,
but this is the one that won. I am stunned, amazed,
and flattered that you all are here
when you could be eating lunch or learning about Wave, so thank you very much
for showing up. I was going to go
get lunch myself if you hadn’t. So, I’ll warn you also that all of my rehearsals
of this have run long. And I’ve responded to that
by adding more slides to the presentation,
so I’m probably going to do a lot of mumbling
and a lot of talking fast. And we’ll see where it goes. So what are we talking about
today? This is about
how to put together a nontrivial GWT application. Something that you
actually want to ship. Something that
you’re going to have more than two or three people
at a time working on without stomping
on each other’s toads. Toes. We’re going to look,
in particular, at the client side, because that’s where I tend
to pay attention. And what we’re really
exploring here are lessons that were learned
over the past year building the new AdWords
user interface. AdWords is a small product
at Google. You may have heard of it. And it’s recently been–
the user interface of that has been revamped
from the ground up as a GWT application. But first, let’s go to the last slide
of the presentation. If you take nothing else
away today, there are three things that you
really want to remember. First thing, which I’m not going
to talk about much at all, but still,
you want to remember it, get your browser history right,
and get it right early. One of the first things
that you should nail down on your app
if you want it to work is what the back button
and the forth button are going to do to your users, how they’re going
to be bookmarking things. GWT gives you a very nice
history library to take care of that, and if you apply it early,
it’s easy. If you apply it
after the fact, and try to retrofit it in,
not so easy. The next takeaway point
is you’re going to use an Event Bus as the backbone
of your application to let yourself–
let you make sure that the left hand of your app has no more
than a nodding acquaintance with the right hand
of your app. Preferably
through conversations brokered by
a neutral third party. And then finally, you’re going
to start saying to yourself, “DI + MVP FTW.” Which is to say,
dependency injection and the Model/View/Presenter
pattern for the win. And I promise that that’ll all
make a lot more sense in about 50 minutes or so. So let us start
with a demonstration of the app that I mentioned,
the AdWords UI. Which I, of course,
forgot to cue up. So give me a moment
to rectify that situation. Yeah. We might just blow off
this part of it if I can’t
get my act together here. There it is. And it has decided to reload. Good. So this is live right now. I’m looking
at the production site. If I run into glitches here,
there are people in ten countries
around the world, a number of users– which number I have been
cautioned not to disclose– but they’d notice. You can see that this is
a pretty traditional kind of table full of data
sort of app. But we’ve got
nice little widgets like the GWT Incubator
tree view, fast tree view, helping us guide our way
through things here. Our users are going to do things
using the paging scrolling table from the GWT Incubator to make
lots of edits of their data. Maybe several fields at once
in that kind of a thing. Or I might want to type around
and change my matching and change my CPC. I forget what that means,
actually, although this
is my live account. So I’m not going to actually
commit any of these changes that I’m making. They might take advantage
of the GWT visualization stuff that you might have
learned about yesterday to show graphs and such. There’s my pretty graph. I’m not doing so well, really. Maybe we’re going to compare
my click-through rate to the number of clicks
that I get and see if there’s
a correlation there. Yep, there is. So this is the app
that we’ve built with a team of more
than a few engineers. I really forget the handful,
but the sizeable handful has grown lately. And we’re all able
to commit changes to this and test portions of this without necessarily talking
to each other every day and destroying
each other’s code. So let’s get back
to the presentation. And before we get back
to the presentation, let’s get my speaker notes back, or this is going to be
a much shorter presentation. Dude, it all worked.
All right. So we’ve got three major themes that we’re going
to talk about here on your way to making
no bad apps the AdWords way. You’re going to embrace the asynchronous nature
of your app. You are an AJAX developer. And the first word in AJAX
is “asynchronous.” Let’s just not kid ourselves. You want to always be
decoupling your app. Like I said, the bit over here
and the bit over here just shouldn’t really know
much about each other. And finally,
you’re going to strive to achieve statelessness, so as various bits of your
infrastructure fall over, the other bits
aren’t bothered by it. So, embracing asynchrony. These Keynote builds, man.
I can’t get enough of ’em. Yes. The “A” in AJAX
is for asynchronous. There is nothing interesting
that you’re going to do in your application
that isn’t going to, at some point or another,
require some kind of an asynchronous callback. So you need to just
come to terms with that fact. You don’t want to spend
a lot of energy trying to create
little synchronous bits that you can call
once everything is swapped in, because you’ve got better things
to do with your time. And if you do it well, it’s really not
such a bad thing. So here’s an example of what you might start out
trying to do. Through the talk,
I’m going to assume that we’re writing
an address book application. A contact manager. Could you all turn your cell
phone ringers on, please? The first thing you’re going
to do as a good developer is you’re going to create
your data objects, your model objects
at the heart of your app. And at the heart
of an address book we have contacts. And my contacts have things
like a name field, and they have ContactDetails. ContactDetails
are an interface to cover phone numbers
and street addresses and mother-in-law’s birth date
and that sort of a thing. And the mistake
that we made here is that we are downloading
the kilobytes and kilobytes of ContactDetail information
at the same time that we’re downloading
our contact objects. At least,
that’s what I see implied here. That’s a mistake. The odds are that you want
to get your hands on that list of contacts
with as little information as you need as possible
to display them to your users, and then you want
to move on from there to fetch just the details
that the user cares about. So probably you want a structure
that looks more like this. My contact comes down
with a list of DetailIds. Some kind of opaque Id object. It’s probably
a string under the hood. But we’re all
Java developers here. We like our strong types. And that way
we don’t accidentally ask for a contact
with a phone number Id. Another small change
I made here, which is kind of sneaky, is that instead of using
a list of ContactDetails, doing the Josh Bloch thing
and correctly providing an interface
for my field name rather than the implementation
class name. I’m actually being very
straightforward about the fact that this is an ArrayList
that I’m looking at. I picked up this superstition
from a talk that I may have misunderstood
on optimizing GWT RPC. Where if you know that all
you’re ever going to send across the wire
are array list instances, you don’t want to give
the GWT RPC– the magic generator–
a chance to try to pick up every other possible
implementation of the list and accidentally compile that
into your app. Small point. So here we are, writing
everything asynchronously. And thinking to ourselves,
“This is really going to suck.” It doesn’t have to. If we wrap
our asynchronous calls and asynchronous operations
in the command pattern, life can be pretty good. A command pattern
is a kind of a thing you do where instead of having
a call for this– you know, a “do this” method
and a “do that” method and an “update the other”
method– we have objects
that embody such calls. So when it’s time for me
to get ContactDetails, I’ll make an instance
of getContacts command, and I’ll hand that off
to a command processor and receive back in return
a “got the contacts” response. Every action I want to take
with my app, I encapsulate into an object
like that. And because I have all of these
nice little command objects, I’ve got a nice unit
of currency for implementing caching
policies. Maybe whenever I see
the same GET request twice, I’ll cache away
the response I got last time and just return that to myself
immediately. Not bother
with a server-side trip. I’ve got a place where I can do
batching mechanisms. If I see five getCalls
in succession that aren’t interlayered
with updateCalls, I’ll have a timer going where I can collect
all of those guys and put them into one do this
group of operations command, send that over
to the wire, over the wire
in a single HTTP request, rather than sending them off
as bits of the app ask for them. I got a place that I can
centralize my failure handling. So that every time I’m making
one of these async calls, I can inherit the “oops,
something went wrong” behavior rather than having
to call it out in line there. This also, if I want to get a little bit forward-looking
about this, since I’m being honest
with myself about the asynchronous nature
of what’s going on here, I’ve done all of the hard parts
of chopping up my app into bits
that can be code split at GWT.runAsync points. I won’t go into detail
on GWT.runAsync, because I’m sure you’ve been
hearing about it for two days, but do it this way
and you’re halfway there. If you ever read a book
on “how I’m going to implement undo and redo
on my application,” the odds are the term “command pattern”
is going to come up. And you’re already working
that way. Because you’re so clever,
you’re halfway there. And then finally,
the work that you’ve done to isolate yourself
from all of this RPC. You’ve got a nice funnel point
at which you could slip in your HTML5 persistence
type of code when you decide you want to get
into offline work. So… And it shines your shoes too. So let’s look
at some actual code here, how we might implement
something like this. Are there any AdWords engineers
in the audience? I can say anything.
Okay. [audience laughs] They won’t actually recognize
this interface. It’s not exactly
what they do. But there are tools
that they created specifically for the project, which when you pull back
the hood, this is what’s going on there. So I assume most of you
are GWT developers or you would be off
looking at Wave. You probably recognize
the bottom half of this slide where we are defining
a GWT RPC service. When we’re working
in this style, we have a single service, and that service provides
a single call, which is basically
that “execute” word there. Do something for me, and then
return to me the response. What happened? And then the various somethings
that we want our app to do are going to implement
this Action interface, which we couldn’t call Command
because that word is taken by another GWT class. So an example
of an Action object that we might write
would be this GetDetails thing. Remember that we are working
on our address book, because the world doesn’t have
enough address books. The command will be something
as simple as I’ll instantiate the thing. I’ll give it a list of the Ids
of the details that I want. On the server,
I’ll do something clever to actually fulfill
that request and send back across the wire
a GetDetailsResponse object, which has this nice ArrayList
of the details that I can then
go and render. Now, I’m not trying to say
what the granularity of your operation should be
when you write your app. I’m implying
a pretty verbose world here where I’ve got 500 different
flavors of Get command, based on my 500 different
model objects. Maybe you want to do something
a little bit more generic and just have a single
Get something command that’s parameterized based on
the type that you’re fetching. Maybe it’s going to make sense
for your app to be more coarse-grained. Maybe you want
to write actions like, “Get me all the stuff I need to render
the first page of the UI.” The level at which you break
stuff down is up to you. I’m just trying
to pound home the idea that you’ve got objects
that embody what it is
you’re trying to ask for and the ways you ask for it. And I took that digression
one slide too early. We’ve had our…whoops. We have our action class. We have our response class. To make the code a little bit
more pleasant to deal with, we’re going to write
probably a third class which is a custom subclass
of the asynchronous callback that happens–is handed
to each GWT RPC call. This gives us a spot
to write failure handling that the application code
can inherit and not have to worry
its pretty little head about. Maybe we’ll pre-chew
the response a little bit to keep everybody
from having to write the Get, the Get, the Get,
the code to actually get the meat
of the response. So what I actually will end up
writing in my app when it’s time
to render a contact or something like that is a method like
this showContact thing. Where I somehow magically–
we’ll discuss it– got my hands on the service. I’ve called this execute method. I’ve given it an instance of the GetDetails command
that I want it to run. And I’ve instantiated
my callback GotDetails so that once I’ve got
all my information, I can call renderContact,
I can call renderDetails, and go mess with widgets
and stuff. As Java goes,
that’s fairly concise. We don’t have anonymous… we don’t have closures
and probably never will. But this is about as short
as it’s going to get in a Java sort of world. So, on with the theming. I mentioned that you want
to decouple your app. The whole left hand/right hand
don’t talk situation. The way that we’re going
to make that happen is the combination
of an Event Bus, using the MVP pattern when we have custom widgets
to implement, and by using
dependency injection, preferably via a tool
like Google GIN, which is derived
from Google Guice, which all of you–
all of you should be attending
the Guice tech talks that follow this one,
by the way, since you’re already
blowing off the Wave guys. Guice, Guice, Guice. Let’s go into depth
on each of those. Oh, the reason
that you’re going to do this is because it buys you things. Because your app
is nicely encapsulated, you’re going to be able
to throw away bits of it without the entire thing
falling over. You’re going to give yourself
a spot where you can delay,
as long as possible, the slow DOM operations that you might want to be–
required to perform. Your application logic
will be separated enough from your widget
and DOM manipulation logic that the slow things can happen
later or never. You’re going to find
that unit testing is a lot simpler to do. If I can–
if it’s very clear how I instantiate
this particular part of the app, it’s going to be easy for me to test
that particular part of the app without having to swap in
the other 500 parts of the app. And if I do this right, I’m going to have
really fast unit tests that I can execute in a JRE
rather than in a GWTTestCase. So unit tests that execute
in microseconds rather than in
the 20-whatever seconds it takes to launch GWTTestCase
these days. Which time we are improving,
let me say. But it’ll never be the same
as simply not doing it at all. So what’s an Event Bus? Let’s show you first
what an Event Bus is not. You’re writing your app
in a typical style, and you’ve probably
created yourself a bunch of model objects
in our address book that are probably contact groups
and contacts. And they got property lists. They’re throwing
property change events. Each one has
a list of listeners that are watching for changes
to the thing. And we’ll start adding in
bits of our UI. We’ve got our contact
group list UI, which is going to have
a listener attached to each one
of these group objects. And then we’ve got
the list of contacts within an individual group
that’s listening, attaching handlers–
event handlers to some of those contact guys. We probably have a display
with individual contacts that the list UI needs to know
how to swap in. And the contact list is going
to want to edit these things, and these are all going to be
listening to each other for update notifications,
you know, show yourself, hide yourself,
I’m done now. And then marketing comes in
and says, “We don’t have enough
bread crumbs on this thing, and that Window Title’s
looking kind of sloppy.” We got kind of
a messy world here. We’ve got a lot of handler
objects that we’ve instantiated. We’ve got a lot of things
that we can forget to decouple when it’s time
to tear things down. It’s not a fun world. I won’t even talk
about testing. It’s an excellent profile. So we can reduce this coupling
in a couple of steps. But first, we’ll introduce
our Event Bus. This thing
on the side of the app that everybody has access to,
where they can listen for the stuff that has happened
in the application that might be
of interest to them without necessarily
needing to know who was responsible for that
event in the first place. So, for example,
when the contact list UI wants to tell the world, “Hey, the user thinks that
it’s time to look at the details of contact X,” it can just post that event
to the Event Bus. And whatever parts of the UI
are responsible for actually showing
the user contact display, contact number X
can take care of doing that. And it doesn’t have to know
that it’s–this week, it’s the contact list UI
that’s responsible for doing that,
even though next week it’ll probably be
some other gesture that some UI designer– respected UI-designing
colleague– came up with. But you see we still have
a lot of mess in the middle there. We’ve got all these
property change listeners that I keep clearly implying I don’t think
you should have. And what I espouse
doing instead is just getting rid
of that model core. Not saying that you don’t have
model objects, just saying that they’re not
terribly of central importance. Instead, remember that we know
that everything that we do is asynchronous. Let’s just push
that asynchrony right through to the bottom
of our application. When the contact display UI
is ready to display somebody, it’ll tell the RPC service, “Hey, get me contact XYZ.
I’ve been told to display him.” With any luck,
that’s cached, and so my callback
fires right away, and I’ve got him immediately. When the editing UI needs
to mess with that contact, and change his data, he’s going
to tell the RPC service, “Hey, I’ve got an update
for you. Push that down to the service
for me.” When the response comes back in
to the RPC service, he will announce to everybody
who is interested, “A contact has changed. “Here is the new copy
of that contact. Why don’t you all who are
interested display that thing?” And everything is nicely
isolated from each other. So let’s look at what the code
would shape up as for that. You’ll remember
this showContact method that we wrote earlier. We’re going to add
a little bit to it. We’re going to start
paying attention to just which contact
we’re looking at at the moment over here
in our contact display UI. So just something as simple
as holding on to that Id object so that we know
who’s important to us. Before we ever tried
to show a contact, we attached ourselves
to the listener bus. Sorry, the Event Bus. We’re going to use a GWT class to actually instantiate
our Event Bus, because that’s simpler
than writing our own. With GWT 1.6, we revamped
our event handling mechanism. And at the heart
of each one of our widgets is a handy class
called the HandlerManager. There’s no reason
that you can’t use your own instance
of HandlerManager to provide your app-wide event
dispatch services. So our contact display
has somehow magically gotten its hand
on the HandlerManager Event Bus instance
for this app. And he’s attaching to it
a typical event handler. You’ve created for yourself
a custom ChangeEvent type called ContactChangeEvent. And you’re implementing your custom event handling
interface. So when a contact change
comes in, you’re going to look
at the new contact object that’s hanging off
of that event, see if it’s the one
that you’re actually displaying, and if so,
do something about it. And a subtlety here
is that you don’t really know if that’s the one and only
copy of this contact, if it’s one
that’s been handed to you for your purposes
at this moment. The contact goes from being
of central importance where you might be attaching
handlers to and from it to this kind of ephemeral,
disposable thing you can kind of wad up
and toss on the floor when you’re done. But don’t change it, ’cause other people
might be looking. Continuing with the code, let’s move over
to the RPC service itself. What we’re doing here is we have
wrapped the GWT RPC service that we defined
with somebody who’s implementing the interface itself. In this particular case, we’re taking that execute method
that our RPC service provides and we’re overloading it
to provide specialized handling of this UpdateContact
type of action. And the interesting bit is that
we are wrapping the callback that the caller gave us
with our own callback, which on a successful response
is going to update whatever kind of a cache
we’re maintaining. It’ll fire off
the real onSuccess result for the real callback, and then it’s going to tell
the rest of the application, “Hey, contact changed. You might want to do something
about that.” It’s as simple as that. So continuing
with our decoupling theme. I keep saying
“MVP, MVP, MVP.” And I did not say MVC. Now the odds are
that when you got out of the five or ten years
you spent doing JSP and Web 1.0 app, you kind of dusted off
some desktop knowledge or somebody who had once
done that kind of work told you, “You know
what we should really be doing “now that we’ve got
these widgets is model, view, controller.” And it’s this kind
of triangular thing. And the model throws events. And then the view throws events. And the controller
messes with both of them. And I forget what code
goes in the controller and what code
goes into the view. And no two people
will give you the same answer for what MVC actually means. There are a handful of guys
who wrote Smalltalk-80, but they may well be retired. You also wind up
with a problem here that, like I said,
some of your code landed in the controller. Some of it landed
in the view. You need to test it all. And the code that landed
in the view is not going to run
real fast. It’s messing with the DOM. And you either need to have
a pretend DOM there if you’re lucky,
which we don’t provide you– yet– or you need to fire up
a real DOM. And those tests are just not
going to run fast. So what you want to do instead is use the model, view,
presenter pattern. We found ourselves implementing
this style kind of by accident, just trying to isolate our code
from tests. And then some people
who are brighter than me were reading
Martin Fowler’s blog and saw that he had already
invented this pattern before most of us
were professionally active and had called it MVP. So we call it that too. Then what you’re doing
is just much simpler layering. Your view class
down there at the bottom is the only thing
that actually knows anything about DOM elements
and widgets. And it’s a source of things
like KeyboardEvent and ClickEvent and very
browser-specific events. The model at the top, we’re familiar with
at this point. It’s this kind of
overglorified bag of setters and getters
that we’re using because we decided
we don’t like property change listeners. And that leaves the presenter
in the middle as the only object
that has anything that’s really worth testing. This is the thing
that knows how to take, say, a contact in one end
and take its values and cram them into
a bunch of text fields on the other side,
listen for changes to those text fields, and interpret them
as something– as values to push back
into the model. When it comes test time,
we can ignore that silly little collection
of DOM widgets that we created and replace it
with a bunch of mocks. And in fact, we can even use
the GWT MockUtilities package, which I think was also
introduced in 1.6, to use something
like EasyMock or JMock–
or actually, there’s something called
Mockalicious now, which looks interesting– to provide fake test fields,
fake this and fake the other, and run them under a JRE. Although today I’m actually not
going to show you doing that, because I found that for
the pretend code that I’m putting together,
it was easier to do the mocks by hand. So let’s get concrete again. In our address book,
we are doing things like editing contact details. Say we’re going to edit
somebody’s phone number. So a phone number
looks like that, it’s got an Id,
it’s got the telephone number, and it’s got the work, home,
mobile, babysitter label. The UI probably looks
something like this. I’m sure we’ve all
seen that numerous times. And all
of the interesting stuff is here
at the presenter layer, where we’re going
to implement a thing called
the PhoneEditor, whose job in life
is to take a phone object in one end
and a phone UI in the other end and make them all go. So the PhoneEditor probably
looks something like this. At least it does
when I write it. Oh, the brace
is in the wrong place. Damn. It’s going to define
an interface for the kinds of widgets
it wishes it was talking to. And you’ll note
that I’m describing things like a save button
and a cancel button and a number field. But I’m not calling them
“button.” I’m calling them
HasClickHandlers and HasValue. These are characteristic
interfaces that the GWT widget set
is littered with. And if I define
my display interface in terms of these
characteristic interfaces, it becomes quite easy
at test time for me to provide
mock instances of those things. A lot of people think that
providing this display interface is more trouble
than it’s worth. And they will tend to give
their presenter objects actual knowledge
of the specific widgets, like text field,
like button. Not a big deal,
because you can, again, use EasyMock or its like to put in fake versions
of those in the JRE. But that made the slides
too big, so I didn’t do that today. So we’ve got
our display interface. How are we actually
going to use the thing? At some point in the lifetime
of our PhoneEditor, we’ll be handed
our display object, which–don’t tell anybody–
it’s a composite. We’ll hold on to that thing. We’ll attach a few handlers
to it. OnClick of the save button,
I want to call my doSave method. OnClick of my cancel button,
I’m gonna do my cancel method. Sooner or later,
somebody’s going to tell me to edit a phone number. And I’ll do that simply
by holding on to the phone instance
that I’m editing. I’m implying a kind of
sneaky thing there with that static method
on phone. I’m figuring that
the instance of phone that I’m editing
may not turn out to be the one that I actually want
to keep. And to make sure that I’m not
going to accidentally mess with the phone object
that other parts of the app might be trying to display, I’m going to assume
that I defined a kind of a clone style method
on my POJO. You can follow this convention
or make up something else. This is more or less
what we did, except our code was uglier. Once I’ve got this safe copy
of the phone, which I can toss away
when I’m done because model objects
aren’t special anymore, I’ll just tell my display
to show the number and update the label picker
and that kind of thing. Oh, there’s another cheat
that I’m doing in here. I have implied– head back
to our interface here– I have implied that GWT has
a pop-up widget that implements
the HasValue interface. It does not.
We ran out of time. I think it will have such
sooner or later. Maybe even in the 2.0 timeframe. I need to talk to my boss
about that. But in the meantime,
it is no big thing for you to write
your own HasValue wrapper around the list picker
as you’re going to use it. We did. And it didn’t take us
hardly any time at all. So full disclosure
out of the way. Now let’s actually save
what the user has done. Again, it’s a simple thing
to pull the values back out of
that display instance and then fire off my nice
asynchronous service method. When I hear back
that my POJO– my phone number
was updated successfully, I’ll tear myself down,
whatever teardown means for my PhoneEditor. If there were errors, I’ll have some error reporting and rendering convention
that I will have implemented, and I’ll display
those things there. Obviously,
I’m glossing over a lot. And you’ll call me on that
at question time. But until then,
I can just get away with this. So let’s talk about
dependency injection. I’m sure you’ve all heard
the term. And you’ve all been meaning
to adopt it, and it seems like a good idea, but maybe
on my next project. Dependency injection
ain’t no thing. It is just a pattern. All it means is that instead
of having global instances of my services
that I reach out for, like GetEventBus.singleton
instance, GetRPC.singleton instance. And instead of using
a service locator that I kind of cram full of every interesting
property of my app and shove it down the throat
of any part of the app that might want it, I’m very explicit, preferably via constructor
arguments, about just what it is
this particular object needs to exist in a useful way. DI is really not at all hard
to do manually. And in fact, AdWords does do
all of its DI manually, because we didn’t have any way
to do it automatically at the time
that we started the project. In the interim, there was a GWT developer
on another project… this is public. You know the contact manager
in the personal profiles that Google is starting
to flog these days? The group that put that together
were a big fan of the Guice dependency
injection framework for Java, and they wrote
their own version of it, called GIN. And now more and more apps,
internally and publicly, are taking advantage of that. You can find both Guice
and GIN at the URLs provided there. There are also talks coming up
on Guice right after this one, and if you leave this room, I suggest you go to that room. I’m not sure which one it is, but it’s on
your little badge-y thing. I had a picture
of Snoop Dogg here for the GIN and Guice thing, but the lawyers
wouldn’t let me do it. So, sorry. So what does the code
actually look like when we do something like this? Well, let’s start
at the bottom of it. Let’s assume
that we have a widget that is a widget
in the MVP style that is my contactViewer. And that’s kind of
the heart of my app. And when the contact viewer
is ready to go, it wants to get the root panel and just start
to jump into it. So what do I need to do to instantiate
my contactViewer? Well, I’m going to look
at its constructor arguments. It needs its ContactWidget, probably implementing
its display interface, because I wrote it. It’s going to need an instance of that PhoneEditor
MVP presenter thingy because it’s going to–
it uses that end line. It doesn’t go talk to it
through the Event Bus. Not everything needs to talk
to everything else through the Event Bus. Things that want to deal
with each other directly– there’s no reason
that they can’t have handles onto each other. We still like composition
in this world. It needs the RPC service
to ask for the contacts, and it needs the Event Bus
to listen for changes to the contacts
that it cares about. So it’s going to get its hand
on the ContactWidget with a simple “new.” It’s going to get
that PhoneEditor with a simple “new”–ooh. But the PhoneEditor
has dependencies too. It’s going to need a widget and it too needs its hands
on the RPC service. But we’re not really using the actual GWT generated
RPC service. We have our wrapping thing
around that. So let’s instantiate
our CachedBatching rpcService, into which we will jam
the one that we GWT.created to do the real work. And then finally,
everybody seems to want this Event Bus thing, so we’ll instantiate
one of those. So that’s kind of a lot of code, but it wasn’t really
hard to look at. Part of the payoff
starts to come when new dependencies appear. Marketing has heard about
this Google Voice service, and they’re
absolutely convinced that we should have
Google Voice integration with the PhoneEditor. So we’re going to add that by instantiating
the voice service. We’re going to change
the PhoneEditor constructor. And nobody else
knows about that change. Even though the PhoneEditor
is fairly far down in our tiny little stack, the thing that needs
a PhoneEditor because it never
instantiated it itself doesn’t need to know that PhoneEditor
now needs the VoiceService. And I didn’t have to add
a VoiceService argument and a VoiceService argument
and a VoiceService argument at every level in my code. But still, you can see
that this is going to grow into a lot of kind of
grungy code to maintain, and a big list
of instantiation to do all at the top. If you were to use
a framework to do it, something like GIN–
talk– Actually, there’s no talk
about GIN itself today. I don’t want to imply that. But there is a talk about Guice. And GIN is just like Guice,
but on the client side. Anyway,
if you use GIN correctly, and using it correctly
is easier than using it incorrectly, the code winds up
looking like this. So I highly recommend it. Now why are we doing
all of this stuff? What’s the punch line? Besides having the app
isolated from itself for that purposes, we’re particularly happy
because this gives us easy to write
and fast tests. So to write a test
in this style, we need our mock objects. We’re not using EasyMock here, so we’re just implementing
these things ourselves. We’re going to make stuff
that looks like this. I’m going to have
a mock version of my ContactsService. And it’s going to have
these fields here, the lastAction
and the lastCallback, and I’m going to fill those
at obvious times. When somebody gives me a pretend
execute this object, execute this action call,
I’ll hold on to it so that my test code
can take a peek. Throughout
the code examples here, I’ve been leaving off things like public and private
and so forth so on. On this slide,
that’s not pretend. I probably would have
package access or even public access to the fields
on this mock object because there’s not
a lot to be gained. By having accessor discipline, I wind up
with more concise code. We’re going to need
a few more mock objects as we’re working through here. So I’m going to have to have a nice fake version
of that ClickEvent. Because for reasons
that I don’t remember, we decided you shouldn’t be able
to do new ClickEvent. But let’s not worry
about that. We have a mock version
of the thing that has ClickHandlers. This is our pretend button. It’s got the same notion
of the last ClickHandler that was added to me. I’ll hold on to it
so that people can find it. When I’m told to… Does this do anything else
interesting? Nope. Yeah, in fact, the fireEvent,
it doesn’t even do anything. It’s a no-op.
Our tests don’t tend to do that. Similarly, we had
our HasValue thing. We’ve got a mock version
of that that’ll hold on
to the last value that was set into it. It also,
because I have access to… Never mind. That’s not a point
worth making. And then finally,
we’ll put together a bigger, more interesting
composite mock object, the thing that implements
our PhoneEditorDisplay. So where we would have needed
a phone editing widget, remember that our PhoneEditor
presenter wants a phone edit widget. We gave it a nice instance
of MockPhoneEditorDisplay, which is made up of
MockHasClickHandlers and some MockHasValues. Oops. Oh, well. Some fake accessor methods
for those, and again,
nice visible fields so that the test
can play with it. So that’s a lot of work
that we had to do for what’s going to be a test
for three lines of code. On the other hand,
the three lines of code will probably be
more interesting in real life when I need to test, say, “Did I warn the user
that they’re about to abandon their changes when they navigate
away from this page?” And when I have tests
for the cancel path and for the save path, all of these guys
are eminently reusable. In fact,
you might be asking yourself, “Why doesn’t the GWT team
provide me “with a prerolled
MockHasValues and MockClickHandlers?” And yeah,
we should probably do that. So on to the test itself. We’re going to put together
our mock world. We’ve got our fake service. We’ve got our fake display. We’re creating
our fake phone object that we wanted to be editing. And we’re setting–actually,
it’s a real phone object that we wanted to be editing. And we’re setting up
another one for how we expect
the “after” phone object to look that we’re going
to send across the wire for comparison purposes. We’re going to instantiate
the PhoneEditor, the thing that we actually
want to test here. We’re going to tell it
“Go edit this phone number,” just like we would tell it
in our real code. And then we’re going to sneak
into our mock objects. We’re going to tell
the labelPicker, “Okay, the user typed ‘work.'” And we’re going to tell
our number field, “This is the phone number
she provided.” And then we’re going to tell
the fake save button, “Do a click for me now, okay?” That should have been enough
to kick off our presenter object,
the PhoneEditor. And now we’re going
to verify all of that. We’re going to sneak
into our service. We’re going to see what action
it actually requested. We’re going to make sure
that it was an instance of UpdatePhone,
based on this expected… Oh.
That’ll work, actually. It should’ve been
UpdatePhone before, but they’re equivalent because they have
the same contactId is the idea. And I did run this test. It compiles and passes. Buh-buh-buh-buh-buh. And then we get out
of the action. The phone object that was
actually sent across the wire, we compare
the interesting bits of that with what we expected to see,
and our test works. So, um…
oh, blew the transition. There we go. So finally, I talked about
you wanting to have statelessness going on
in your app. And what
I’m talking about there is you want to have
a lot of disposability. When your server falls over, your user doesn’t want
a notice about it. What I’m saying here is, you really do want
to have stateless servers. And in particular, the–doing anything interesting
based on the session, the Servlet session object
on your server, is just a bad idea. It’s a fine thing
to use for caching. Caching is a wonderful thing. But anything– If you’re coming
from a JSP background and you’ve written
a multi-step wizard– you know, step one,
step two, step three– there’s a good chance
that you implemented that via some kind of session object
on your server. And your user’s sort of
halfway through your wizard when the server falls over
or its refresh time– they’re all screwed. Or you wrote something
really confusing and difficult to maintain
to try to bounce that session state
from one server to another, and that was more trouble
than it was worth and pagers go off and stuff. Don’t do that anymore. You’ve got a browser now.
You’re an AJAX developer. The browser provides
all the server state, all the server session
you actually need. So that means that when
it comes time for rolling updates
and servers are falling over and new ones
are taking their place, or it means that at your desk, when you need to restart
your server because you rejiggered
some of the business logic code, what’s going on
in your browser doesn’t even need to notice
that that happened. Maybe some calls will be
a little bit slower because the cache fell off. But otherwise you’re fine. If you’re developing
an App Engine app, you’ve got the Memcache package
that’s available for you which works really, really well
for this kind of thing. So we’ve got disposable servers. We similarly want to have
disposable clients. I’m afraid I’m going
to gloss over this more than it deserves, but the punch line here is, as I said
at the beginning, you want to get
your history right. As your user
is doing things that feel like navigating
around your app– you remember
in the AdWords demo, I was clicking
around the tree and clicking on–
navigating into different parts
of the app. Each one of those places
in your app wants to be embodied
by a GWT History token, so that as the user
hits that back button, she’ll return to where she was. If she hits the forth button,
she goes on. If she keeps a bookmark,
that bookmark actually works, and she returns to the space
where she was in the app. If you’ve done that right, you’ve got a disposable client. When the user hits F5, or you copy a URL
from one browser to another, it just works. Your development life
is happier. Your users are happier. That said, the History library
is in the traditional GWT way. It is a bit low-level. Making every bit of your app
knowing about History tokens, and knowing to listen
for OnHistory token change, and to try to push
History tokens if they want to change
is sort of nasty. And you want to come up
with some kind of an abstraction to isolate
the bits of your app from that kind of knowledge. What we did in AdWords
was we came up with a package called Place. It’s not open sourced. It wound up being
very ad-specific. But the pattern itself
is pretty straightforward. It pretty much winds up being,
just like I have command objects, action objects
to embody operations, I’ve got place objects to embody
addresses within my app. They’re kind of
incarnate bookmarks and each place object
knows how to talk to the History service,
to push tokens, and read tokens
and that kind of a thing. And it’s all integrated
into the Event Bus. So you remember this picture,
where all of my bits of my app are talking to each other. To introduce place management
into this, I’ll create something
called the place service, which is the only part
of the app that’s actually responsible for knowing about
the GWT History library. So when a bookmark
is pasted in, when the back button is hit,
when the forth button is hit, place service
notices about that. And it announces
to the rest of the app, “The user has changed places. Here’s the new place
that they’re going.” Maybe it represents
a contact. Maybe it represents a text ad
in AdWords. And the bits of the app
that need to swap themselves in or swap themselves out
can listen for those more semantic objects,
the place changes, and go on their merry way. I’ve actually run out of things
to talk about. Like I said, it always
ran long before. So I did talk faster. But we have ample time
for questions and answers now. So if people could line up
at the microphones, so I don’t have to try
to repeat your question and get it wrong, this would be
an excellent time. [applause] Thank you. man: I just wanted
to reiterate something you mentioned briefly,
that… about creating
some of these mock objects inside of GWT. And not so much a question,
but a hope that that is something
that would happen, because anything we can do
to make it easier for testability
and to get these designs right, I think that would really help
with adoption. Because in past projects,
we’ve tried to use it, and it’s really difficult
to get it right and to get the decoupling in. So if that was baked in
to just standard GWT, that would be, I think, a really, really
beneficial adoption part. Ryan: We totally agree. And we’re getting better– learning more
about that kind of thing as real people
build real applications inside of Google
and yell and scream at us. Before we get to actual changes
inside of GWT, one of the things that I’d hoped
to deliver today was a simple sample app that actually embodies
all of these practices. So if nothing else,
there’s code to point at and show people,
“No, do it that way.” And I’m going to try
to block out some time to actually finish that thing
and post it up on the GWT website
sooner or later. man: First I just wanted
to say thanks. All the things in this talk were definitely things
I’ve been struggling with. Ryan: Great. man: I was about halfway there, and this kind of–
going to help me fix things. I was just going to ask
about testing and mocking. I’ve seen a lot of discussions
back and forth about is it feasible
to test the GUI itself. So the techniques here
are great. I didn’t think about doing it
where you’re actually getting most of your code
out of the DOM and you’re just testing
everything else. But yet, let’s say
you’re trying to make a very complicated,
you know, interface. Drag and drop, resizing,
crazy stuff. Ryan: Yep. man: How do you test that? Ryan: Then you’re back
to a GWTTestCase. But, you know, it’s not like
GWTTestCase is poison. You’ve got a–kind of
a 20-second startup time to get it going,
but each individual test beyond that actually
runs pretty quickly. And as long as you’ve got… We’ve got a discipline
within Google about small, medium,
and large tests. And I think for a GWT app, that breaks down
into JRE-type unit tests are the small tests. You want those to be
about 70% of your test coverage in an ideal world. And GWTTestCases
are medium tests. The ones that, you know, they’re a little bit
more complicated, but they’re still not
involving setting up the entire world. If I’m writing a widget
that has enough DOM-based code that it’d be worth testing, I’ll write a sample app. Or just a display of that. And I’ll have a GWTTestCase
that drives that thing. And then the third part
of that puzzle, the large tests, for us, that tends to mean
Selenium tests, where I’m actually going
to put my entire app together– or maybe put together some
subpart of my app together if my app is too big
to want to fire it up every time I test
on everything– and have kind of
happy path tests that make sure that I can flow
through the entire app and off to other pages
and back again. That sort of thing. There’s also work being done under the Selenium umbrella
called WebDriver– which I think is going to be
rechristened Selenium 2.0– that provides
much better browser control. Actual little plug-ins that can go inside of IE
in particular. So that instead of having
to pretend to do a click and find that
you emulated it wrong, it will do
an honest-to-God click of an honest-to-God button. You can test off of that. So, 70-20-10.
Small, medium, and large. man: Would that new
Selenium stuff work in conjunction
with the in-browser hosting mode where it’s kind of
built in right now? Ryan: Yeah. man: ‘Cause the stuff
that’s in there now is kind of–
there’s docs on it, but it’s not really
well exposed. Ryan: We’re still getting
our story straight on how to get those all
to play well together. Another fun thing
that we started looking at is the HtmlUnit package. They’ve been, for quite
a while now, saying, “Hey, guys.
We work with GWT apps.” And we’re looking to actually
take advantage of that fact in GWT for you. So that when you do stuff
like run a GWTTestCase that doesn’t actually care
about accurate layout or that kind of a thing, you can talk
to the pretend browser in this HtmlUnit package and get faster execution
that way. But still even with that, the more you can isolate
application logic from view logic, the simpler and faster
your tests are going to be. man: We’re using the Event Bus
approach, partially. I’m curious what you do
if a bunch of objects that get put on it that aren’t
being used anymore– they’re basically
dead listeners that are added
but never removed. And how do you manage that? Ryan: Uh, badly. We don’t have weak references. This isn’t really Java.
It’s just a pretend Java. So you pretty much have to… It’s all developer discipline
of listening–well, actually, the place change event
simplifies that some. Because we’ve got that
at the heart of our app, widgets are able to hear, “I’m not relevant right now,
and so I’m going to– “When a place change happens, “and it’s not a place
that I live in, “I’m going to tear down
my Event Bus handlers and throw those away.” We…of all of the many
fascinating performance and memory problems
we have run into in the course of AdWords,
I don’t think that that one has proven to be
too big of a deal. I’d put that down to having
that kind of consistent place handling story. man: Okay, related to that, if I have multiple tables
and I have an object that’s interested in events
from one of the tables and you want to use
this Event Bus approach to communicate that, how do I know
which table it is without being
directly connected to them? Is there–have you guys
solved that problem? Without knowing
the object itself. Loosely coupling. Ryan: Yeah.
I’m not following the question. man: Maybe it’s too complex. Ryan: If you want to come up
afterward, we can hash it out. man: I just thought of–
the other question I had– So I went through the whole
property change listeners mess. And I’m looking forward
to getting rid of them. But how do you deal
with efficiency? Like, now you get an event
that this object changed. And you have to update
the UI to reflect it. But you don’t know exactly– if you knew, like,
this one field changed, you can just go
and change one field or move the corner over. But now all you know
is something changed. And how do you get around… Ryan: Well, I know this… I know the something
that it is that is actually interesting
to me. And you’ve got
more efficiency now, because instead of having
this one-to-one mapping of everything that wants
to listen to something and what they’re listening to, I’ve got a lot fewer
instances of handler. The execution speed,
I don’t think, has turned out to be
such a big deal. Especially if I’m good
about only listening while it makes sense
for me to listen. So if I’m
the tree of contacts, just, you know, then I’m
displaying all of them, well, every single
contact event is going to be
of interest to me. If I’m the editing UI
that’s only displaying a particular contact
at the moment, it’s very unlikely
that some other contact changed, because
I’m only one application. I’m not, like,
some kind of server handling all of the stuff. man: And what if there is… Our app has, a lot of times,
more than one view on the same object
in different ways. Ryan: But you’re still–
you’re usually not going to have
hundreds of views, right? There have–
two or three views, and those two or three views
will be listening and maybe will hear
some irrelevant stuff. I think that that’ll all
wash out. man: All right.
Thanks. Ryan: Hi. man: Yeah, my question is, you talked about
the importance of being able to bookmark
or refresh pages. So going with
the contact example, you know, it’s not just,
you know, good enough that I’m on, you know,
hit the back button and it knows I was at
the contact page. You know, I want
to hit the back button and know I was viewing, you know,
John Doe. And then I want to hit
the back button again and know, you know,
it was Jane Smith. So, you know,
I’m kind of wondering, like, in the HTML
or in the Web 1.0 or JSP world,
you would pass URL parameters. You know, with
a question mark Id. Ryan: That’s pretty much how the History library’s
implemented. Except everything winds up
after the hash mark rather than after
the question mark. So what you wind up doing is I’ve got
a subclass of place per type of object
that I want to be– that my location
is relevant to. So in the AdWords case,
we wind up with campaign places,
ad group places, and stuff like that. These place objects
know enough about the History
management system to provide
a History token string that includes the ad group Id
and the campaign Id. And so boom,
it’s right back there in the URL. man: And so then
does the place interact with the Event Bus,
so when it notices… Ryan: Yes. man: That a new Id was passed,
it triggers an event? Ryan: Exactly.
man: And notifies pages? Ryan: So we can go back
to our pretty picture here. That pretty picture. So the user hits the back button
or the forth button. The History event
hits the place service, which is where the code
that actually implements the History client interface
lives. The place service instantiates
a new little place object, which…let’s see. The place service might actually
talk to your RPC service to, you know, say,
“Get me this contact that is relevant
to the URL that I just had.” And then it will announce
to the world, “Hi, everybody,
we’re at a new place. And this is the contact object
that I found at that place.” Nobody else has to know
about the fact that it happened to live
on the URL or whatever else went on. man: And then, you know,
around your Event Bus, how–
I’m just kind of interested in how many different things that subscribe
to a single event, like, you know–
let’s say I have a tiered navigation,
you know, maybe. Or I have top navigation
and side navigation. So kind of pages
within pages with, you know– or in terms of GWT,
like a panel within a panel. You know, maybe I have,
you know, a bunch of tabs at the top. And I have a contact tab
and I have tabs on the left. I mean, does–
do you try and just subscribe to the event in one place
and then top down drive, like, “Hey, this was changed,” or do you have
multiple places– Ryan: No, it… People did start talking
directly to the Event Bus all of the time
for everything. And that was
kind of retrograde. If I’ve just got– It’s like
in the PhoneEditor example. The PhoneEditor… Or in the dependency injection
example. We created our contact display
and we gave it an instance of PhoneEditor display. PhoneEditor
didn’t have to know about navigation changes
within the app because it had
a really tight relationship with the contact display object
that needs to know how to edit phone numbers. There’s no reason for that
to go crazy with it there. So I don’t have
a pat answer for you. But I think it’s the… the top-level bits of the app that need to appear
and disappear are probably the ones
listening to, for example, place changes. Maybe other types of events–
you know, contact editing or whatever, maybe there you do
want to be a bit finer grained. But you kind of… It becomes a feel thing. I don’t really have
a simple answer. man: So have you guys
thought about just taking a simple app
like this and putting it out there
as an example? Ryan: Yeah, absolutely. man: ‘Cause, I mean,
you know, what’s out there, I think it was the sandbox
or the– Ryan: Yeah, um– man: It’s nice,
but it’s not really real-world scenarios. Ryan: I have been
reliably informed that I will be doing that. man: Well, thanks.
Appreciate it. [audience chuckles] man: Hi.
Quick question. I started recently using GWT,
and I really like it. My question is more about
the History button in general, since you’ve talked about
different design paradigms and patterns. Is History button really,
in your view, still a useful thing? Or not History button. The back button,
I’m sorry, I meant. Ryan: Oh, sure. man: Because now we’re talking more and more
rich applications. You know,
fancy applications. More like
desktop applications. You really–you know,
once you add– you may want
to let them delete it, but not necessarily delete
by going back, for example. So–
Ryan: I wouldn’t– You don’t want to let them
delete by going back. But…especially if you’re
doing an application like this, where at the end of the day,
it’s a big bag of objects and I want to navigate
around the space that that big bag of objects
defines, your users are used
to clicking on the thing and then
hitting the back button to get back to the place
that they were before. I’m certainly not suggesting
that you encourage– that the back button becomes
your undo mechanism. I think you’ll go insane. But you can’t stop your user
from hitting that back button. And it’s a pretty nice way to work your way
through a space. man: What we did in our app
is basically we would stop having
the back button at all. So as a result,
user get used to using in a different way. More like they’re used to using
a rich application. Ryan: I’ve never had the luxury
of working in an app where I was allowed
to take the back button away. So…but I wouldn’t want to. I mean, it’s… There’s a reason
that the Web browsers got shaped the way they did–
it feels really good. If you’re–I mean–not every app
is this kind of an app. I don’t know if the back button
really makes sense for Lombardi, where they’re, you know,
doing more– I’m doing
a big diagramming thing. But for an app like this, I think it’s pretty natural. And it’s not something
to hide from. man: Thank you. man: When you build the UI
in GWT, it’s very developer-centric,
usually. It’s basically Swing. It feels like that
when I’m building a UI. But usually, UI designers
want to make it with mark-up. So there was some talk
a while ago about a declarative UI. I may have missed it
if that came out. But what do you use
for AdWords, and are there– Ryan: We use declarative UI.
man: Yeah? Ryan: The code’s there.
It exists. It’s called UiBinder now. Its documentation
is all public, to make it painfully obvious that we haven’t actually
released the code itself. We are trying to actually
get it out there, and it’s just been a question
of too few engineers being pulled
in too many dimensions. But yeah, UiBinder is used
by AdWords. Wave uses it. And getting those guys
to ship has kept managing to trump actually open sourcing
the thing. It will go out. There’s also, in AdWords,
there’s some code that we rolled to try to–
I implied a lot of Glue there. Of…here’s my phone object,
here’s my string display, copy the string to here,
copy the string back, and, you know,
that kind of stuff. We managed to generate
some amount of that code in AdWords. We weren’t super thrilled– or I wasn’t super thrilled
with what we came up with. But we’ve got notions there too of frameworks
we’d like to provide to kind of minimize that need. But I don’t have
particular promises or particular dates to say. We’re aware of it
as an issue. And we’ll get there. man: Hi.
Thank you for your talk. Ryan: Thank you. man: So the application
that we work on, we’ve done something
similar to this with something that roughly
translates to the Event Bus. But we don’t have all the other
constituent pieces talking to the services. Instead, they–
there’s, like, this back and forth
propagation of events. And can you comment
on why that would be– Ryan: If it’s working for you, I wouldn’t tell you
to change it just for the sake of changing. We…this worked nicely
for us because it… I think we have no more events
than we actually need traveling around the place,
and… Again, you know,
for the testing and for configuration purposes, the contact list
can stand on its own without having to know
who, actually, it will be calling
into display contacts and that kind of a thing. If you don’t have a problem, there’s no reason for you
to find a solution. So…
man: All right, thank you. Ryan: Yeah. Hi. man: Hi. One of the
classic patterns that people use
while writing UI code, especially
in JavaScript libraries like YUI
and other things like that, is having data objects,
i.e. beings, that they can then take
into a widget that is able to take
that data object and using
a reflection-like mechanism of one sort or another
display things into the widget. Manipulate the data, potentially even edit it
then spew it back out. There’s nothing like that
today in GWT, and I’m suspecting
very strongly that you guys internally
at Google have some way
of dealing with this for the large apps
that you have. And what are your plans
in the future with respect to this? Ryan: We do have kind of
part of that in AdWords. Other teams… AdWords is the… maybe the only app, or one of the only apps
at Google, that’s actually
this kind of classical, J2EE-style app. And so we don’t tend
to have broad solutions for those types of things. We have the solution
that AdWords rolled for their particular needs. You’ve probably seen
some borderline flame fests on the GWT contributors list
about data binding and the need
for doing something about this. The approach
that we have taken is where you would have used
reflection, we will decorate
bits of our UI with annotations, with the name
of the particular property of the model object
that that part of the UI wants to display, and we can generate the code that would have been
reflection-based for–this text field
is tied to the name property. Oh, this thing looks
like a JavaBean and it has a GetName method. I’ll GetName, I’ll call SetName
at appropriate times. We want to make that better to generate
more of that code than we’re generating
right now. And there’s also
similar problems that are coming up
on the server side with AppEngine
and the ORM objects that you’re probably
persisting through JDO. A lot of people have found
that they’ve created these crafty little objects that get all nice
and persistent for them on the server side,
and then they try to serialize them
for GWT RPC, and that doesn’t work, and how do I get around that without making
separate copies and calling set and get
and get and set back and forth? I think there’s going to be
a similar solution to that, but we don’t– We haven’t quite
come upon it yet. But we are
thinking about it actively. I’m sorry, Fred,
I was just told I have to shut up now. So thanks, everybody. [applause]

Danny Hutson

Leave a Reply

Your email address will not be published. Required fields are marked *