di using mvvm & wpf
TRANSCRIPT
Dependency Injection using MVVM & WPFTraining / 2016-04-25
www.beemobile.se
Piotr Kundu• Lead Developer
+ 6 utvecklare
• Software Architect
• KTH & Handelshögskolan
• Konsult & Utvecklare(12 år & 20 år)
• C++ och C#
• DI, SOLID, WPF
Agenda - DAG 1• 08:30-09:30 | Frukost och registrering
• 09:30-10:15 | Introduktion
• 10:15-10:45 | Fika
• 10:45-11:30 | Patterns & Anti-patterns
• 11:30-13:00 | LunchTraining / 2016-04-25
www.beemobile.se
Agenda - DAG 1• 13:00-14:00 | SOLID principles
• 14:00-14:30 | Fika
• 14:30-15:30 | SOLID principle och Inversion of Control
• 15:30-14:45 | Fika
• 15:45-16:45 | Dependency InjectionTraining / 2016-04-25
www.beemobile.se
Agenda - DAG 2• 09:00-10:00 | Model-ViewModel-View
• 10:00-10:30 | Fika
• 10:30-11:15 | Model-ViewModel-View
• 11:15-12:45 | Lunch
Training / 2016-04-25
www.beemobile.se
Agenda - DAG 2• 12:45-14:00 | Lifetime Management
• 14:00-14:30 | Fika
• 14:30-15:30 | Concurrency
• 15:30-16:00 | Kursutvärdering
Training / 2016-04-25
www.beemobile.se
Vilka är ni?• Utbildning
• Erfarenhet och språk
• WPF, MVVM, MVC
• SOLID, DI
• Förväntningar
• Projekt ni är stolta över
Principles & Patterns• Vad är skillnaden?
• DRY (Do not repeat yourself)
• YAGNI (You ain’t gonna need it)
• Separation of Concerns
Training / 2016-04-25
www.beemobile.se
Design Patterns• En mall
• Specifikt problem
• I given context
• Oberoende av språkTraining / 2016-04-25
www.beemobile.se
Anti-Patterns• Ett design-pattern som används vid fel tillfälle
• Något som man tror löser problem men gör det värre
• Orsak och verkan är tydligareTraining / 2016-04-25
www.beemobile.se
Coding Guidelines• Antal tabbar, mellanslag
• Radbryt före parenteser
• Logging, tracing, assert
• Null-checksTraining / 2016-04-25
www.beemobile.se
Vad är “bra” respektive dålig kod?
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Diskussion
Fika10:15 - 10:45
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Anti-Patterns - I• Golden Hammer
• Mushroom Management
• Warm Bodies
• Bastard Injection Training / 2016-04-25
www.beemobile.se
Anti-Patterns - II• Service Locator
• Singleton Design Pattern and Static
• Temporal Coupling
Training / 2016-04-25
www.beemobile.se
Design Patterns • Observer (finns i WPF - Dag 2)
• Decorator
• Abstract Factory
• Command (finns i WPF - Dag 2)
Training / 2016-04-25
www.beemobile.se
Ta reda på ett design pattern och presentera för gruppen
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Uppgift
Lunch11:30 - 13:00
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
SOLID Principles• 1. Single Responsibility Principle (SRP)
• 2. Open/Closed Principle (OCP)
• 3. Liskov Substitution Principle (LSP)
Training / 2016-04-25
www.beemobile.se
SOLID Principles• 4. Interface Segregation Principle (ISP)
• 5. Dependency Inversion Principle (DIP)
Training / 2016-04-25
www.beemobile.se
1. Single Responsibility Principle (SRP) • En klass gör en sak
• Det finns endast en anledning till varför man vill ändra klassen
• Viktigaste principen av alla 5 SOLID principles
Training / 2016-04-25
www.beemobile.se
2. Open/Closed Principle (OCP) • “Open for Extension/Closed for modification”
• Överlagring bryter mot “Closed for modification”
• Klassiskt exempel: Shape & Area
• Validering av paranteserTraining / 2016-04-25
www.beemobile.se
3. Liskov Substitution Principle (LSP) • Hänger ihop med OCP
• Får inte ändra basklassens beteende (Exceptions)
• Klassiskt exempel: Rektangel och Kvadrat
• Beror på kraven (WriteToFile skriver till DB)
Training / 2016-04-25
www.beemobile.se
4. Interface Segregation Principle (ISP)• Hänger ihop med SRP
• Command Query Responsibility Segregation (CQRS)
• IReadService & IWriteService
• Var pragmatisk!Training / 2016-04-25
www.beemobile.se
5. Dependency Inversion Principle (DIP)• Grunden för Dependency Injection
• One should “Depend upon Abstractions. Do not depend upon concretions.”
• All member variables in a class must be interfaces or abstracts. (inte skapade med new)Training / 2016-04-25
www.beemobile.se
5. Dependency Inversion Principle (DIP)• No class should derive from a concrete class.
• No method should override an implemented method.
• Varning för “Golden Hammer”Training / 2016-04-25
www.beemobile.se
Skriv en modul för att hantera användare och inloggning
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Uppgift
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Modul för användare och inloggning• Tänk på SRP, OCP, ICP och DIP
• Ny användare (Namn, epost, lösenord)
• Inlogg (epost, hashat lösenord (bcrypt)
• Console, WPF eller papper och penna
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Modul för användare och inloggning• Spara till fil och läs från fil
• Logga till Debug
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
BONUS - Design Thinking• Rita 6 olika UX förslag för desktop på inlogg
• Rita 6 olika UX förslag på registrera ny användare
• Rita 3 olika förslag vardera ny användare och inlogg för mobil
• Tänk på att utökade krav (adress, avatar, billing)
Fika14:00 - 14:30
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Inversion of Control (IoC)• Grunden för Dependency Injection
• Användaren/konsument av en klass vet inte när och var den skapas och ansvarar inte för att ta bort den.
• Har med lifetime management att göra.
• Inte använda new för medlemsvariabler (CRC, RegEx)
Training / 2016-04-25
www.beemobile.se
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
• Hur många “protection levels”/“access modifiers” finns det i C#?
• Vilka är dem?
Kuggfrågor!
4 “Protection levels”/“Access modifiers” • Public
• Protected
• Private
• Interface (+abstract class)
Training / 2016-04-25
www.beemobile.se
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
• Vad tror ni att det är?
• Vad har ni hört?
• Vad tror ni är nyttan?
Vad är Dependency Injection?
Dependency Injection• DI-containers vs Pure Di
• Constructor Injection
• Property Injection
• Method Injection Training / 2016-04-25
www.beemobile.se
DI-containers vs Pure Di• DI-containers underlättar en hel del
• Men man måste förstå DI och IoC
• Annars bygger man en Service Locator
Training / 2016-04-25
www.beemobile.se
Constructor Injectionpublic interface IMultiply { int Multiply(int a, int b); }
public class Multiplier : IMultiply { public int Multiply(int a, int b) { return a * b; } }
public class MathProffessor { private readonly IMultiply _mult; public MathProffessor(IMultiply mult) { _mult = mult; } public int Square(int a) { return _mult.Multiply(a, a); }
var prof = new MathProffessor(new Multiplier()); int sqr = prof.Square(3); //=9
Training / 2016-04-25
www.beemobile.se
Property Injection public interface ICalculate { int Calculate(int a, int b); } public class Additioner: ICalculate { public int Calculate(int a, int b) { return a + b; } } public class Multiplier : ICalculate { public int Calculate(int a, int b) { return a * b; } } public class MathProffessor { public ICalculate Calc { get; set; } public MathProffessor() { Calc = new Additioner(); } public int WhatIf(int a, int b) { return Calc.Calculate(a, b); } } var prof = new MathProffessor(); int add = prof.WhatIf(3, 3); //=6 prof.Calc = new Multiplier(); int mult = prof.WhatIf(3, 3); //=9Training / 2016-04-25
www.beemobile.se
Method Injection public interface ICalculate { int Calculate(int a, int b); } public class Additioner: ICalculate { public int Calculate(int a, int b) { return a + b; } } public class Multiplier : ICalculate { public int Calculate(int a, int b) { return a * b; } } public class MathProffessor { public MathProffessor() { } public int WhatIf(ICalculate calc, int a, int b) { return calc.Calculate(a, b); } } var prof = new MathProffessor(); int add = prof.WhatIf(new Additioner(), 3, 3); //=6 int mult = prof.WhatIf(new Multiplier(), 3, 3); //=9Training / 2016-04-25
www.beemobile.se
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
• Nej, inte de 3 sätten att “injecta” på
• Men hur får man rätt SRP och ISP?
• Att “injecta” betyder att man får IoC
Är Dependency Injection svårt?
Decorator Patterns • Ett sätt att bryta isär olika “concerns” (SRP)
• Man ärver från en basklass, överlagrar alla metoder
• Man anropar basklassen metod och därefter sin egen kod.
• Man får OCP på köpet.
• Tänk att du utökar en befintlig klass med loggningTraining / 2016-04-25
www.beemobile.se
Fika15:30 - 15:45
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Modul för användare och inloggning• Refaktorisera koden så att du använder DI
• Använd Decorator Pattern för loggning
• Användaren vill logga till fil eller databas (Property Injection)
Recap Dependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
Anti-Patterns - Recap• Golden Hammer • Mushroom Management • Warm Bodies • Bastard Injection • Service Locator • Singleton Design Pattern and Static• Temporal Coupling Training / 2016-04-25
www.beemobile.se
Design Patterns - Recap• Observer (finns i WPF - Dag 2)
• Decorator
• Abstract Factory
• Command (finns i WPF - Dag 2)Training / 2016-04-25
www.beemobile.se
SOLID Principles - Recap• 1. Single Responsibility Principle (SRP) • 2. Open/Closed Principle (OCP) • 3. Liskov Substitution Principle (LSP) • 4. Interface Segregation Principle (ISP) • 5. Dependency Inversion Principle (DIP)
Training / 2016-04-25
www.beemobile.se
Dependency Injection - Recap• DI-containers vs Pure Di
• Constructor Injection
• Property Injection
• Method Injection Training / 2016-04-25
www.beemobile.se
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
• Single Responsibility Principle (SRP)
• Constructor Injection
• Decorator pattern
3 saker att minnas
Agenda - DAG 2• 09:00-10:00 | Model-ViewModel-View
• 10:00-10:30 | Fika
• 10:30-11:15 | Model-ViewModel-View
• 11:15-12:45 | Lunch
Training / 2016-04-25
www.beemobile.se
Agenda - DAG 2• 12:45-14:00 | Lifetime Management
• 14:00-14:30 | Fika
• 14:30-15:30 | Concurrency
• 15:30-16:00 | Kursutvärdering
Training / 2016-04-25
www.beemobile.se
Välj en principle, pattern eller “injection” från gårdagen. Presentera för gruppen.
Dependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
Presentation - 10 + 2 min
• En utveckling av MVC till MVP till MVVM
• Naturlig del av en WPF applikation
• Använder Observer, Mediatior och Command pattern
• Separation of Concern mellan UI och affärslogik
Training / 2016-04-25
Model-ViewModel-View
Dependency Injection - Composition Root
• I en console-applikation: Main()
• I WPF-applikation OnStartUp() i App.xaml.cs
• Varför? Matlagningsexempel och fisketur
• Tar det inte lång tid? (Abstract Factory)
Training / 2016-04-25
www.beemobile.se
MVVM for Dummies• Använd olika namespace typ:
Company.Project.Model (eller något domänspecifikt)Company.Project.ViewModelCompany.Project.View (eller UI)
• Eller tre olika projekt i din solution, Model och ViewModel som DLL och View som EXE
Training / 2016-04-25
www.beemobile.se
Model• Normalt där det mesta av funktionaliteten ligger
• Helst skall Model vara “stateless”
• POCO och DTO - dvs vanliga objekt/klasser
• Det är inte samma sak som datamodel
Training / 2016-04-25
www.beemobile.se
Model - II• I vårt exempel, valideringregler, skapa användare,inlogg
• I princip det mesta av koden i ett projekt
• Kommunikation, EF, Databaser, CRUD
• Det går att data-binda direkt mot en modell
Training / 2016-04-25
www.beemobile.se
ViewModel• Det är en model av vyn (trots namnet)
• Vymodellen kan vara ett tunt lager (stateless)
• Vymodellen kan vara en Service (stateful)
• Design Thinking och sketcher, hjälper dig att göra Vymodellen
Training / 2016-04-25
www.beemobile.se
ViewModel - II• Det finns inga ViewModel klasser i WPF
• En klass med publika properties är ViewModel
• Dessa properties kan databindas till Vyn i WPF
• En property av typen ICommand används istället för Button_Click
Training / 2016-04-25
www.beemobile.se
ViewModel - Stateless vs Stateful• Det finns två skolor
• Den ena säger att Vymodell är ett tunt lager mellan Vyn och Modellen och skall vara stateless
• En annan skola säger att Vymodellen skall vara Stateful och en del av affärslogiken kan ligga där.
• Exempel kan man ha en Service som skapar en användare och en som hanterar inloggning (CQRS)
Training / 2016-04-25
www.beemobile.se
View• Vyn är XAML kod och “code-behind”
• Code-behind skall innehålla sådant som endast rör GUI (Animationer)
• Det brukar gå att göra det mesta utan code-behind
Training / 2016-04-25
www.beemobile.se
WPF, XAML och DI• En Vy (Window, UserControl) har en DataContext
property
• DataContext ärvs neråt i VisualTree
• DataContext sätts till Vymodellen
Training / 2016-04-25
www.beemobile.se
WPF, XAML och DI
Training / 2016-04-25
www.beemobile.se
Constructor Injection - View-ViewModelpublic ProgrammingView(ProgrammingViewModel progviewmodel){ this.DataContext = progviewmodel; InitializeComponent();}
Training / 2016-04-25
www.beemobile.se
INotifyPropertyChanged - Observerpublic event PropertyChangedEventHandler PropertyChanged = delegate { };
public string OrderNumber { get { return _ordernumber; }set { if (value != "") { _ordernumber = value; PropertyChanged(this, new PropertyChangedEventArgs("OrderNumber")); } } }
Training / 2016-04-25
www.beemobile.se
ICommand - Command Patternprivate RelayCommand _firmwareupdatecommand;
public ICommand FirmwareUpdateCommand{get{ if (_firmwareupdatecommand == null) { _firmwareupdatecommand = new RelayCommand(param => FirmwareUpdate(),
param => CanFirmwareUpdate()); } return _firmwareupdatecommand;}}
Training / 2016-04-25
www.beemobile.se
WPF Composition Root - OnStartUp()protected override void OnStartup(StartupEventArgs e){ base.OnStartup(e); CreateDependencyGraph(); Application.Current.MainWindow.Show();}
Training / 2016-04-25
www.beemobile.se
WPF Composition Root - IIprivate void CreateDependencyGraph(){
ISQLConnection order_sql = new OrderSqlConnection(); IOrderReader order_reader = new OrderReadService(order_sql);
ISQLConnection firmware_sql = new DCD_SQLConnection(); IFirmwareReader firmware_reader = new DCD_FirmwareService(firmware_sql);
IConnectionManager conn_manager = new ConnectionManager(); ITSS2Connection connection = conn_manager.Resolve(); IFirmwareWriter firmware_writer = new FirmwareWriteService(firmware_reader.firmware_bytes(), connection);
ProgrammingViewModel progviewmodel = new ProgrammingViewModel(firmware_reader, firmware_writer); ProgrammingView progview = new ProgrammingView(progviewmodel);
//ProductionWindow ProductionViewModel prodviewmodel = new ProductionViewModel(order_reader); Application.Current.MainWindow = new ProductionWindow(prodviewmodel, progview); }
Training / 2016-04-25
www.beemobile.se
WPF Composition Root - IIIprivate void CreateDependencyGraph(){ ...
Application.Current.MainWindow = new ProductionWindow(prodviewmodel, progview); }
UI Layout• Stycka upp delar av UI i UserControls (Vyer)
• Hur byter man Vy? (Hidden, Collapsed)
• Observable Collection och ItemsControl
• Har ni flera fönster (Window) ?
Training / 2016-04-25
www.beemobile.se
Training / 2016-04-25
www.beemobile.se
ItemsControl - I... <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel>...
Training / 2016-04-25
www.beemobile.se
ItemsControl - II... <ItemsControl.ItemTemplate> <DataTemplate> <local:SlotControlSimple/> </DataTemplate> </ItemsControl.ItemTemplate>...
Training / 2016-04-25
www.beemobile.se
ItemsControl - III... <ItemsControl.Template> <ControlTemplate> <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" > <ItemsPresenter /> </ScrollViewer> </ControlTemplate> </ItemsControl.Template>...
Training / 2016-04-25
www.beemobile.se
ItemsControl - IV<ItemsControl ItemsSource="{Binding SlotControls, Mode=TwoWay}" HorizontalContentAlignment="Center" Width="1250" MinWidth="1224" Height="302" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="-13,20,0,0" > <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <local:SlotControlSimple Margin="13,0,0,0" Height="363" /> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.Template> <ControlTemplate> <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" > <ItemsPresenter /> </ScrollViewer> </ControlTemplate> </ItemsControl.Template></ItemsControl>
Event vs Data-Binding• WPF purister menar att all kommunikation mellan olika
delar skall ske via data-binding och INTE event
• Med ViewModel och View, får en del gratis data-binding
• Mellan ViewModel eller Model, måste man använda DependencyProperty
Training / 2016-04-25
www.beemobile.se
Fika Dependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
10:00 - 10:30
Service Variant Configuration - Training / 2011-06-07 / www.beemobile.se
Skriv om gårdagens program med MVVM. 45-60 min
Lunch Dependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
11:15 - 12:45
Lifetime Management• DI löser två problem
• Abstrahera bort konkreta implementationer via Interface
• Konsumenten behöver inte bry sig om att skapa och ta bort objekt
Training / 2016-04-25
www.beemobile.se
Training / 2016-04-25
www.beemobile.se
Lifetime Management - Singletonprivate IFirmwareReader firmware_reader;private IFirmwareWriter firmware_writer;
public ProgrammingViewModel(IFirmwareReader firmware_reader, IFirmwareWriter firmware_writer){ if (firmware_reader == null || firmware_writer == null) throw new ArgumentNullException();
this.firmware_reader = firmware_reader; this.firmware_writer = firmware_writer; }
Lifetime Management - II• Transient - varje konsument får ett eget objekt
• Transient - är säkraste kortet, men minst effektivt
• One-Per-Graph - en variant på Singleton och Transient
• One-Per-Graph - ett eget objekt som är Singleton per Graph
Training / 2016-04-25
www.beemobile.se
Abstract Factory• Ett interface som kan skapa ett objekt av en viss typ
(Interface)
• Oftast en CreateXXX() metod
• Ett av de få Design Patterns från GoF (Gang of Four) som fortfarande är användbart
Training / 2016-04-25
www.beemobile.se
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Agil värld gör gårdagens möjligheter till morgondagens krav. Skriv om programmet. 60 min
Training / 2016-04-25
www.beemobile.se
Nya krav• Vi vill validera en NY användare mot en “databas” av
spammare
• Vi vill validera en NY användare mot betalningsanmärkningar
• Vi vill validera epost adress så att den är korrekt formaterad
• Skapa användare och inloggning skall vara en var sin Service
Fika Dependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
14:30 - 15:00
Concurrency - BONUS• TAP eller PLINQ
• AsParallel() eller Parallel.ForEach()
• Stephen Toub (TAP)
• Stephen Cleary (Concurrency in C# Cookbook)
Training / 2016-04-25
www.beemobile.se
Training / 2016-04-25
www.beemobile.se
IProgress<T>public class FakeFirmwareUpdate : IFirmwareUpdate{public void FirmwareUpdate(byte[] firmware, int id, IProgress<int> progress){ ... progress.Report(80 /*%*/); ...}}
Training / 2016-04-25
www.beemobile.se
IProgress<T> - IIIProgress<int> progress = new Progress<int>(prog =>
{ Programming[0].Progress = prog; });
_firmware.FirmwareUpdate(null, 0, progress);
IProgress<T>• TAP eller PLINQ
• AsParallel() eller Parallel.ForEach()
• Stephen Toub (TAP)
• Stephen Cleary (Concurrency in C# Cookbook)
Training / 2016-04-25
www.beemobile.se
KursutvärderingDependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
10 min
Dependency Injection using MVVM & WPF - Training / 2016-04-25 / www.beemobile.se
Dagens sista kodpass45 min
Training / 2016-04-25
www.beemobile.se
Nya krav - II• Vid skapande av ny användare skall 3 valideringar
köras paralellt
• Används Sleep(1000/3000/5000) för att simulera tidsåtgång
• Lägg till en ProgressBar i Vyn och används IProgress<T>
• Statefulness - 3 failade logging, låser användaren.
• MVVM - eller som jag kallar det: MVMV
• Separata Namespace eller projekt
• Stateful och Stateless ViewModel
• ViewModel och UserControl.DataContext
• INotifyPropertyChanged, ICommand, ObservableCollection<T>
Training / 2016-04-25
Recap
• Composition Root och OnStartUp()
• Singleton, Transient, One-Per-Graph, Abstract Factory
• Concurrency, TAP och PLINQ
• IProgress<T>
• Det är alla småsaker TILLSAMMANS som gör det svårt
Training / 2016-04-25
Recap - II
3 saker att minnas• Composition Root
• Abstract Factory
• IProgress<T>
Diplom Dependency Injection using MVVM & WPF - Training / 2016-04-25
www.beemobile.se
Fortsätt att öva och håll små Coding Dojos på hemmaplan!