Arbeide med sett av virksomheten objects

I denne artikkelen vil jeg vise en måte å jobbe med sett av virksomheten objectsThe behovene i ManyIn denne artikkelen går vi tilbake til en verden av en generell objekt rammeverk og komplett forholdet håndtering ved å vurdere hvordan man kan arbeide med sett eller samlinger av Business Objects. Så langt har vi sett hvordan å uttrykke enkle 1-1 eller mange-1 relasjoner ved rett og slett å utsette relatert objekt som en eiendom, for eksempel Order.Customer. Dette er en enkel og naturlig måte å eksponere relaterte objekter, med riktig håndtering skjer innenfor de aksessoregenskaper funksjoner av eiendommen, men hvordan kan vi avsløre de andre varianter av relasjoner, nemlig en-mange eller mange-mange? En enkel tilnærming, slik som Customer.Order, ikke tjener vårt formål som det innebærer at det er en enkelt ordre for en gitt kunden (som vanligvis ikke er tilfelle), og hindrer tilgang til eventuelle andre bestillinger som kan eksistere. Det vi trenger er syntaks, og en effektiv gjennomføring, for håndtering av et sett av virksomheten objects.If vi tenke på dette på en annen måte da trenger vi en generell betyr for håndtering av slikt sett av objekter. I praksis, samt en liten samling av objekter (for eksempel en liste over Ordre for en gitt Kunden som vanligvis ville bestå av høyst et par hundre oppføringer) vil vi også ønsker å støtte store samlinger av gjenstander, som for eksempel en liste over alle varer på lager. Som vi opererer i et objektorientert verden, er den logiske konklusjonen at vi trenger en ny klasse som eksponerer et sett av forretningsobjekter. La oss kalle denne klassen TPDList (en liste over problemdomenet gjenstander) å gå med vår TPDObject klasse. Navnet er vilkårlig og noen kanskje tror at dette innebærer en spesiell implementering. Dessverre er det alternativer som "set" og "samling" allerede har lignende konsekvenser innenfor Delphi verden. Syntaktisk sukker
En syntaktisk behagelige og naturlig måte å håndtere et sett av objekter vil være å avsløre dem ved hjelp av en slags array, som vist i Listing 1. En slik klassedefinisjon ville tillate oss å få tilgang til objekter ved hjelp av konstruksjonene i koden vår som Customer.Orders [], som er veldig kjent. Men det er to store ulemper for denne tilnærmingen: det innebærer at vi vet hvor mange gjenstander er på listen, og at de er alle tilgjengelige i et tilfeldig tilgangstype mote. Den eneste måten å sikre disse forutsetningene er oppfylt, er å fullt ut fylle listen, eller i det minste fullt fylle en intern liste over objekt ID og laste hvert objekt individuelt som det er tilgjengelig. Ulempen med den første tilnærmingen er overdreven minneforbruk og muligens merkbar forsinkelse mens de mange objekter startes, og den ulempen til andre tilnærmingen er ineffektiviteten i å utstede en rekord belastning for hvert objekt nås (stepping gjennom et sett av 100 gjenstander ville krever 100 søk i databasen som skal utstedes) .Så, til tross for de syntaktiske fordelene av matrisen tilnærmingen det ikke er optimalt for det generelle tilfellet, selv om det selvsagt en ramme kan utvides til å støtte to (eller flere) forskjellige måter å håndtere sett av objekter , en for liten, og en for stor. Personlig er jeg en stor fan av konsistens og foretrekker det å være et enkelt syntaks for å arbeide med sett av stedene. Som vi skal se i et senere kolonnen, betyr ikke dette hindre oss fra å ha en rekke implementasjoner for syntaks, følg med for annen circumstances.At det mest grunnleggende nivå våre gjenstander kommer til å være befolket av vedvarende lagringsmekanismen, vanligvis en database. De fleste data i disse dager er tilgjengelig gjennom en spørring (SQL), og hvis vi ser på egenskapene til slike elementer de er vanligvis i stand til å gi oss den "neste" konseptuelle posten, og til å bestemme når listen er oppbrukt. Typisk informasjon som antall poster i listen, eller tilfeldig tilgang til dem, er ikke tilgjengelig. Vårt rammeverk bør utformes med ytelse og klientprogram ressursbehov i tankene, så et forslag til grensesnitt for vår TPDList er vist i Listing 2. Dette gir oss et første metoden (re-initialisering listen tilbake til begynnelsen), Next (tilgang neste objekt i listen) og en IsLast eiendom (som indikerer når listen er oppbrukt). "Gjeldende" objekt i listen er tilgjengelig gjennom en passende navnet eiendom. Dette grensesnittet kan virke unødvendig enkel; hvor er metoder for å støtte bakover navigasjon? Erfaring viser at reverse navigering gjennom en liste er svært sjelden nødvendig, og hvor det er, kan enkelt gjøres gjennom andre konstruksjoner. For tiden, vil vi holde vår liste styring klassen simple.How er denne klassen som skal gjennomføres? Som før, bør problemet vårt domene (virksomhet objekt) lag har ingen begrep om hvordan data er lagret eller forvaltes. Vår TPDList forvalter en samling av forretningsobjekter og kan derfor ikke være en tynn wrapper rundt noe som database-spesifikk som en databasespørring. I stedet vil vi utforme en annen klasse til å håndtere database støtte for lister over gjenstander, og gir et objekt-basert database-uavhengig grensesnitt mellom vår TPDList og denne klassen. På denne måten har vi holdt strengt skille mellom virksomheten lag og data management lag, slik at vi i full fleksibilitet i hvordan sistnevnte er administrert. Søtningsstoffer pillen
På samme måte som vår TPDObject hadde en TDMObject data management konsekvens, kan det virke som vår TPDList bør ha en TDMList tilsvarende. I praksis er det en stor mengde av felles mellom de to datahåndteringstimer og de kan være innordnet i en enkelt klasse. Det kan synes logisk å ha en klassehierarkiet med en felles stamfar for felles funksjonalitet og etterkommere å håndtere enkelte tilfeller og lister, men dette medfører en kode-skriving overhead når det gjelder å faktisk implementering vår søknad, med liten fordel. Vi vil derfor utvide vår TDMObject å støtte listeoperasjoner, samt eksisterende enkelt forekomst Load og spar. Hver TPDList vil derfor eier en privat TDMObject som er ansvarlig bare for å administrere data tilgang for listen over objekter. "Gjeldende" TPDObject avslørt av listen vil etterligne "dagens" post i databasen markøren. Vi trenger en unik (og private) data management objekt for hver TPDList fordi det er behov for å opprettholde staten (spørring informasjon, markør posten og så videre). Derimot, kan problemet domene objekter av samme klasse dele en enkelt data management objekt fordi laste og lagre metoder er statsløs operations.Our TDMObject kan nå bli utvidet til å støtte operasjoner som kreves. Den vil ha FirstRecord og NextRecord metoder (for å indikere at det er rekord-baserte natur), og en IsLastRecord eiendom for å indikere når markøren er oppbrukt (dette markøren vil være privat til data management objektet og basert rundt noen database-avhengige spørring mekanisme). Metodene i vår TPDList vil bare delegere arbeid av til data administrere objekt, og kaller disse lignende navngitte metoder. Den TPDList ber private data management formål å gi den med en instansiert problem domeneobjektet som klientprogram skritt gjennom den. Koden for å fylle dette objektet fra spørre markør bør deles med at for å fylle et enkelt objekt i Load routine.We nå har en klasse som tillater oss å navigere gjennom et sett av problem domene objekter, og vi har utvidet vårt dataadministrasjon klasse for å støtte disse operasjonene. Det vi har ennå ikke gjort er å definere hvordan ulike sett av gjenstander bør defineres. Tross alt, er det mange forskjellige typer sett av objekter vår søknad kan kreve; vi kanskje trenger det sett av kunder som har bestilt en bestemt lagervare, kanskje vi trenger det sett av kundene som kalles "SMITH" eller vi kanskje trenger settet av alle kunder (for rapporteringsformål). En opplagt måte å definere disse ulike sett at vi kanskje trenger er å definere tilpassede konstruktører. Oppføring 3 viser felles grensesnitt for et eksempel TCustomerList som forvalter et sett med kunder. Du vil også se at det eksponerer en Customer eiendom; dette bare returnerer CurrentObject statisk typecast til en TCustomer (vi vet og forventer at alle objekter i listen for å være av denne typen, så det er en sikker drift og unngår å plassere typecast i hoved programmet logikken). Noen ultra-purist OO talsmenn kan hevde at heller enn å bruke tilpassede konstruktører en klassehierarkiet bør opprettes, med en ny klasse for hver type liste nødvendig. Jeg personlig ser liten nytte i denne fremgangsmåten, med mindre den spesielle sett med objekter krever noe særlig involvert håndtering som må forbli privat for en bestemt liste implementering, og denne fremgangsmåten har den ulempen at den krever en betydelig mengde av kode som skal skrives og påfølgende klasse proliferation.We kan nå håndtere lister over kunder bare ved å lage et TCustomerList på den mest hensiktsmessige måten. Vår programkode kan se omtrent slik ut: var CUSTOMER: TCustomerList; begynne CUSTOMER: = TCustomerList.CreateByName ('SMITH'); prøve CustomerList.First; mens ikke CustomerList.IsLast ikke begynne //Gjør noe med CustomerList.Customer objekt CustomerList.Next; slutt; endelig CustomerList.Free; ende, slutt, ha denne typen logikk i programmet er mye tydeligere enn tilsvarende prosessuelle hjelp av å bygge databasespesifikke søk og bruk av felt direkte. Spesielt har vi innkapslet alle disse detaljene innenfor vår data management klasse og denne koden sentralisering tillater oss luksusen av å vite at mulighetene for å registrere et ugyldig bord eller feltnavn er sterkt reduced.So langt har vi ikke spesifisert den faktiske gjennomføringen av tilpassede konstruktører i vår liste styring gjenstander. Som allerede nevnt, disse klassene sitte resolutt innenfor vår søknad forretningslogikk og derfor må være helt database-uavhengig. Nærmere bestemt kan disse konstruktører ikke være involvert med å bygge opp SQL-spørringer eller lignende. Slike detaljer er innenfor rammene av den rollen for våre data management klasse, og så tilsvarende TDMObject for hver klasse vil få tilpassede konstruktører, hver nøyaktig samsvar i navn og parametre de for TPDList gjenstand for vedkommende har ansvar for. Neste måned vil vi avrunde denne håndteringen ved å se på noen av gjennomføringen detaljer, og viser hvordan forbedringer i vår klasse design, og kraften av polymorfisme, fører til svært redusert koden du skriver for våre tilpasset applikasjons klasser. Denne artikkelen er Spørsmålet
Å kunne håndtere sett av objekter er byggesteinen for håndtering av objektrelasjoner. Hvordan kan vi bruke dem til å støtte en-mange relasjoner som Customer.Orders, og vi kan støtte disse konstruksjonene generelt på samme måte som vi gjorde for 1-1 og mange-1 relasjoner (((Oppføring 1 - Array-basert TPDList interface))) skriver TPDList = klasse offentlig eiendom ObjectAtIndex [indeks: Integer]: TPDObject; misligholde; Eiendommen Count: Integer; slutten; (((End Oppføring 1))) (((Oppføring 2 - Navigasjons TPDList interface))) skriver TPDList = klasse offentlig prosedyre Først; prosedyren Neste; Eiendommen CurrentObject: TPDObject; Eiendommen IsLast: Boolean; slutten; (((End Oppføring 2))) (((Oppføring 3 - Eksempel TCustomerList felles grensesnitt))) skriver TCustomerList = klasse (TPDList) private //Resultat: = TCustomer (CurrentObject); funksjon GetCustomer: TCustomer; offentlig konstruktør CreateAll; konstruktør CreateByName (konst Navn: String); konstruktør CreateByStockOrder (Sak: TStockItem); Eiendommen Kunde: TCustomer lese GetCustomer; slutten; (((End Oppføring 3))) Neste i serien