Hej
Jeg har en lille designovervejelse som jeg godt kunne tænke mig at få vendt et par forslag til.
Strukturen i min lille applikation er at en "menu" AIR app, der ligger øverst i hierakiet og forvalter en "appStage" sprite.
Når forskellige menu punkter vælges instatieres appStage som min applikation. feks. appStage = new App1();
Det er fint, garbage collection klares internt i App1, App2 osv. men kaldes fra menu. Strukturen fra menu og ned efter ligner tilnærmelsesvis Model-View-Controller strukturen.
P.g.a. måden "menu" håndterer appStage:Sprite'n kan kun én applikation være instatieret af gangen. Så menu bruges også til at igangsætte garbage collection, og holde evtuelle variabler der skal fragtes fra App1() til App9(); feks. usecase: "nyt menupunkt valgt af bruger" -> bed igangværende App(); få afleveret hvad der evt. skal bruges i næste app-> start garbage collection -> nedlæg appStage -> opret appStage og instantier ny AppX(variabel fra tidligere app);
Ok, håber det giver mening.
Mit spørgsmål er nu: jeg har en del ting jeg gerne vil gøre tilgængeligt alle steder. Feks. lyde der genbruges rundt i de forskellige applikationer(uden at skulle loade og oprette dem hver gang), indstillinger, urls til eksterne assets og farvekoder.
Til feks. lyde kan jeg lige umiddelbart se et par løsninger... load det hele i menu og lad "spil lyd 4" events "boble op" fra de dybeste afkroge af App() objekterne (ville kun skulle loades og oprettes en gang) men resultere i listeners placeret overalt på min stage + dårlig kobling fra nederst til øverst. Jeg kunne oprette et enkelt lyd objekt med lydende i og proppe det i mine constructors, det er bare begrænsende, medmindre jeg gør det overalt og det ville seriøst gøre min kode u-genbrugelig fremover + forvirrende.
Statiske klasser kunne måske være løsningen til de forskellige farver, urls og indstillingsfiler?
Så hvordan får jeg på en "pæn" måde gjort det absolut pærenemt for mig hurtigt at afspille en lyd eller hive en url frem uden at det resulterer i grimme løsninger og skrivekrampe?
AS3, AIR, Flex 3.
Håber på et par gode forslag ![]()
Tak
Ricki
4 kommentarer
Hej Ricki
Nu er det lidt svært lige at få et overblik over din applikation uden et klasse diagram eller lignende, men jeg tror umiddelbart løsningen er at bruge statiske klasser og/eller muligvis singleton.
F.eks. har du måske en lyd klasse som står for at afspille en lyd, men som også sørger for at der kun bliver afspillet én lyd af gangen, så kunne det være praktisk at lave den som en singleton som kan tilgås overalt.
Til det med farver, urls og indstillingsfiler så kan det som du siger være en løsning at lave dem som statiske klasser, det kommer lidt an på hvordan du skal bruge de ting, om det vil passe ind i en statisk klasse. Hvis det drejer sig om konstante værdier eller faste utility methoder(som i Math), så vil en statisk klasse passe fint.
Hej Ricki.
Som du selv er inde på, så er MVC et godt udgangspunkt i forhold til at strukturere de forskellige "ansvarsområder" der er i din applikation. Min erfaring er at alt for ofte får View, langt mere ansvar end det egentligt bør; f.eks. i forhold til at validere indhold, formidle data og endda håndtere forretningslogik i forhold til kommunikation med f.eks. server lag, eller lignende. View bør udelukkende renderer data. - intet andet. Når du nu er så heldig at bruge Flex har du jo muligheden for at benytte dig af databinding, så View kan binde sig til data i model delen af MVC, og når disse data ændre sig, ændre View sig, og dermed opfylder View sin del af MVC kontrakten. Når brugeren gestikulere med applikationen er det som oftest over for View, som opsamler disse gestures og formidler dem videre som events - events der opfanges af et sæt Controller klasser der har ansvar for at lytte efter og processure disse events samt tilgå serveren og updaterer Modellen. Modellen er et samlingssted for data, og stedet hvor den konceptuelle logik er og administreres.
Et hurtigt eksempel i UML:

Det er taget med udgangspunkt i dit eksempel omkring lyd.
Kort beskrivelse:
Model
Her har vi den konceptuelle lydafspiller, det der er en mapping mellem vores egen verden og den virtuelle. Jeg har valgt at kalde den "JukeBox" for at have så lavet repræsentativt kløft, mellem computer verdenen og den verden vi kender, som muligt. "Jukebox" kan afspille en sang, den har en playliste, man kan stoppe sangen der spiller, og man kan sætte volumen. Derudover kan man se på "JukeBoxen" hvilken sang der spiller, hvor lang sangen er, og hvor længe den har spillet. Altså i princippet alt det vi forventer en "JukeBox" kan i den virkelige verden, og som egentligt ikke behøver have noget med en computer at gøre. - i eksemplet er alle attributter gjort "Bindable" så View kan abonnere på disse data strukturer og renderer det grafisk for brugeren.
View
View er i eksemplet et SoundPlayerView component, som kunne være en media-afspiller, eller på anden måde være den GUI brugeren interagere med. GUI er ikke min interesse-side, så lad det være op til fantasien hvordan oplysningerne i "JukeBox" kan præsenteres smart og spændende visuelt. Pointen er, at View binder sig til attributterne i "JukeBox".
Controller
Vores sidste punkt på rejsen rundt i applikationen er vores Controller del. Controller delen består af to grupperinger i mit eksempel. En reel kontrollerende enhed(enheder) der har varetager den ene del af Controller kontrakten, nemlig at lytte og behandle events. Denne Controller, abonnere på events fra vores SoundPlayerView, og når disse opstår, behandler den disse events ud fra de det givne events natur. Denne behandling består i at sætte en såkaldt Command klasse i sving med at udføre et stykke arbejde, der nu passe med det event der er opstået. I mit eksempel har jeg lavet Commands for PlaySong, StopSong, og SetVolume. Disse tre commands har hvert deres specifikke arbejdsområde, i forhold til at "Controlle" JukeBox'en. De updater deres respektive data-områder på JukeBox... soooooom jo er bindable så disse ændringer renderes automatisk i View, og bingo, vores MVC cycle er sluttet.
Der er mange måder at implementere MVC godt på, vi bruger i webyte, Cairngorm applikations frameworket, som er meget i tråd med det netop beskrevne. I Cairngorm bruger man fænomenet en "ModelLocator". ModelLocator er en singleton klasse, som har det ene ansvar at agere samlingspunkt for alle Model enhederne. - præcist som Artmos benævner det i hans svar. I eksemplet løser det vores problem med at View jo ikke fra sin fødsel kender Model... eller mere bestemt, at SoundPlayerView ikke ved hvor JukeBox er.- men med en ModelLocator kan dette imødekommes. Så i SoundPlayerView tager SoundPlayerView fat i ModelLocator (som vi jo netop fandt ud af har ansvar for at vide hvor alle Model enhederne er) og siger
ModelLocator.getInstance().jukeBox;- og vupti, vi får returneret en reference til vores JukeBox instans. På den måde behøver vi ikke lave JukeBox, og alle de andre Model klasser der er i vores applikation som singletons, vi kan nøjes med at have den del af Model pakken der administrere disse enheder, som en singleton.På samme måde før vores Command klasser fat i JukeBox, ved at tilgå ModelLocator'en.
Hvis vi lige til afslutning skal se på indholdet af ModelLocator, så er det meget simpelt. - ud over implementationen af Singleton pattern (som jeg ikke vil gennemgå her) består ModelLocator af en række bindable attributer.
Outro
Nå, nu fik jeg nærmest svaret på dit spørgsmål, med en hel lille gennemgang af MVC - det må jeg lige ved lejlighed refactor og poste som en publikation. - men kort og godt, så se om du kan få placeret ansvaret for data ét sted, måske som enkelte variabler (en farve en url etc) eller som samlinger af konceptuel data (som jukeboxen) og lad dit View renderer disse data ubetinget, uden at forholde sig til om det er "rigtigt" eller "forkert" (forstået som at den logik skal varetages andre steder). Lad en controller stå for at administrere gestures fra brugeren over i modellen. - du kan jo alle de steder du har brug for at afspille noget i JukeBoksen, bruge samme controller til at lytte på events fra dine View enheder.
Held og lykke med projektet.
Vi snakkes ved.
Hej Artmos og Asger
Uha Tak og sikken en mundfuld Asger, håber du udkommer med
et eller andet en dag:)
Det er jo et par dage siden jeg
sad med overvejelsen så den er både færdig overvejet og implementeret:)
Løsningen blev som Artmos foreslog og jeg selv var inde på, en singelton.
Da jeg fik gennemgået min(e) applikation(er) var der en del forskellige ting jeg
gerne ville have liggende i en slags konfigurations fil globalt. Flash har det med at
trække min tankegang væk fra den måde jeg normalt ville løse sådan et problem
i en desktop app.
Så div. blev til en konfigurations fil der indlæses rundt omkring vha. af
en klasse og lydene blev pakket i en singelton.
Tak igen for gennemgangen af MVC Asger, man kan altid få
en endnu bedre forståelse for værktøjerne.
Mvh. Ricki
AS1 < AS2 < AS3
Godt at høre at du fandt en god løsning.
- ja, jeg lider af udpræget grafomani så mon ikke en dag det ender med et eller andet der kan wrappes i et omslag. Indtil da, må FlashForum.dk's brugere lide under min lidelse
Cheers