uni.sherbrooke 2015 créez la meilleur application grâce à gwt, gwtp et jukito

126
MEILLEURES PRATIQUES DE DÉVELOPPEMENT GRÂCE À GWT, GWTP ET JUKITO CHRISTOPHER VIEL CHRISTIAN GOUDREAU Département de Génie Informatique Université de Sherbrooke Juin 2015

Upload: arcbees

Post on 07-Aug-2015

239 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

MEILLEURES PRATIQUES DE DÉVELOPPEMENT GRÂCE À GWT, GWTP ET JUKITOCHRISTOPHER VIELCHRISTIAN GOUDREAU

Département de Génie InformatiqueUniversité de Sherbrooke Juin 2015

Page 2: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Christopher Viel

Lead DéveloppeurArcbees

+ChristopherVielArcbees

Christian Goudreau

BEOArcbees

+ChristianGoudreau@imchrisgoudreau

Page 3: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 1

Présentation d’Arcbees

Partie 2

Résumé du MVP Model-View-PresenterPartie 3

Survol de GWTP Framework MVP pour GWTPartie 4

Communication serveur Rest-Dispatch

Slides disponibles à https://goo.gl/PBzmwL

Page 4: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 5

Tests unitaires Exemples avec Mockito et JukitoPartie 6

Meilleures pratiquesPartie 7

GWT 3.0

Slides disponibles à https://goo.gl/PBzmwL

Page 5: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 1

ArcbeesArchitectes de la Simplicité

Page 6: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 1 Arcbees

Page 7: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 1 Arcbees

Page 8: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Notremission

Créer des produits permettant à nos clients, nos abeilles et la communauté de développeurs d'optimiser leurs processus, habitudes et façons de penser,en créant continuellement de la valeur et en transformant la façon dont ils travaillent.

Partie 1 Arcbees

Page 9: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Originede Arcbees

Afin d'améliorer leur efficacité de production, les deux cofondateurs ont conçu GWT-Platform, un outil open source de création d'applications web doté d'une incroyable capacité d'adaptation accélérant la vitesse de développement des applications.

Partie 1 Arcbees

Page 10: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 11: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Évolutionrapide

Rapidement, GWT-Platform a généré une importante demande de soutien de la part de ses utilisateurs et les deux entrepreneurs n'ont eu d'autres choix que de créer officiellement Arcbees le 16 juillet 2010 afin de répondre à ces requêtes.

Partie 1 Arcbees

Page 12: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Reconnaissance

de Google

En moins d'un an, Google a remarqué la jeune entreprise qui a été invitée à donner une conférence au Google I/O, puis, en 2012, Christian a été nommé sur le Comité de direction de GWT, groupe en charge de la direction et de l'évolution du framework.

Partie 1 Arcbees

Page 13: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 1 Arcbees

Page 14: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 15: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 16: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 17: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 18: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 19: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 20: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 2

MVPModel View Presenter

Page 21: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Model : Définit les données qui seront ultimement gérées dans l’interface utilisateur.

➢ View : Affiche le modèle pour l’utilisateur. Généralement passive: seulement de la logique d’affichage. Délègue les interactions utilisateur (events) au presenter.

➢ Presenter : Récupère et met à jour le modèle. Interprète le modèle les données pour les transférer à la vue.

Partie 2 MVP

MVP

Page 22: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Caractéristiquesdu MVP

➢ Couplage faible entre les différentes couches.

➢ Flot très simple, presque linéaire.

➢ Communique exclusivement au moyen d’interfaces.

➢ Vue passive. Ne prend aucune décision et notifie le presenter.

Partie 2 MVP

Page 23: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 2 MVP

MVP

Page 24: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 2 MVP

MVCcomparéà MVP

Page 25: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Quand l’utiliser➢ Idéal lorsqu’un interface utilisateur est

nécessaire pour contrôler l’application.➢ Pratique lorsqu’il y a beaucoup d’édition

de données (formulaires, CRUD, etc.)➢ Simple à mettre en place lorsqu’une

communication entre client - serveurest requise.

Partie 2 MVP

Quandl’utiliser

Page 26: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Quand l’utiliser

➢ Simple à tester : Le faible couplage permet de bien isoler les couches.

➢ Réutilisation de code plus aisée : Le flot plus simple et l’utilisation intensive d’interfaces permet de mieux extraire le code réutilisable.

Partie 2 MVP

Les bénéfices et les désavantages

Page 27: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Quand l’utiliser

➢ Flexible : Il est facile de remplacer n’importe quel composant tant qu’on respecte le contrat défini par les interfaces.

➢ Peut se combiner à d’autres design patterns.

Partie 2 MVP

Les bénéfices et les désavantages

Page 28: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Le grand nombre d’interface à gérer augmente la complexité du code. Les IDEs modernes aident néanmoins à atténuer ce problème (détection des implémentations).

➢ La vue passive introduit beaucoup de code boilerplate: beaucoup d’aller-retour entre le presenter et la vue.

Partie 2 MVP

Les bénéfices et les désavantages

Page 29: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 3

Survol de GWTPFramework MVP pour GWT

Page 30: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Repose sur GWT et GIN (GWT INjection).➢ Abstraire la gestion du pattern MVP,

mais aussi imposer son utilisation.➢ Abstraire la gestion cliente: initialiser l’

application, navigation, communication avec le serveur.

➢ Réduire le code à écrire habituellement requis en GWT.

➢ Optimisations: Proxy, code splitting...

GWTP

Partie 3 GWTP

Page 31: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Permet un découplage plus poussé et rend le code plus modulaire (DIP, IoC). ○ Aide à atteindre de meilleures

pratiques,○ Classes immutables,○ Créer de nouvelles dépendances

devient plus simple : Extraction de code vers des collaborateurs (SRP).

➢ Tend à rendre les tests plus simples: Jukito, GuiceBerry…

➢ En bref : Aide à atteindre les principes SOLID

Injectionde dépendances

Partie 3 GWTP

Page 32: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Limiter le code redondant à écrire qui est habituellement requis en GWT.

➢ Séparer les phases d’initialisation en phases logiques simple à étendre ou remplacer.

➢ Permet d’utiliser l’injection de dépendances plus tôt dans le programme.

➢ Configuration initiale à un seul endroit.

Références : DefaultModule, PreBootstrapper, Bootstrapper

Initialisationde l’application

Partie 3 GWTP

Page 33: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Initialisation et Bootstrapper

Configuration via le module GWT

public class ClientModule extends AbstractGinModule { @Override protected void configure() { install(new DefaultModule.Builder() .defaultPlace(NameTokens.LOGIN) .errorPlace(NameTokens.LOGIN) .unauthorizedPlace(NameTokens.UNAUTHORIZED) .build());

install(new ApplicationModule());

bind(ResourceLoader.class).asEagerSingleton(); }}

<?xml version="1.0" encoding="UTF-8"?><module> <inherits name="com.gwtplatform.mvp.MvpWithEntryPoint"/>

<source path="client"/> <source path="shared"/>

<set-configuration-property name="gwtp.bootstrapper" value="com.arcbees.demo.client.DefaultBootstrapper"/> <extend-configuration-property name="gin.ginjector.modules" value="com.arcbees.demo.client.ClientModule"/></module>

Bootstrapper (facultatif!)

Configuration via GIN

public class DefaultBootstrapper implements Bootstrapper { private final PlaceManager placeManager;

@Inject DefaultBootstrapper(PlaceManager placeManager) { this.placeManager = placeManager; }

@Override public void onBootstrap() { // Initialize states then reveal the app: placeManager.getCurrentPlaceRequest(); }}

Page 34: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Permet de réagir à différents stimuli provenant d’ailleurs dans l’application.

➢ Permet d’éviter de coupler des classes qui n’ont aucun point commun.

➢ Implémentation générique et de l’Observer.

Références : addRegisteredHandler, addVisibleHandler, @ProxyEvent

Plus de détails: https://blog.arcbees.com/?p=699

Évenements(GWT, EventBus)

Partie 3 GWTP

Page 35: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Isoler le comportement du presenter pour chaque phase de sa vie.

➢ Comportements isolés donc plus simple à tester unitairement.

Lifecycle(GWTP)

Références : onBind, onReveal, onReset, onHide, onUnbind, prepareFromRequest

Partie 3 GWTP

Page 36: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Aperçu des méthodes du lifecyclepublic class EditManufacturerPresenter extends PresenterWidget<MyView> { interface MyView extends View { }

@Inject EditManufacturerPresenter( EventBus eventBus, MyView view) { super(eventBus, view); }

@Override protected void onBind() {}

@Override protected void onReveal() {}

@Override protected void onReset() {}

@Override protected void onHide() {}

@Override protected void onUnbind() {}}

Page 37: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Gère la navigation entre les places. Beaucoup de code à écrire autrement.

➢ Offre plusieurs façons de présenter le token : le hash dans l’URI, après le #.

➢ Possibilité de rediriger vers une même page lorsqu’un token inconnu est accédé. Page 404 à-la GWTP.

Références : PlaceManager, PlaceRequest, TokenFormatter

Navigation(GWTP)

Partie 3 GWTP

Page 38: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Utiliser le Place Manager

Révéler un name tokenprivate final PlaceManager placeManager;

@InjectEditManufacturerPresenter( EventBus eventBus, MyView view, PlaceManager placeManager) { super(eventBus, view);

this.placeManager = placeManager;}

@Overridepublic void cancel() { PlaceRequest placeRequest = new PlaceRequest.Builder() .nameToken(NameTokens.MANUFACTURERS) .build(); placeManager.revealPlace(placeRequest);}

Récupérer le name token courantprivate final PlaceManager placeManager;

@InjectHeaderPresenter( EventBus eventBus, MyView view, PlaceManager placeManager) { super(eventBus, view);

this.placeManager = placeManager;}

@Overrideprotected void onReset() { PlaceRequest currentPlace = placeManager.getCurrentPlaceRequest(); String currentNameToken = currentPlace.getNameToken();

getView().setActiveMenuItem(currentNameToken);}

Page 39: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Permet de configurer et restreindre l’accès à certains tokens.

➢ Possibilité de configurer un gatekeeper par défaut.

➢ Permet de rediriger vers une même page lorsque qu’un accès non autorisé est détecté. Page 401 à-la GWTP.

➢ Attention: Si la page protégée par un gatekeeper accède à des ressources serveur, le serveur doit lui aussi protéger ses ressources!

Références : Gatekeeper, GatekeeperWithParams, @UseGatekeeper, @GatekeeperParams, @NoGatekeeper, @DefaultGatekeeper

Sécurité(GWTP)

Partie 3 GWTP

Page 40: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Utiliser un Gatekeeper

Gatekeeperpublic abstract class AclGatekeeper implements GatekeeperWithParams { private final CurrentSession currentSession;

private Set<String> permissions;

@Inject AclGatekeeper(CurrentSession currentSession) { this.currentSession = currentSession; this.permissions = new HashSet<>(); }

@Override public GatekeeperWithParams withParams(String[] params) { permissions = new HashSet<>(Arrays.asList(params)); return this; }

@Override public boolean canReveal() { return currentSession.isLoggedIn() && currentSession.hasPermissions(permissions); }}

Utilisation du Gatekeeperpublic class EditGroupMembersPresenter extends Presenter<MyView, MyProxy> { interface MyView extends View { }

@ProxyStandard @NameToken(NameTokens.EDIT_GROUP_MEMBERS) @UseGatekeeper(AclGatekeeper.class) @GatekeeperParams({"GROUPS_UPDATE", "MEMBERS_UPDATE"}) interface MyProxy extends ProxyPlace<EditGroupMembersPresenter> { }

/* snip */}

Page 41: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Le coeur des fonctions de GWTP :○ Accès au lifecycle,○ Gestion centralisée des événements○ Possède une vue,○ Communication vue vers presenter via

un UiHandlers.➢ Permet de développer

des composants réutilisableset testables.

➢ Permet de définir des Slots pour imbriquer d’autres PresenterWidgets.

Références : PresenterWidget, UiHandlers, View, OrderedSlot, SingleSlot, Slot

PresenterWidgets

Partie 3 GWTP

Page 42: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Un PresenterWidget

Le PresenterWidgetpublic class DashboardPresenter extends PresenterWidget<MyView> { interface MyView extends View { }

static final Slot<PresenterWidget<?>> SLOT_TEMPLATE = new SingleSlot<>();

private final Presenter<?, ?> presenter;

@Inject DashboardPresenter( EventBus eventBus, MyView view, Presenter<?, ?> presenter) { super(eventBus, view);

this.presenter = presenter; }

@Override protected void onBind() { setInSlot(SLOT_TEMPLATE, presenter); }}

Sa vuepublic class DashboardView extends ViewImpl implements MyView { interface Binder extends UiBinder<Widget, DashboardView> { }

@UiField SimplePanel template;

@Inject DashboardView(Binder uiBinder) { initWidget(uiBinder.createAndBindUi(this));

bindSlot(DashboardPresenter.SLOT_TEMPLATE, template); }}

Sa configuration GINpublic class DashboardModule extends AbstractPresenterModule { @Override protected void configure() { bindPresenterWidget(DashboardPresenter.class, DashboardPresenter.MyView.class, DashboardView.class); }}

Page 43: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Un PresenterWidget spécialisé.➢ Doit être associé à un proxy.➢ Initialisation uniquement lorsque

nécessaire: améliore le chargement initial.➢ Peut être associé à un name token (place).➢ Permet de définir des NestedSlots

pour imbriquer d’autres Presenters sans couplage.

Références : Presenter, NestedSlot, Proxy, ProxyPlace, @ProxyStandard, @NameToken

Presenter

Partie 3 GWTP

Page 44: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Un Presenter

Le PresenterWidgetpublic class DashboardPresenter extends Presenter<MyView, MyProxy> { interface MyView extends View { }

@ProxyStandard @NameToken(NameTokens.DASHBOARD) @UseGatekeeper(LoggedInGatekeeper.class) interface MyProxy extends ProxyPlace<DashboardPresenter> { }

static final NestedSlot SLOT_TEMPLATE = new NestedSlot();

@Inject DashboardPresenter( EventBus eventBus, MyView view, MyProxy proxy) { super(eventBus, view, proxy, ApplicationPresenter.SLOT_MAIN); }}

public class DashboardView extends ViewImpl implements MyView { interface Binder extends UiBinder<Widget, DashboardView> { }

@UiField SimplePanel template;

@Inject DashboardView(Binder uiBinder) { initWidget(uiBinder.createAndBindUi(this));

bindSlot(DashboardPresenter.SLOT_TEMPLATE, template); }}

Sa configuration GINpublic class DashboardModule extends AbstractPresenterModule { @Override protected void configure() { bindPresenter(DashboardPresenter.class, DashboardPresenter.MyView.class, DashboardView.class, DashboardPresenter.MyProxy.class); }}

Sa vue

Page 45: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Un PresenterWidget ayant un popup comme vue.

➢ Les mêmes avantages qu’un PresenterWidget: slots, lifecycle.

➢ Délègue l’affichage / masquage du popup au presenter.

➢ Abstrait le concept de positionnement du popup.

Références : PopupView, PopupViewImpl, addToPopupSlot, PopupPositioner

Popups

Partie 3 GWTP

Page 46: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Comunication ServeurRest-Dispatch

Partie 4

Page 47: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 4 Rest-Dispatch

Amené à disparaître dans GWT. Nécessite beaucoup de code pour un cas simple. Renforcit le couplage entre client et serveur. Plus simple de conserver le code client et serveur compatible.

RPC REST

Permet de communiquer avec n’importe quel API REST. Presque tous les serveurs permettent de faire du REST : à la mode. Plus facile de modifier l’API et oublier de mettre le code client à jour.

Page 48: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Implémentation partielle de JSR-311 1.1 (JAX-RS).

➢ Définition d’interface et configuration de l’API au moyen d’annotations.

➢ Code client (GWT) seulement. L’API doit être codé en utilisant une autre technologie.

➢ Possibilité de créer ses propres extensions.

Rest-Dispatch

Partie 4 Rest-Dispatch

Page 49: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Usage plus explicite que la syntaxe de base.

➢ Les interfaces et annotations peuvent être réutilisé sur l’implémentation serveur (DRY).

➢ Plus simple de conserver un API privé compatible à la fois sur le client et le serveur.

➢ Désavantage: Perte du type safety lors de la création de callbacks.

Extension :Delegates

Partie 4 Rest-Dispatch

Page 50: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Configurer et utiliser Rest-Dispatch

Le module GWT Les paths

Le module GIN L’interface de ressource

<?xml version='1.0' encoding='UTF-8'?><module> <inherits name="com.gwtplatform.dispatch.rest.delegates.ResourceDelegate"/> <inherits name='com.gwtplatform.mvp.MvpWithEntryPoint'/>

<source path="client"/></module>

public class ResourcesModule extends AbstractGinModule { @Override protected void configure() { install(new RestDispatchAsyncModule.Builder() /* Additional configurations */ .build()); }

@Provides @RestApplicationPath String applicationPath() { String baseUrl = GWT.getHostPageBaseURL(); if (baseUrl.endsWith("/")) baseUrl = baseUrl.substring(0, baseUrl.length() - 1);

return baseUrl + API; }}

public static class DashboardPaths { public static final String DASHBOARD_ID = "dashboard-id"; public static final String DASHBOARDS = "/dashboards"; public static final String DASHBOARD = "/{" + DASHBOARD_ID + "}";}

@Path(DASHBOARDS)public interface DashboardResource { @GET List<Dashboard> getAll(); @GET @Path(DASHBOARD) Dashboard get(@PathParam(DASHBOARD_ID) int id);

@PUT @Path(DASHBOARD) void update(@PathParam(DASHBOARD_ID) int id, Dashboard dashboard);}

Page 51: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Exemple: Configurer et utiliser Rest-Dispatch (suite)

Utilisation de la ressourcestatic final SingleSlot<PresenterWidget<?>> SLOT_TEMPLATE = new SingleSlot<>();

private final ResourceDelegate<DashboardResource> dashboards;private final DashboardTemplateFactory templateSelector;

@InjectDashboardPresenter( EventBus eventBus, MyView view, MyProxy proxy, ResourceDelegate<DashboardResource> dashboards, DashboardTemplateFactory templateFactory) { super(eventBus, view, proxy, ApplicationPresenter.SLOT_MAIN);

this.dashboards = dashboardService; this.templateFactory = templateFactory;}

@Overrideprotected void onReveal() { dashboards.withCallback(new AbstractAsyncCallback<Dashboard>() { @Override public void onSuccess(Dashboard result) { PresenterWidget<?> template = templateFactory.createTemplate(result); setInSlot(SLOT_TEMPLATE, template); } }).get(DashboardSettings.DEFAULT_DASHBOARD_ID);}

Page 52: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Tests unitairesTester GWTP et Rest-Dispatch avec Mockito et Jukito

Partie 5

Page 53: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 5 Tests unitaires

Jukito

Jukito permet à vos tests d’utiliser l’injection de dépendances. Peu importe le type de test — unitaire, intégration ou quoi que ce soit de loufoque —, le code redondant dû au mocking diminuera grandement. Rapidement, vous ne pourrez plus vous passez de sa syntaxe sécuritaire et basée sur les annotations!

Page 54: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

➢ Mocking automatique➢ Injection des mocks➢ Annotation @ALL➢ Léger➢ S'adapte à toutes tailles de test➢ Facile d’installation

Fonctionalités

Partie 5 Tests unitaires

Page 55: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

ExemplesSur GitHub

Mockito et Jukito:ManufacturerDetailPresenter: https://goo.gl/27NsKL

ManufacturerDetailPresenterTest: https://goo.gl/irq5rV

ManufacturerDetailPresenterMockitoTest: https://goo.gl/EIlj47

Jukito @All:PersonRenderer: https://goo.gl/o4UGZn

PersonRendererTest: https://goo.gl/uhcL2k

Partie 5 Tests unitaires

Page 56: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Mockito : Initialisation

CAS DE TEST TEST@InjectManufacturerDetailPresenter( EventBus eventBus, MyView view, MyProxy proxy, ResourceDelegate<ManufacturersResource> manufacturers, PlaceManager placeManager, EditManufacturerMessages messages) { super(eventBus, view, proxy, SLOT_MAIN_CONTENT);

this.manufacturers = manufacturers; this.placeManager = placeManager; this.messages = messages;

getView().setUiHandlers(this);}

public class ManufacturerDetailPresenterMockitoTest { // SUT private ManufacturerDetailPresenter presenter;

// Mocks (created by Mockito) @Mock private EventBus eventBus; @Mock private MyView view; @Mock private MyProxy proxy; @Mock private ResourceDelegate<ManufacturersResource> manufacturers; @Mock private PlaceManager placeManager;

@Before public void setUp() { // Create @Mock and @Captor fields. MockitoAnnotations.initMocks(this);

// Manual way to create a mock EditManufacturerMessages messages = mock(EditManufacturerMessages.class);

// Manual creation of the SUT. presenter = new ManufacturerDetailPresenter(eventBus, view, proxy, manufacturers, placeManager, messages); }

Page 57: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Mockito : Test

CAS DE TEST TEST@Overrideprotected void onReveal() { List<ActionType> actions; if (createNew) { actions = Arrays.asList(ActionType.DONE); } else { actions = Arrays.asList(ActionType.DELETE, ActionType.UPDATE); }

ChangeActionBarEvent.fire(this, actions, false);}

@Testpublic void onReveal() { // when presenter.onReveal();

// then // Manual way to create an argument captor ArgumentCaptor<ChangeActionBarEvent> captor = ArgumentCaptor.forClass(ChangeActionBarEvent.class);

verify(eventBus) .fireEventFromSource(captor.capture(), same(presenter));

ChangeActionBarEvent event = captor.getValue(); assertThat(event).isNotNull(); assertThat(event.getActions()).containsOnly(ActionType.DONE); assertThat(event.getTabsVisible()).isFalse();}

Page 58: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Jukito : Initialisation

CAS DE TEST TEST

@RunWith(JukitoRunner.class)public class ManufacturerDetailPresenterTest { // SUT (Injected by Jukito). We don't need to create all dependencies explicitly, Jukito will mock them. @Inject private ManufacturerDetailPresenter presenter;

// Mocks (injected by Jukito) @Inject private EventBus eventBus;

// Captors (Create by Mockito) @Captor private ArgumentCaptor<ChangeActionBarEvent> changeActionBarEventCaptor;

@Before public void setUp() { // Create @Mock and @Captor fields. MockitoAnnotations.initMocks(this); }

@InjectManufacturerDetailPresenter( EventBus eventBus, MyView view, MyProxy proxy, ResourceDelegate<ManufacturersResource> manufacturers, PlaceManager placeManager, EditManufacturerMessages messages) { super(eventBus, view, proxy, SLOT_MAIN_CONTENT);

this.manufacturers = manufacturers; this.placeManager = placeManager; this.messages = messages;

getView().setUiHandlers(this);}

Page 59: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Jukito : Test

CAS DE TEST TESTJukito: Test

@Overrideprotected void onReveal() { List<ActionType> actions; if (createNew) { actions = Arrays.asList(ActionType.DONE); } else { actions = Arrays.asList(ActionType.DELETE, ActionType.UPDATE); }

ChangeActionBarEvent.fire(this, actions, false);}

@Testpublic void onReveal_newManufacturer_preparesActionBar() { // when presenter.onReveal();

// then verify(eventBus) .fireEventFromSource(changeActionBarEventCaptor.capture(), same(presenter));

ChangeActionBarEvent event = changeActionBarEventCaptor.getValue(); assertThat(event).isNotNull(); assertThat(event.getActions()).containsOnly(ActionType.DONE); assertThat(event.getTabsVisible()).isFalse();}

Page 60: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Jukito : Utiliser @All pour tester plusieurs cas

CAS DE TEST TEST@InjectPersonRenderer( Messages messages, @Assisted Mode mode) { this.mode = mode; this.messages = messages;}

public String render(Person person) { String result = "";

if (person != null) { String firstName = person.getFirstName(); String middleName = person.getMiddleName(); String lastName = person.getLastName(); String title = renderTitle(person);

if (mode.isDisplayTitle() && !Strings.isNullOrEmpty(title)) { result += title + " "; } if (mode.isDisplayFirstName() && !Strings.isNullOrEmpty(firstName)) { result += firstName + " "; } if (mode.isDisplayMiddleName() && !Strings.isNullOrEmpty(middleName)) { result += middleName + " "; } if (mode.isDisplayLastName() && !Strings.isNullOrEmpty(lastName)) { result += lastName; } }

if (result.isEmpty()) { result = messages.unknown(); }

return result;}

public class PersonNameTestCase { private final Person person;

private Mode mode; private String expected;

public PersonNameTestCase() { person = null; }

public PersonNameTestCase( String firstName, String lastName) { person = new Person(firstName, lastName); }

/* Setters */

public Person getPerson() { return person; }

public Mode getMode() { return mode; }

public String getExpected() { return expected; }}

Page 61: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Jukito : Utiliser @All pour tester plusieurs cas (suite)

TEST TEST@RunWith(JukitoRunner.class)public class PersonRendererTest { public static class Module extends JukitoModule { @Override protected void configureTest() { bindManyInstances(PersonNameTestCase.class, new PersonNameTestCase("Zom", "Bee") .mode(Mode.SHORT).expected("Zom Bee"), new PersonNameTestCase("Zom", "Bee").title(Title.MR) .mode(Mode.SHORT).expected("Zom Bee"), new PersonNameTestCase("Zom", "Bee").middleName("Buzz") .mode(Mode.SHORT).expected("Zom Bee"), new PersonNameTestCase("Zom", "Bee").title(Title.MR).middleName("Buzz") .mode(Mode.SHORT).expected("Zom Bee"),

new PersonNameTestCase("Zom", "Bee") .mode(Mode.FORMAL).expected("Zom Bee"), new PersonNameTestCase("Zom", "Bee").title(Title.MS) .mode(Mode.FORMAL).expected("Ms. Zom Bee"), new PersonNameTestCase("Zom", "Bee").middleName("Buzz") .mode(Mode.FORMAL).expected("Zom Buzz Bee"), new PersonNameTestCase("Zom", "Bee").title(Title.MS).middleName("Buzz") .mode(Mode.FORMAL).expected("Ms. Zom Buzz Bee"),

new PersonNameTestCase() .mode(Mode.SHORT).expected(UNKNOWN), new PersonNameTestCase() .mode(Mode.FORMAL).expected(UNKNOWN) ); } }

private static final String UNKNOWN = "unknown";

@Injectprivate Messages messages;

@Beforepublic void setUp() { given(messages.unknown()).willReturn(UNKNOWN); given(messages.title(Title.MR)).willReturn("Mr."); given(messages.title(Title.MS)).willReturn("Ms.");}

@Testpublic void render(@All PersonNameTestCase testCase) { // given Person person = testCase.getPerson(); Mode mode = testCase.getMode(); PersonRenderer renderer = new PersonRenderer(messages, mode);

// when String result = renderer.render(person);

// then String expected = testCase.getExpected();

assertThat(result).overridingErrorMessage( "Expected %s with mode %s to be '%s'.", person, mode, expected) .isEqualTo(expected);}

Page 62: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Jukito : Utilitaires pour tester Rest-Dispatch

CAS DE TEST TESTpublic void onSave(ManufacturerDto manufacturer) { manufacturersDelegate .withCallback(new AbstractAsyncCallback<ManufacturerDto>(this) { @Override public void onSuccess(ManufacturerDto newManufacturer) { DisplayMessageEvent.fire(ManufacturerDetailPresenter.this, new Message(messages.manufacturerSaved(), SUCCESS));

PlaceRequest placeRequest = new Builder() .nameToken(NameTokens.MANUFACTURER) .build(); placeManager.revealPlace(placeRequest); } }) .saveOrCreate(manufacturerDto);}

@Testpublic void onSave_showsMessage_revealsManufacturers( EditManufacturerMessages messages) { // given ManufacturerDto manufacturer = new ManufacturerDto(); ManufacturerDto resultManufacturer = new ManufacturerDto();

givenDelegate(manufacturersResource) .succeed().withResult(resultManufacturer) .when().saveOrCreate(same(manufacturer));

given(messages.manufacturerSaved()).willReturn(A_MESSAGE);

// when presenter.onSave(manufacturer);

// then // note `isA` is used instead of `any`. This is because the event bus // accepts all `GwtEvent` subclasses. `isA` also verifies the type verify(eventBus) .fireEventFromSource(isA(DisplayMessageEvent.class),same(presenter)); verify(placeManager).revealPlace(placeRequestCaptor.capture());

PlaceRequest placeRequest = placeRequestCaptor.getValue(); assertThat(placeRequest.getNameToken()) .isEqualTo(NameTokens.MANUFACTURER);}

Page 63: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

GWTMeilleures Pratiques

Partie 6

Page 64: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Avoid widgetsas much as you can

BEST PRACTICE 1

Partie 6

Page 65: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

WIDGETSARE HEAVY.

BECAUSE

Partie 6

Page 66: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 67: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

TAKE CONTROL OF YOUR HTML!

Page 68: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 69: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 70: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 71: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Full Event Mechanism

BP 1 : AVOID WIDGETS AS MUCH AS YOU CAN

Partie 6

Page 72: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Even if you don’t need itFull Event Mechanism

BP 1 : AVOID WIDGETS AS MUCH AS YOU CAN

Partie 6

Page 73: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

How to attachevent handlerto elements ?

BP 1 : AVOID WIDGETS AS MUCH AS YOU CAN

Partie 6

Page 74: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 75: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Use widget

To encapsulate complex component to reuse

» prefer PresenterWidget if the componenthas a lot of business logic

» In the futur: Web Component.

BP 1 : AVOID WIDGETS AS MUCH AS YOU CAN

Partie 6

Page 76: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Cell widgets (CellTable, CellList…)

HtmlPanelExceptions

BP 1 : AVOID WIDGETS AS MUCH AS YOU CAN

Partie 6

Page 77: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Use anEvent Bus

BEST PRACTICE 2

Partie 6

Page 78: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Use DependencyInjection

BEST PRACTICE 3

Partie 6

Page 79: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Use MVP Pattern

BEST PRACTICE 4

Partie 6

Page 80: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Make Navigation Easy

BEST PRACTICE 5

Partie 6

Page 81: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Use directly your name tokens

BP 5 : MAKE NAVIGATION EASY

Partie 6

Page 82: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Use CSSas much as you can

BEST PRACTICE 6

Partie 6

Page 83: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Loas everythingyou can in the html page

BEST PRACTICE 7

Partie 6

Page 84: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

UNITTESTS

Partie 6

Page 85: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Test each protected and publicmethods of your presenters.

UNIT TESTS

Partie 6

Page 86: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 87: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 88: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 89: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 90: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 91: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

CODEREVIEW

Partie 6

Page 92: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Improve qualityof your code

CODE REVIEW

Partie 6

Page 93: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Detect Bugsearlier

CODE REVIEW

Partie 6

Page 94: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

A way to learnfrom your peers

CODE REVIEW

Partie 6

Page 95: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Web basedcode review system

CODE REVIEW

Partie 6

Page 96: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 97: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

CODE REVIEWBest practices

Partie 6

Page 98: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito
Page 99: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

TAKE CONTROL OF YOUR HTML!USE A STYLE GUIDE !

Page 100: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Address/fixall commentsbefore you merge.

CODE REVIEW Best Practice

Partie 6

Page 101: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

CONTINUOUSINTEGRATION

Partie 6

Page 102: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 103: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

The first to do code review is your CI Server

CONTINUOUS INTEGRATION

Partie 6

Page 104: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 105: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

EnforceCheck Style

CONTINUOUS INTEGRATION

Partie 6

Page 106: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

ACTORS

Partie 6

Page 107: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 108: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 109: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Designer

Partie 6

Page 110: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Web Integrators

Partie 6

Page 111: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Developpers

Partie 6

Page 112: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 113: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 114: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 115: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Partie 6

Page 116: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

SUCCESS

Partie 6

Page 117: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

GWT 3.0

Partie 7

Page 118: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Java 8 Support

Partie 7

Page 119: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

JSInterop

Partie 7

Page 120: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Export any Java codeto Javascript

JSinterop

Partie 7

Page 121: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Export any Javascript APIto Java

Partie 7

JSinterop

Page 122: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Subclassing JavaScript Objects

Partie 7

JSinterop

Page 123: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Web component Material design in GWT

Partie 7

JSinterop

Page 124: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

Start toexperimentwith GWT 2.7

» Turn it on with a flag

-XjsInteropMode

» Subject to change !

Partie 7

JSinterop

Page 125: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

MERCI

Page 126: Uni.sherbrooke 2015   créez la meilleur application grâce à gwt, gwtp et jukito

QUESTIONS ?