Social Web
Wat is dit? Vanaf deze pagina kunt u gebruik maken van de Sociale Web links om GWT MVP, waar te beginnen? op te slaan naar een sociale bookmarking site, of het E-mail formulier gebruiken om een link te verzenden via e-mail.
del.icio.us |
Digg |
Furl |
Netscape |
Yahoo! My Web |
Technorati |
Google Bookmarks |
Newsvine |
BlinkList |
reddit |
Blogmarks |
ma.gnolia |
Tailrank |
Windows Live |
Linkedin |
Geplaatst op 12 February 2010, 12:13 door Pascal Janssen in java, open source, rich internet applications
Voor degene die GWT nog niet kent, GWT is een webapplicatie framework
ontwikkeld door Google om snel en relatief gemakkelijk een applicatie te
ontwikkelen die draait in je browser. Programmeren doe je in GWT m.b.v.
Java en als je klaar bent zorgt GWT ervoor dat een en ander wordt
"gecompiled" naar JavaScript. Gevolg? Een dynamische webapplicatie die
in je browser werkt met pure JavaScript en HTML zonder extra benodigde
plugins.
Maar goed, hoe begin je nou met een GWT applicatie? Na het doorworstelen van enkele mooie stukjes proza (o.a. van Google zelf) kom je tot de volgende set hulpmiddelen die je wordt aangeraden om te gebruiken. Om te beginnen, het Model-View-Presenter pattern. In tegenstelling tot het bekendere MVC die een soort driehoeksverhouding voorstelt, is MVP een hiërarchische kolom waarbij de view het domme ding is die GUI items kan tonen. De presenter bevat de view logica en haalt zijn data uit het model en update dit zonodig. Deze praat met de view d.m.v. een interface die definieert wat een view moet "kunnen". De presenter is dus eigenlijk "the man in the middle".
Verder raadt Google aan gebruik te maken van een eventbus (in GWT echter weer een HandlerManager geheten), dependency injection d.m.v. Google Gin (afgeleide van Google Guice) en een implementatie van een command pattern om te praten met je server. Deze laatste twee zijn weer stof voor twee aparte blogposts opzich (hou de blog in de gaten!), dus ik ga me hier beperken tot een poging tot uitleg van MVP en de eventbus met eigen events. Hiermee kom je al een heel eind.

Net als ik zijn ook andere mensen zo slim geweest om te kijken naar de presentatie
van Ray Ryan over dit topic, zo heeft iemand bijvoorbeeld al een GWT MVP
framework met boilerplate code in elkaar gezet. Dit kan gebruikt worden
om je presenters en views op te baseren zodat een aantal zaken al voor
je worden afgehandeld, echter brengt dit framework een aantal
eigenaardigheden met zich mee, zoals een PlaceManager class terwijl deze
eigenlijk het zelfde doet als de History class van GWT zelf. Een en
ander is echter ook goed zelf te schrijven, zonder de overhead.
Een view die e.e.a. moet kunnen tonen kan er als volgt uitzien:
public HasText getMessage() {
return this.messageLabel;
}
public void showMessage() {
this.show();
}
...
}
Zoals je ziet implementeert de FeedbackView netjes de display interface van de FeedbackPresenter. In GWT hebben veel widgets interfaces die in MVP gebruikt kunnen worden zonder dat de presenter iets over het daadwerkelijke widget weet. Zo zie je in dit voorbeeld dat Label de interface HasText implementeerd. In de view dienen verder alle widgets gezet te worden, maar geen verdere logica, die dient immers in de presenter te komen.
Het ontwikkelen met GWT vergt echter een andere denkwijze dan
ik in eerste instantie gewend was. GWT is niet paginagebaseerd waarbij enkele
pagina's stukjes dynamische content hebben, maar volledig
dynamisch waarmee je werkt binnen 1 en dezelfde pagina. Alle data die je
van de server nodig hebt haal je asynchroon op. Je zult er dus rekening
mee moeten houden dat je niet weet wanneer je gegevens binnenkomen,
sterker nog, je weet niet eens óf ze überhaupt binnenkomen nadat je een
request hebt gestuurd.
Maar goed, hoe begin je nou met een GWT applicatie? Na het doorworstelen van enkele mooie stukjes proza (o.a. van Google zelf) kom je tot de volgende set hulpmiddelen die je wordt aangeraden om te gebruiken. Om te beginnen, het Model-View-Presenter pattern. In tegenstelling tot het bekendere MVC die een soort driehoeksverhouding voorstelt, is MVP een hiërarchische kolom waarbij de view het domme ding is die GUI items kan tonen. De presenter bevat de view logica en haalt zijn data uit het model en update dit zonodig. Deze praat met de view d.m.v. een interface die definieert wat een view moet "kunnen". De presenter is dus eigenlijk "the man in the middle".
Verder raadt Google aan gebruik te maken van een eventbus (in GWT echter weer een HandlerManager geheten), dependency injection d.m.v. Google Gin (afgeleide van Google Guice) en een implementatie van een command pattern om te praten met je server. Deze laatste twee zijn weer stof voor twee aparte blogposts opzich (hou de blog in de gaten!), dus ik ga me hier beperken tot een poging tot uitleg van MVP en de eventbus met eigen events. Hiermee kom je al een heel eind.

Om te beginnen met de presenter, deze is niet geïnteresseerd welke views
hij dient aan te sturen. De presenter definieert echter wel de
mogelijkheden die een view dient te implementeren, d.m.v. een interface.
public class FeedbackPresenter implements
ExceptionHandler
...
public interface Display {
HasText
getMessage();
void showMessage();
}
public void onBind() {
this.registerHandler(this.eventBus.addHandler(ExceptionEvent.TYPE,
this));
}
public void onExceptionOccurred(ExceptionEvent event) {
this.display.getMessage().setText(event.getUserFriendlyMessage());
this.display.showMessage();
}
public void onExceptionOccurred(ExceptionEvent event) {
this.display.getMessage().setText(event.getUserFriendlyMessage());
this.display.showMessage();
}
...
}
De FeedBackPresenter is een presenter die graag geïnformeerd wil worden indien
er iets uitzonderlijks gebeurd in de applicatie. In de onBind methode
geeft de presenter bij de eventbus aan geïnteresseerd te zijn in
ExceptionEvents. D.m.v. de ExceptionHandler weet de FeedbackPresenter
hoe de ExceptionEvents dienen te worden afgehandeld. Wie een
ExceptionEvent afvuurt is verder niet van belang/interessant om te
weten. Daarnaast definiëren we dat views die aangestuurd willen worden
door de FeedBackPresenter op zijn minst een bericht moeten kunnen
teruggeven dat tekst bevat. D.m.v. de interface HasText weten we dat, en
kunnen we het bericht opvragen of wijzigen. Daarnaast dienen de views
het bericht te kunnen tonen op commando. De presenter is verder niet
geïnteresseerd hoe/waar een view het bericht toont.
Een view die e.e.a. moet kunnen tonen kan er als volgt uitzien:
public class FeedbackView
extends DialogBox implements FeedbackPresenter.Display {
...
private Label messageLabel;
...
private Label messageLabel;
public
FeedbackView() {
this.messageLabel = new Label();
// Geeft aan dat dialogBox gehide moet worden
// als er buiten de dialogBox wordt geklikt.
this.setAutoHideEnabled(true);
}
public HasText getMessage() {
return this.messageLabel;
}
public void showMessage() {
this.show();
}
...
}
Zoals je ziet implementeert de FeedbackView netjes de display interface van de FeedbackPresenter. In GWT hebben veel widgets interfaces die in MVP gebruikt kunnen worden zonder dat de presenter iets over het daadwerkelijke widget weet. Zo zie je in dit voorbeeld dat Label de interface HasText implementeerd. In de view dienen verder alle widgets gezet te worden, maar geen verdere logica, die dient immers in de presenter te komen.
That's all there is to it! Wat is nou het voordeel van een
dergelijke werkwijze? Ten eerste heeft GWT zelf al enkele voorzieningen
om te werken met MVP en de eventbus, waardoor het je gemakkelijk wordt
gemaakt om dit ook daadwerkelijk in te zetten.
Daarnaast, normaal gesproken als je GWT code gaat unittesten dien je te extenden van de GWTTestCase. Deze zorgt ervoor dat je code die GWT Widgets bevat kan testen. Het uitvoeren van een unittest die extends van GWTTestCase kan echter erg lang duren, omdat een GWTTestCase ervoor zorgt dat er een DOM en een javascript engine aanwezig is tijdens het uitvoeren van de tests. Deze zijn namelijk nodig voor de widget code. Door de widget code (view) en de view logica (presenter) uit elkaar te trekken kan de logica van de presenter getest worden zonder te extenden van GWTTestCase. De view die alleen widgets bevat kan gemocked worden d.m.v. de display interface die in de presenter gedefinieerd wordt. Gevolg, sneller draaiende unittests.
Daarnaast, normaal gesproken als je GWT code gaat unittesten dien je te extenden van de GWTTestCase. Deze zorgt ervoor dat je code die GWT Widgets bevat kan testen. Het uitvoeren van een unittest die extends van GWTTestCase kan echter erg lang duren, omdat een GWTTestCase ervoor zorgt dat er een DOM en een javascript engine aanwezig is tijdens het uitvoeren van de tests. Deze zijn namelijk nodig voor de widget code. Door de widget code (view) en de view logica (presenter) uit elkaar te trekken kan de logica van de presenter getest worden zonder te extenden van GWTTestCase. De view die alleen widgets bevat kan gemocked worden d.m.v. de display interface die in de presenter gedefinieerd wordt. Gevolg, sneller draaiende unittests.
Blijft natuurlijk de vraag, hoe koppel ik nu een view en
eventbus aan een presenter? Hier kom ik volgende keer op terug (tip:
Google Gin).
Top artikelen




