Silverlight WPF et la guerre des patterns Cyril CATHALA Architecte Sot Olivier NAVARRE Architecte Sot 08022011 Cédric DAVIAUD Directeur Technique Sot Sommaire Introduction Rappels ID: 364808
Download Presentation The PPT/PDF document "Mon application" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1Slide2
Mon application Silverlight/WPF et la guerre des patterns
Cyril CATHALAArchitecteSo@t
Olivier NAVARREArchitecteSo@t
08/02/2011
Cédric
DAVIAUD
Directeur Technique
So@tSlide3
Sommaire
IntroductionRappelsInversion of ControlMVVMApplication CompositePrésentation PRISM
SoPrism !PrésentationConseils pour bien démarrerDécoupageCommunication
OutilsValidation de donnéesSlide4
IntroductionSlide5
So@t en quelques mots …
SSII spécialisé dans le développement10 ans de savoir-faire .Net / Java220 collaborateursTous les métiers du développement3 ans d’expertise Silverlight / WPFSociété Générale, Dexia, Vente Privée, Canal+, M6, Radio France, Crédit Agricole, Eurosport, Sarenza.comSlide6
IntroductionApplication de référence «
HappyNet »Application composite Nos « Bonnes pratiques » Découplage ! Quickstart : Template SoPrism
Génération d’un squelette applicatifMise à disposition de briques techniquesSlide7
Inversion
of control
Rappels !Slide8
Inversion of control
Problématique :Dépendance très forte entre les classes composants / servicesRésolution :Déporter l’instanciation des dépendances des classes à un composant externe (Container)Slide9
Framework Unity
Container IoC : UnityContainerInjection de dépendancesConstructeurPropriétév2.0 - mai 2010
Microsoft Patterns & PracticesEnterprise Library Slide10
Framework MEF
Utilise un container IoC : CompositionContainerInjection de dépendancesConstructeurPropriétéInclus dans .NET 4 .0 / Silverlight
4.0Slide11
Unity vs MEF
MEF -
UnityEnregistrement de typesEnregistrement d’instancesCréation d’instance des types enregistrés uniquementInjection d’instances via constructeur / propriétésAttributs pour marquer types et dépendances
Résolution des dépendances dans un graphe d’objetsCe qu’ils font tous les 2 :Slide12
Unity vs MEF
Unity
MEFCentraliséDécentraliséRésolution de classes concrètes
sans enregistrementRésolution de
génériques
Interception
Nombreux retours d’expérience
Découverte
d’assemblies
à la
volée
Téléchargement
de XAP
Recomposition
à
chaque
nouvelle
découverte
Exporte automatiquement les types dérivés
Livré avec le Framework .NET
Ce qui les distingue :Slide13
Utilisation d’Unity
Exemples de codeConfiguration du Container :
Résolution :this.container.RegisterType<IMyView,MyView>();this.container.RegisterType<IMyView,MyView>( new
ContainerControlledLifetimeManager());IView
view
=
this.
container.Resolve
<
IView
>
();
Enregistrement d’un type
Enregistrement d’un singleton
Récupération d’une instanceSlide14
Utilisation d’Unity
Exemples de code (suite)public class
MyViewModel { public IMyView View { get; private set; } // Constructeur public MyViewModel
(IMyView view) { this.
View
=
view
;
}
}
// Exemple d’instanciation d’un
MyViewModel
MyViewModel
viewModel
=
this.
container.Resolve
<
MyViewModel
>
();
Par injectionSlide15
Model-View-
ViewModel
Rappels !Slide16
View
XAML
Code-BehindEvent HandlersModèle de donnéesSans Binding
Code behind Only :Slide17
Pattern MVVM
Problématique :Collaboration développeur / designer difficileTests fastidieux (plus que d’habitude !)Code-behind difficilement maintenables
Résolution :Utiliser le pattern Model-View-ViewModel !17Slide18
Pattern MVVM
View
XAML(Code-Behind)Modèle de données
ViewModelEtatOpérations
DataBinding
Commands
PropertyChanged
Web
Service
View.DataContext
=
ViewModelSlide19
Pattern MVVM
View (
xaml)ViewModel (cs)
Model (
cs
)
Interface utilisateur
Logique applicative
Persistence
de
données
Design pur
XAML seulement
Code-
behind
minimal
Basé sur un
UserControl
Data
Binding
vers la classe
ViewModel
(Presque) aucun gestionnaire d’évènements
Classe
adapteur
entre la vue et le modèle
« Englobe » le modèle pour le rendre exploitable par la vue
Notifications (implémente
INotifyPropertyChanged
)
Expose des
Commands
Se charge de la validation
Testable
Données pures
Pas de concepts visuels
Couche d’accès aux donnéesSlide20
Pattern MVVM : View First
DéfinitionLa View assigne le DataContext au ViewModelDisponible au design time (support de Blend)
Pas d’IoC possible en XAMLView<UserControl.DataContext> <my:PageViewModel
/></UserControl.DataContext>
En XAMLSlide21
Pattern MVVM : View First
D’autres méthodes d’affectation par le code…public MyView
(){ InitializeComponent(); DataContext = new MyViewModel(); }var
viewModel = new MyViewModel();var
view
=
new
MyView
(
viewModel
);
public
MyView
(
IMyViewModel
viewModel)
{
InitializeComponent
();
DataContext
= viewModel;
}
Dans le constructeur
A l’extérieurSlide22
Pattern MVVM : ViewModel First
DéfinitionLe ViewModel affecte le DataContext de la ViewMéthode préconisée
ViewModel pilote la ViewIoC possible et donc testableView Modelpublic MyViewModel(
IMyView myView){
myView.DataContext
= this;
}
Par le codeSlide23
Application CompositePrismSlide24
Composite Application Guidance
Microsoft P&P TeamGuidance & FrameworkOpen source (Codeplex)Composants pour construire des applications composites
Se base sur un conteneur IoCMVVM “compliant”Version 4.0Compatible Silverlight 4.0 / WPF 4.0 / WP7Prism - PrésentationSlide25
Prism – Pourquoi ?
Faible couplageConfigurabilitéComposabilitéMaintenance / lisibilité
Testabilité accrueMulti-platform (WPF / Silverlight / WP7)Slide26
Prism – Vocabulaire
BootstrapperInitialisation de la configurationShellRootVisual / MainWindowConteneur visuel principal
ModuleDécoupage vertical des fonctionnalitésSlide27
Prism - Bootstrapper
Lance le Bootstrapper
Initialise les servicesCharge les modulesInjection de dépendances
Gestion de régions d’affichageGestion de messages
RootVisual
MainWindow
Découpage vertical des fonctionnalitésSlide28
Prism – Services
Prism contient différentes briques techniques :Un gestionnaire de Module : > BootStrapper
Un gestionnaire de régions d’affichage : > RegionManagerUne implémentation de ICommand : > CommandDelegateUn gestionnaire d’évènements : > EventAggregator…Slide29
Template d’applicationSoPrismSlide30
SoPrism
Template applicatif se basant sur :Framework PrismPattern MVVMEt permettant :La génération d’un squelette applicatifDe concentrer des « bonnes pratiques »Slide31
SoPrism
Templates Visual Studio 2010Template de solution d’application SilverlightTemplate de Projet Module (Prism)Template de « bloc visuel » MVVMSnippets
ComposantsContrôlesInteractivité (Triggers/Actions/Behaviors)ValidationGestion des logsGestion des exceptionsConvertersSlide32
SoPrism
Shell
Infrastructure
Module
Module
Prism
Module
Vue
Vue
Vue
Vue
Vue
Vue
Services
Business
Data
Business
Data
Business
DataSlide33
Shell
Infrastructure
Module
Module
Prism
Module
Vue
Vue
Vue
Vue
Vue
Vue
Logging
Configuration
Logging
Helpers
Validation
Controls
Interactivity
Converters
Services
Business
Data
Business
Data
Business
DataSlide34
[ Démo ]
SoPrism : génération d’un squelette applicatifSlide35
Prism - RegionManager
Problématique :Une vue peut contenir d’autres vues : couplage fortRésolution :Confier l’injection d’une vue à un gestionnaire de régions d’affichageSlide36
[ Démo ]
SoPrism : Utilisation du RegionManagerSlide37
Comment bien découper son application ?Slide38
Hello Board !
DescriptionApplication composite de démonstration basée sur le Template SoPrismRespecte nos « bonnes pratiques »ScrumBoard en SilverlightSlide39
Hello Board !
Vocabulaire ScrumUserStory : fonctionnalitéBackLog : liste de fonctionnalitésTâche : partie de fonctionnalitéSprint : itération
ScrumBoard : tableau des tâches d’un sprintSlide40
[ Démo ]
HelloBoardSlide41
Définition des modules Besoin :
Découper l’application par modules applicatifs et par blocs visuels2 approches possiblesEn mettant en avant le visuelEn mettant en avant le métierSlide42
Définition des modules
Découpage orienté visuel
Module SprintModule User
VueUserList
Vue
UserSelection
Page
User Manager
Vue
UserDetail
Vue
Page
Scrumboard
Vue
Task
Vue
SprintSlide43
Définition des modules
Module Sprint
Module User
VueUserList
Vue
UserSelection
Page
User Manager
Vue
UserDetail
Vue
Page
Scrumboard
Vue
Task
Vue
Sprint
Injection
Découpage orienté métierSlide44
Hello Board ! Conception
Découpage orienté métierSlide45
Comment communiquer entre les couches ?Slide46
Gestionnaire d ’Evènements EventAggregator
View Model
View ModelView Model
View ModelView Model
View Model
View Model
View Model
FAIL!Slide47
View Model
View Model
View ModelView Model
View Model
View Model
View Model
View Model
Event Aggregator
Gestionnaire d ’Evènements
EventAggregatorSlide48
Gestionnaire d’évènementsEventAggregator
Problématique :Comment dialoguer entre 2 modules (classes) ne se connaissant pas ? Résolution :Confier la gestion d’évènements à un gestionnaire
Pattern Publish-SubscribeCouplage faible de la communication entre classesSlide49
Gestionnaire d ’Evènements EventAggregator
Comment transitent les données d’un module à un autre ?
SprintServiceData
UserService
Event Aggregator
Module
Sprint
SprintService
Reference
IdUser
Module
User
Vue
UserSelection
UserService
Reference
UserService.User
SprintService.User
Vue
TaskViewSlide50
Gestionnaire d ’Evènements EventAggregator
Exemples de code
public class UserSelectedEvent : CompositePresentationEvent<UserSelectedEventArgs>{}public class UserSelectedEventArgs { public int IdUser
{ get; private set; } public
UserSelectedEventArgs
(
int
idUser
)
{
this.
IdUser
=
idUser
;
}
}
Création d’un
CompositePresentationEvent
<
EventArgs
>Slide51
Gestionnaire d ’Evènements EventAggregator
Exemples de code
this.eventAggregator.GetEvent<UserSelectedEvent>() .Publish(new UserSelectedEventArgs(idUser));this.eventAggregator.GetEvent<UserSelectedEvent>() .
Subscribe(this.OnSelectedUser);
Publication d’un Event
Abonnement à un EventSlide52
[ Démo ]
Communication inter-moduleSlide53
ValidationSlide54
Validation
ValidationExceptions
IDataErrorInfoINotifyDataErrorInfo
Setter { throw
; }
Synchrone
Limité
à 1
erreur
par
propriété
Confusion entre
erreur
de
saisie
et exception applicative
Interface
Synchrone
Limité à 1 erreur par propriété
Compatibilité WPF
Interface
Asynchrone
Plusieurs erreurs par propriété, non limitées aux strings
HasErrors
: indique si actuellement valide ou non
Silverlight
4 «
compliant
»
3 approches possibles :Slide55
Validation
Interface INotifyDataErrorInfo
public interface INotifyDataErrorInfo{ bool HasErrors { get; } event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; IEnumerable
GetErrors(string propertyName);}Slide56
Validation Manager (SoPrism)
Exemples de code
this.validationManager.SetRuleFor(() => this.FirstName, new RequiredStringValidator(), "Merci de renseigner le prénom");this.validationManager.ValidateRules(() => this.FirstName);this.validationManager.ValidateAllRules
();Définition d’une règleValidation d’une règle
this.
validationManager
=
new
ValidationManager
(
RaiseErrorsChanged
);
InitialisationSlide57
[ Démo ]
Validation ManagerSlide58
Code source
Disponible sur Codeplex dès …
… maintenant ![ http://soprism.codeplex.com ]Slide59
[
http://happynet.codeplex.com ]
[ http://silverlight.soat.fr ][ http://blog.soat.fr ]
Quelques référencesSlide60
Merci à :
[ Nathalie Pettier ][
Nathanaël Marchand ]Slide61
Des questions ?
?Des réponses !Slide62
Merci !Slide63