• Ingen resultater fundet

A.8 Vælg afdelinger, n˚ ar afdelingsdimensionen er valgt i analyseme-

5.7 Klientstruktur

som klassenavne iC#. P˚a den m˚ade kan man skelne mellem en constructor functionog andre funktioner[9, s. 181], der skrives med lille startbogstave.

Ideen med dette afsnit er, at jeg i figur 5.8 viser et klassediagram over kli-entlaget, der illustrerer de elementer, klientlaget best˚ar af. Figuren beskriver systemets klasser og strukturen mellem dem. Idet klientlaget bliver implemen-teret vha.JavaScript, synes jeg, det er p˚a sin plads at komme ind p˚a objekter iJavaScript, og endnu vigtigere, objekt konstruktion iJavaScript. Den m˚ade at konstruere JavaScriptobjekter p˚a, som jeg har beskrevet i dette afsnit, kaldes Constructor Pattern[9, s. 181]. Der findes flere objektkonstruktions patterns, som er opst˚aet i takt med udvikling af sproget. Jeg vil bruge den omtalteConstructor Patterni udvikling af klientlaget til at strukturere og konstruereJavaScript ob-jekter. Mere herom i næste kapitel, Implementering.

5.7 Klientstruktur

Strukturen i klientlaget er delt op i elementer, der repræsenterer hhv. bruger-grænsefladen, systemets funktionalitet/adfærd og data. Dette er i overensstem-melse med design mønstretmvvm, som jeg beskrev i Teknologi Analyse kapitlet i forbindelse medJavaScriptbiblioteketKnockoutjs. Jeg har i Brugergrænseflade og struktursektion i dette kapitel præsenteret et foreslag til brugergrænseflade-struktur. Strukturen best˚ar af et navigationsomr˚ade i vestreside, hvor jeg gerne vil præsentere en brugers Dashboards i en træstruktur, hvor Dashboards vil blive organiseret i nogle foldere. Det valgte Dashboard vil blive vist i indholdsomr˚adet til højre med alt dets indhold.

Designklassediagram vist i figur 5.8 fra forrige afsnit illustrerer elementerne i klientlaget.htmlogcsselementerne fra figuren repræsenterer den foresl˚aede brugergrænsefladestruktur. KlassenTreeViewModelindkapsler funktionalitet til h˚andtering af brugerinteraktion i navigationsomr˚adet i brugergrænsefladen. Som det kan ses, har klassen et array af folder objekter, repræsenteret ved klassen FolderViewModeli figuren. Denne har igen et array af dashboards objekter re-præsenteret ved DashboardViewModel i figur 5.8. Som det kan ses, er det en hierarkisk struktur som elementerne i klientlaget er organiseret i. Dashboard-ViewModel vedligeholder et array af kpi objekter, hvor et kpi, repræsenteret ved KpiViewModel, indkapsler funktionalitet omkring egenskaber ved et kpi. S˚aledes er alt adfærd indkapslet i ViewModel instanser og adskilt fra præsen-tationen (html). Disse ViewModel har ingen afhængighed til præsentationen (html).ViewModelsrepræsenterer i stedet for de abstrakte egenskaber af præ-sentationen, som fx “en liste af dashboards ”.

5.7.1 At Bringe MVVM til Klienten

mvvm, som beskrevet i Teknologi Analyse kapitlet, er en adskillelsesmønster (Eng. separation pattern), der adskiller ansvarsomr˚ader forModel(data), View,

5.7. KLIENTSTRUKTUR KAPITEL 5. DESIGN

som i dette tilfælde er html, og ViewModel, som vi skriver i JavaScript. Jeg kan anvende mvvmp˚a klienten ved brug af JavaScriptbiblioteket Knockoutjs, hvorved jeg kan bindehtmlelementer med data.mvvmi form af Knockouthar følgende elementer vist i figur 5.9

Figur 5.9:mvvmp˚a klienten.

Model

Modeler server-side repræsentation af domænets data.

View

View er præsentation af information p˚a en brugervenlige m˚ade. Det er html.

ViewModel

ViewModel binder Model og View sammen. Det er et JavaScript objekt, indeholdende den nødvendige adfærd for et View og kan samle en eller Modelsfor at vise data iViewet.

Jeg vil i det følgende illustrere, hvorledesmvvmprincipperne kan anvendes ihtmlogJavaScript ved brug af Knockout. Ved hjælp af et simpelt eksempel, vil jeg demonstrere, hvordan man kan adskille data (JavaScript), præsentationen (html) og adfærd (JavaScript). S˚a lad os starte medViewet, som best˚ar afhtml vist i kodeoversigt 5.5 nedenfor.

5.7. KLIENTSTRUKTUR KAPITEL 5. DESIGN

Listing 5.5:mvvmmedKnockout-View(html)

1 < !- -data- b i n d a t t r i b u t t e r er m a a d e n K n o c k o u t g i v e r m u l i g h e d for- ->

2 < !- - d e k l a r a t i v t , at k n y t t e V i e w M o d e l v a r i a b l e med DOM e l e m e n t e r - ->

3

4 N a m e : <s p a n data- b i n d =" t e x t : n a m e "> < /s p a n>

5 D e s c r i p t i o n : <s p a n data- b i n d =" t e x t : d e s c r i p t i o n "> < /s p a n>

6 P r i c e : <s p a n data- b i n d =" t e x t : f o r m a t C u r r e n c y ( s a l e s P r i c e ) "> < /s p a n>

Det man kan se her er 3 simple linjer af htmlkode, som viser information om et produkt. Som det kan ses, er der vist noglespanhtmlelementer, som p˚a nuværende tidspunkt ikke har noget indhold. Det er voresModelobjekt der har det data, der skal bindes til dissespanelementer. Vi kan se, atspanelementerne har endata-bindattribut, som er html5 kompatible attribut, somKnockout bruger for at finde ud af, hvilken binding det drejer sig om. I dette tilfælde kan vi se, at det ertext binding, som er en af de mange indbyggedeKnockout bindings, der er tilgængelige. Her er det text binding der er bundet til nogle variable (Eng. properties). Men hvor er disse variable defineret?, og hvordan finder Knockout dem? Svaret er, ViewModel, som er vist i kodeoversigten 5.6.

Modeler ogs˚a vist i den samme kodeoversigt. Binding-syntaksen kan vi se best˚ar af to elementer inde idata-bindattributten;binding-navnogværdi, adskilt af et kolon.Binding-navn kan være en af de mange indbyggedeKnockout bindings, men Knockout giver ogs˚a mulighed for at oprette sin egen bindings. Det gør man ved at registrere sin binding vha. ko.bindingHandlers.Værdi-delen i en binding-syntaks kan være en ganske almindeligeJavaScriptvaraible, enKnockout observable, eller en metodekald. Metoden kan være defineret iViewModel, men den kan ogs˚a defineres inline i binding-syntaksen.

Listing 5.6:mvvmmedKnockout-ViewModel&Model(JavaScript)

1 // T h e M o d e l

2 var p r o d u c t = {

3 id : 1 0 0 1 ,

4 n a m e : ’ S a m s u n g GS4 ’,

5 d e s c r i p t i o n : ’ The S a m s u n g G L S 4 c a p t u r e s all the a c t i o n w h e r e v e r

6 you are . ’,

7 p r i c e : 6 0 0 . 0 8 8

8 };

9

10 // T h e V i e w M o d e l

11 var V i e w M o d e l = {

12 id : ko . o b s e r v a b l e ( p r o d u c t . id ) ,

13 n a m e : ko . o b s e r v a b l e ( p r o d u c t . n a m e ) ,

14 d e s c r i p t i o n : ko . o b s e r v a b l e ( p r o d u c t . d e s c r i p t i o n ) ,

15 s a l e s P r i c e : ko . o b s e r v a b l e ( p r o d u c t . p r i c e ) ,

16

17 f o r m a t C u r r e n c y : f u n c t i o n( v a l u e ) {

18 r e t u r n ’ $ ’ + v a l u e () . t o F i x e d (2) ;

19 }

20 };

21

22 // B i n d t h e V i e w M o d e l to t h e V i e w u s i n g K n o c k o u t

5.7. KLIENTSTRUKTUR KAPITEL 5. DESIGN

23 // V e d at k a l d e d e n n e K n o c k o u t m e t o d e , b l i v e r H T M L ’ s ’ D a t a C o n t e x t ’

24 // s a t t i l v o r e s V i e w M o d e l

25 ko . a p p l y B i n d i n g s ( V i e w M o d e l ) ;

Denne kodeoversigt viser to JavaScript objekter, Modelog ViewModel. Den sidste linje kode udfører en vigtig funktion. Den aktivererKnockout og sætter ViewModelobjektet som en slagt ’DataContext’ forView’et. I eksemplet her har jeg brugt en anden m˚ade at konstruere et objekt p˚a, som kaldesObject Literal Pattern. Det er en hurtig og nem m˚ade at konstruere objekter p˚a, som er bedre egnet til simple objekter. N˚ar man har med komplekse objekter at gøre, vil man gerne have styr p˚a f.eks.thisreferencen, og private ogpublic attributter.

I kodeoversigt 5.6 er der defineret etModelobjekt,product. Det er et simpelt objekt med attributter og værdier.Modelobjekter vil man normal modtage fra serveren via ajax kald. ViewModel objektet har en række observable attri-butter. Enobservables er et Knockout objekt, som underretter (Eng. notify) abonnenter om ændringer. N˚ar en observables indhold ændres, opdateres auto-matisk det/de brugergrænsefladeelementer, der er bundet til detteobservable.

I eksemplet her var det ikke nødvendigt at definere ViewModel properties som observables. Hvis jeg havde defineret dem som almidelige JavaScript variab-le, havde jeg f˚aet samme output - Knockoutville binde variablernes værdier til htmlspan elemeterne, første gang filen blev indlæst. Men efterfølgende inter-aktion som vil resultere i, at variablernes værdier ændres (enten i kode eller UI, fx indtastning i et tekstfelt, som er bundet til variablen), ville ikke afspejle denne ændring i brugergrænsefladen, da almindelige JavaScript variable ingen m˚ade har at underrette, at de er blevet ændret. Her kommerobservablesind i billedet. De er Knockout objekter, der automatisk vil udstede notifikationer, n˚ar deres værdi ændres.

For helhedens skyld viser jeg resultatet af dette eksempel i figur 5.10 nedenfor.

Jeg har brugt værktøjetjsfiddle, som er et kodedelingsværktøj, der kan bruges til at redigere, dele, eksekvere og debugge web kode inde i browseren. Jeg har brugt værktøjet meget hyppigt i forløbet indtil videre for at sætte mig ind i de forskellige web teknologier.

5.7.KLIENTSTRUKTURKAPITEL5.DESIGN

Figur 5.10:mvvmmedKnockouteksemplet - jsfiddle output.

79