Cet article est le premier d’une série publiée à l’origine en anglais sur mon blog personnel. Ray Ryan a fait le buzz l’an dernier à Google I/O 2009 avec sa présentation des Meilleures Pratiques pour l’Architecture de votre Application GWT (Google Web Toolkit Architecture: Best Practices For Architecting Your GWT App). Mais ce qui a peut-être fait le plus de bruit était sans doute moins ce qui a été dit que ce qui n’a été que brièvement évoqué : le Place Service. Depuis lors, de nombreux développeurs (moi y compris) se sont essayés au concept, mais Google l’a finalement intégré dans GWT 2.1, sorti récemment.

Qu’est-ce qu’un lieu ?

Dans n’importe quelle application, les applications web en particulier, qui n’ont que rarement recours au concept de fenêtre (et si vous voulez mon avis, les développeurs d’applications web devraient s’efforcer de faire de ce « rarement » dans un « jamais »), on se situe par une notion de lieu (place en anglais): « où suis-je ? », « aller à … », etc. (d’ailleurs, j’ai bien utilisé le verbe « se situer », et on utilise également couramment « s’orienter », « se diriger », ou encore « naviguer »).

Des exemples de lieux incluent : votre boîte de réception, les résultats de recherche pour « GWT Places », le profil de l’utilisateur « t.broyer », la note de frais référencée « abcdefgh », etc.

L’idée est donc d’utiliser cette notion de lieu pour gérer la navigation dans l’application, en se basant sur des événements de « changement de lieu ».

Le PlaceService ici sert de pont entre ces événements et la gestion d’historique du navigateur (ceci mériterait un article complet, mais disons qu’il s’agit de rendre effectifs les boutons « page précédente » et « page suivante » du navigateur, tout en conservant l’application sur une unique page web). Le PlaceService est, et doit rester, le seul composant de l’application qui gère l’historique du navigateur et réagit à ses changements.

Démystifier les idées fausses

Avant d’entrer dans les détails, mettons certaines choses au clair : les lieux n’ont rien à voir avec le pattern MVP, et rien à voir avec la notion d’un bus d’événements global à l’application (qui n’a lui non plus rien à voir avec MVP). Vous pouvez utiliser chacun d’eux de manière totalement indépendante. Il devient monnaie courante de tous les utiliser en même temps, mais chacun répond à des besoins différents. Cela signifie également que vous n’avez pas besoin de comprendre ces autres concepts dont Ray Ryan a parlé dans sa présentation (MVP, bus d’événements, command-pattern pour les RPC, etc.) afin de comprendre les places.

Alors à quoi cela ressemble-t-il dans GWT 2.1?

GWT 2.1 matérialise le PlaceService à deux niveaux d’abstraction (lieux et activités, places et activities), et l’intégration optionnelle avec d’autres fonctionnalités de GWT (History pour l’instant, et RequestFactory à venir dans une prochaine version), sous la forme des modules com.google.gwt.place.Place et com.google.gwt.activity.Activity respectivement.

Le cœur des places GWT 2.1 est le PlaceController, que vous utiliserez pour naviguer de lieu en lieu, mais nous allons commencer par examiner ce à quoi une place ressemble dans GWT 2.1 et ce qu’elle représente.

Qu’est-ce qu’une place GWT 2.1?

Dans GWT 2.1, les places sont des objets légers qui étendent la classe abstraite Place. Elles sont généralement jetables et immuable, même si cela n’est pas obligatoire ; et il y a quelques bonnes raisons d’utiliser des places non jetables, comme nous le verrons plus tard (je ne vois par contre aucune raison pour avoir des places modifiable).

Vous pouvez définir autant de sous-classes de Place que nécessaire, associées ou non à des « données » (l’identifiant d’un enregistrement, la requête d’une recherche, etc), et vous créerez une nouvelle instance à chaque fois que vous naviguerez dans votre application. La classe Place ne définit aucune méthode, mais les sous-classes doivent implémenter correctement les méthodes Object.equals(Object) et Object.hashCode().

Présentation du PlaceController

Le PlaceController est un objet qui gère la place actuelle (où vous êtes) et la navigation entre les places. Vous ne devriez donc jamais avoir plus d’une instance PlaceController par application.

Pour permettre à votre application de réagir à des changements de lieux (pour mettre à jour l’interface utilisateur et l’état de l’application de sorte qu’elle reflète la nouvelle place), le PlaceControler déclenche des événements sur un bus d’événements. Vous n’avez pas besoin de vraiment comprendre la notion de bus d’événements pour poursuivre la lecture ; disons simplement que, au lieu d’enregistrer vos gestionnaires d’événements sur le PlaceController lui-même, vous les ajouterez à un autre objet (le bus d’événements, dont soit dit en passant il ne devrait également y avoir qu’une unique instance par application), et vous initialiserez le PlaceController afin qu’il lance ses événements sur ce bus.

Le point d’entrée de votre application contiendra donc généralement ce genre de code :

  EventBus eventBus = new SimpleEventBus();
  PlaceController placeController = new PlaceController(eventBus);

Par défaut, le PlaceController est initialisé avec pour place actuelle Place.NOWHERE (en d’autres termes, placeController.getWhere() retourne Place.NOWHERE). Pour naviguer vers un autre endroit, vous passerez une place à la méthode goTo du PlaceController, par exemple :

  placeController.goTo(new MyPlace());

Cela aura pour effet de modifier l’emplacement actuel, puis de lancer un PlaceChangeEvent sur le bus d’événements, événement que vos composants vont écouter en enregistrant un PlaceChangeEvent.Handler :

  eventBus.addHandler(PlaceChangeEvent.TYPE, new PlaceChangeEvent.Handler() {
    public void onPlaceChange (PlaceChangeEvent event) {
      Place newPlace = event.getNewPlace();
      ...
    }
  });
Où aller maintenant?

Ce n’était qu’un aperçu du cœur des places GWT 2.1, afin que vous puissiez saisir les concepts sous-jacents.

Je parlerai de la confirmation par l’utilisateur de la navigation, de l’intégration avec l’historique du navigateur (ce qui signifie aussi des places enregistrables en tant que favoris/bookmarks dans le navigateur), et des activités (une API de plus haut niveau qui, entre autres, aide à l’utilisation du pattern MVP) dans les prochains articles.