Normalisering av objektorienterte systemer Versjon B Knut W. Hansson Førstelektor Høgskolen i Buskerud August 2003/Sept 2005
Innhold Innledning...3 Hvilke klasser bør inngå i normaliseringen...3 Antall instanser...3 Transiente/persistente klasser...4 Entitetsklasser, kontrollklasser og grenseklasser...4 Assosiasjonsklasser...5 Metoder...6 Arv...7 Regler for normalisering av RDBMS...8 Regler for normalisering av OO-systemer...9 ad Ikke-taps projeksjoner ("Heath's regel")...9 ad mål ) Alle entitetstyper har minimal identifikator...0 ad mål 2) Alle relasjonstyper er eksplisitt gitt ved fremmednøkkel...0 ad mål 3) Alle attributtyper er atomære...0 ad mål 4) Gjør om modellen slik at alle determinander er kandidatnøkkel... Konklusjon...2 Oppsummering...3 Knut W. Hansson Høgskolen i Buskerud Side 2 av 3
Normalisering av objektorienterte systemer Innledning Normalisering av relasjonsdatabaser (RDBMS) har lenge vært kjent. Reglene for slik normalisering bygger på relasjonsteori med store innslag av matematikk. Så vidt jeg vet, er det ikke utviklet tilsvarende teori for objektorienterte systemer (OO-systemer) eller objektorienterte databaser (OODBMS). Jeg mener at i den grad objektorienterte systemer lagrer data, kan de samme redundansproblemene oppstå som i relasjonelle databaser. Data struktureres i klasser som i datasammenheng tilsvarer relasjonsmodellens entitetsklasser eller -typer. Objektene i klassene kan lagres og hvert objekt tilsvarer da en linje i relasjonsdatabasenes tabeller. I dag er det også blitt ganske vanlig å lagre de persistente dataene fra OO-systemer i relasjonsdatabaser. Det vil da være en fordel om modellen for det objektorienterte systemet minst mulig avviker fra det som lar seg direkte implementere i en relasjonsdatabase. Likevel kan ikke de samme reglene gjelde, på grunn av de innebygde forskjellene det er på relasjonelle og objektorienterte systemer. Jeg har forsøkt å analysere disse forskjellene og konsekvensene det har for normaliseringsreglene når man modellerer objektorienterte systemer. Generelt gjelder at formålet med normaliseringen er å unngå uønsket redundans i den grad det er mulig. Redundans gir velkjente problemer når databasen fylles med data og vedlikeholdes, som jeg anser kjent og ikke skal gå nærmere inn på her. Jeg anvender uttrykket tabell for RDBMS. Man kan innvende at det bør hete relasjoner, men det skaper lett forvirring i forhold til OO-systemer der relasjoner angir sammenheng mellom klasser og mellom objekter. Hvilke klasser bør inngå i normaliseringen Antall instanser I RDBMS skal alle tabellene inngå i normaliseringen. Det har sammenheng med at alle tabellene (normalt) vil få mer enn en linje. Det er da redundans kan oppstå. I OO-systemer er det ikke uvanlig med klasser som bare skal instansieres til ett objekt. Et eksempel kan være en klasse som modellerer et systems administrator. Siden (nesten) all funksjonalitet legges i objekter, og objekter bare kan lages ut fra en klasse, må det deklareres klasser også for slike enkeltstående (unike) objekter. (Noen velger også å ikke instansiere slike klasser, men deklarere klasseattributter og klassemetoder (static) isteden.) Siden det bare lages ett objekt for slike klasser, vil det vanligvis ikke oppstå redundansproblemer 2, og i normalisering av OO-systemer kan man se bort fra slike. Jeg har oppsummert disse reglene i notatet NORMALISERING AV RELASJONSDATABASER the Quick Hansson Way for Real Experts!, 990-93 2 Det kan tenkes redundans også innen ett objekt, f.eks. hvis objektet har to like attributter: Nr, Navn, Navn. Slik redundans må man kunne karakterisere som tåpelig og ingen vil gjøre det i praksis. Knut W. Hansson Høgskolen i Buskerud Side 3 av 3
Et spesielt fenomen er attributter som representerer flere objekter i en struktur, f.eks. en array. Disse krever spesiell oppmerksomhet, da det kan være redundans imellom disse objektene. (Dette gjelder også for statiske, abstrakte klasse.) Regel : Normaliser bare klasser med flere objekter, men vær spesielt oppmerksom på at ett attributt kan representere mange objekter. Transiente/persistente klasser I RDBMS er utgangspunktet at all informasjon skal lagres det er derfor tabellen lages. I objektorienterte systemer lages mange klasser som instansieres midlertidig mens applikasjonen går, og ingen informasjon lagres utover programmets eksekvering. Objekter av slike klasser sies å være transiente. Det er jo da begrenset hvor mange instanser som blir generert samtidig, og siden de ikke skal lagres blir eventuelle redundansproblemer små og kortvarige. I prinsippet kan man også tenke seg redundans ved at samme attributt finnes som klasseattributt i flere klasser, men også dette vil skape små problemer siden det er så få forekomster. Det synes da praktisk (men neppe helt teoretisk korrekt) å se bort fra disse, og konsentrere innsatsen om de persistente klassene, med objekter som skal lagres på et eksternt lagringsmedium. Regel 2: Konsentrer innsatsen om persistente klasser. Entitetsklasser, kontrollklasser og grenseklasser Booch deler klassene i entitetsklasser som modellerer ting i omverden, kontrollklasser som koordinerer og styrer øvrige klasser dynamisk og grenseklasser som representerer brukere, systemer, utstyr og liknende i systemets omgivelser. Kontrollklasser er først og fremst aktuelle når det opereres med flere tråder eller prosesser og asynkrone kall (meldinger), det vil gjerne si tekniske RT systemer. I administrative systemer er de fleste kall (meldinger) synkrone, og det blir ikke behov for tidsmessig koordinering. Alle disse klassene kan være persistente, og bør da tas med i normaliseringen. På den annen side, vil entitetsklassene være de som instansieres mest og som følgelig vil være mest utsatt for redundans. Hvis man må avgrense normaliseringen bør den følgelig konsentreres om disse. Eksempel: Parkeringsautomat P_Kunde 0.. ControlUnit 0..n P_Salg Betalingsenhet Display Skriver Knut W. Hansson Høgskolen i Buskerud Side 4 av 3
P_Salg er entitetsklasse og persistent. ControlUnit er kontrollklasse som sikrer at de andre objektene opererer i riktig rekkefølge, mens de øvrige er grenseklasser. Regel 3: Normaliser alle persistente klasser, eller i alle fall entitetsklassene. Assosiasjonsklasser I RDBMS må alle mange-til-mange sammenhenger entitetiseres ved at det innføres en ekstra tabell som tar vare på data om sammenhengen. Det skyldes at slike mange-til-mange sammenhenger ikke kan realiseres uten å bryte med normaliseringsreglene. I den grad det er knyttet attributter til sammenhengen, vil disse komme med i den ekstra tabellen (som jeg uformelt kaller en koblingstabell ). I OO-systemer er mange-til-mange assosiasjoner uproblematiske de kan realiseres direkte 3, så det er hverken nødvendig eller ønskelig å innføre noen ekstra klasse. I den grad det knyttes data til assosiasjonen, bindes de til en klasse som knyttes direkte til assosiasjonen. Slike kalles assosiasjonsklasser. Disse er å oppfatte som en spesiell slags entitetsklasse, og må inngå i normaliseringen. Siden assosiasjonsklasser instansieres for hver, enkelt assosiasjon, blir redundans fort et akutt problem for slike klasser. De bør derfor gjøres gjenstand for spesiell oppmerksomhet under normaliseringen. Eksempel: Aksjefond Andel prosent : double Eier fonds : Set of Aksjefond eiernavn : String..n..n Aksjefond eierskap : Set of Eier fondsnavn : String EierAndel (from Aksjefond) prosent : double..n Eier fonds : Set of FondsAndel eiernavn : String..n..n Aksjefond eierskap : Set of EierAndel fondsnavn : String..n FondsAndel (from Eier) prosent : double 3 Jeg har skrevet et notat om hvordan dette kan gjøres kalt Mange-til-mange assosiasjoner (relasjoner) i ODBMS, 200 Knut W. Hansson Høgskolen i Buskerud Side 5 av 3
Øverst er eksempelet modellert slik det er naturlig i OO-systemer, med assosiasjonsklasse (en undergruppe av entitetsklasser) som lagrer andelsprosenten for hver kombinasjon Eier/Aksjefond. Nederst er eksemplet modellert uten assosiasjonsklasse. Mange-til-mange-relasjonen Eier Aksjefond er isteden modellert med to indre klasser som begge har attributtet prosent. Dette er redundant, men denne redundansen er vanskelig å finne, særlig hvis man tilfeldigvis velger forskjellige navn på de to prosent-attributtene. Regel 4: Normaliser også assosiasjonsobjekter, og med særlig oppmerksomhet og kontroller at det ikke mangler en assosiasjonsklasse (da finnes isteden attributter som beskriver assosiasjonen). Metoder I RDBMS er alt data. I OO-systemer finnes også metoder. Spørsmålet er om redundansproblemer også gjelder for metodene, slik at disse skal inngå i normaliseringen. Når en klasse instansieres, kan objektene inneholde en referanse til metodene 4. Hverken deklarasjonen eller definisjonen av metodene vil bli kopiert til objektet, og følgelig gir dette ikke redundans. Referansen til en metoden kan sammenliknes med en fremmednøkkel i RDBMS. Selv om alle objektene i en klasse således inneholder samme referanse, er dette en redundans som ikke kan unngås og som dessuten ikke skaper noen problemer. På den annen side kan det hende at hvert kall på en metode fører til at det skapes en ny instans av metodens kode 5, og det er i så fall en form for redundans. Denne er imidlertid ikke til å unngå. Den er likevel transient, og vil skape få problemer. Også metoder kan være redundante f.eks. hvis man legger samme kode helt eller delvis i flere subklasser istedenfor i metaklasse. Det er likevel en vesentlig forskjell på data og metoder: Man vil aldri lagre mange instanser av samme kode. I objektorientering legges det stor vekt på plasseringen av metoden, blant annet i forhold til de attributtene metoden må ha tilgang til. Normalisering endrer, så vidt jeg kan se, ikke på dette. Det er likevel slik at metoder kan ha tilgang til private data innenfor objektet. Hvis data må flyttes til en annen klasse av hensyn til normaliseringen, kan dette skapes problemer ved at de da må gjøres public for å være tilgjengelige for en metode i en annen klasse, eller metoden må deles på to klasser. (Dette kan unngås ved å gjøre attributtene protected, men da må klassen som har metoden være en subklasse til den med dataene.) Jeg tror det er best å løse slike problemer etterpå, ved å vente med strukturering av metodene til etter normaliseringen. Eventuelt kan større problemer da løses ved bevisst denormalisering 6. 4 Det er ikke sikkert at realiseringen skjer slik det er også mulig bare å notere hva slags objekt det er. Ved kall på objektet kan den realiserte koden sjekke med klassen om metoden finnes og i så fall hente realiseringen derfra. Redundansen omfatter i så fall bare attributtet som angir objektets klasse. 5 Det er også mulig at det ikke skapes en slik kopi, bare en referanse til hvor langt i koden det enkelte objekt er kommet. Men det må skapes en egen instans av alle lokale data til metoden. 6 Denormalisering innebærer å bevisst ødelegge normaliseringen, fordi man vurderer at fordelene ved normaliseringen motvirkes av andre ulemper, f.eks. eksekveringstid, responstid eller kodekvalitet. Knut W. Hansson Høgskolen i Buskerud Side 6 av 3
I OO-systemer kan data skjules i objekter som private og generelt er det anbefalt ( informasjonsskjuling / innkapsling ). Hvis metodene er lagt til før normaliseringen (noe jeg ikke anbefaler) så kan både metoder i den klassen der dataene var før flyttingen miste dem av syne, men også kall fra andre klasser kan gå galt. En løsning vil være å gjøre dataene public så de blir synlige utenfor klassen, men dette er uheldig fordi det fører til patologiske koblinger mellom objekter ett objekt kan endre data i et annet og man får tungt vedlikehold. En annen og bedre løsning, er å flytte metodene helle eller deler av metoden sammen med de flyttede dataene, eller legge til tilgangsmetoder der dataene er og skrive om metodene som bruker dem. Når man skal bruke en RDBMS, og først har valgt å foreta datamodellering, så spiller det liten rolle for sluttresultatet i hvilken rekkefølge man arbeider med attributter, relasjoner og entiteter. I OO-modellering, kan man velge om man vil arbeide entitetsorientert eller funksjonsorientert, fra utsiden (grenseklasser) eller innsiden (entitets- og kontrollklasser). I administrative systemer, der enn god datastruktur ofte betyr mer for drift og vedlikehold enn funksjonaliteten, foreslår jeg her entitetsorientert arbeid: Begynn med entitetsklassene og legg til metodene etterpå. På denne måten unngås bl.a. problemene som er nevnt ovenfor angående metodenes tilgang til private data som flyttes pga normaliseringen. I tillegg anbefaler jeg også normalisering før metodene legges til det kan bli nødvendig å flytte attributter fra en klasse til en annen under normaliseringen. Jeg innser likevel at nye attributter kan komme til fordi en metode krever den, f.eks. til mellomlagring av verdier. I slike tilfelle vil jeg anbefale at man igjen normaliserer dataene, altså en iterert fremgangsmåte. Det kan også nevnes at i simuleringssystemer, kan man skille mellom objekter som deltar i modellen (de er aktive komponenter og ofte modell av virkelige objekter) og de som bare er ressurser for dem (som f.eks. kontrollobjekter, objekter som tar vare på mellomresultater, lager statistikk osv). Det anbefales da å starte modelleringen med dem som deltar. Regel 5: Normaliser bare dataene, ikke metodene. Arv Arv kan skape egne problemer. Attributtene fra metaklassen arves av subklassen, men oftest uten at de uttrykkelig skrives inn i modellen der. Det gjør at man lett kan glemme dem under normaliseringen. De arvede attributtene kan gi redundans hvis de der funksjonelt avhengig av subklassens attributter eller de er determinander for attributter i subklassen (alene eller sammen med attributter der). Det er således viktig å få arvede attributter uttrykkelig uttrykt i subklassene. Eksempel: Kunder med arv Kunde kundenavn : String gateadresse : String postnr : integer poststed : String årsomsetning : double Kunde kundenavn : String gateadresse : String postadresse : Post årsomsetning : double 0..n Post postnr : integer poststed : String kunder : Set of Kunde KontantKunde rabatt% : single KredittKunde kredittgrense : double KontantKunde rabatt% : single KredittKunde kredittgrense : double Knut W. Hansson Høgskolen i Buskerud Side 7 av 3
Hvis man her normaliserer attributtene postnr og poststed allerede i klassen Kunde, vil det som arves (en referanse til objektet med de to attributtene) ikke være redundant. Attributtet årsomsetning må tas med i analysen av underliggende. Det kan f.eks. godt tenkes at årsomsetningen determinerer rabatten for Kontantkunder eller kredittgrensen for Kreditkunder. Det kan være lett å overse hvis ikke alle arvede attributter tas med i subklassene. Regel 6: Start normaliseringen øverst i arvehierarkier og ta med alle arvede attributter under normaliseringen av subklasser. Regler for normalisering av RDBMS Det er velkjent at redundans skaper problemer i en RDBMS. Tilsvarende problemer kan oppstå i et objektorientert system, fordi data ofte lagres også i slike systemer. Redundans oppstår når noe lagres dobbelt og gir problemer med oppdatering, konsistens og lagringsplass. Redundans kan også være fordelaktig i noen situasjoner og gi raskere respons og større sikkerhet. Noe redundans kan ikke unngås. Normaliseringsreglene i RDBMS tar sikte på å fjerne så mye redundans som mulig. Hvis man likevel ønsker noe redundans av ovenstående grunner, anbefales vanligvis å normalisere fullt ut først, for deretter å denormalisere bevisst. Det er naturligvis sentralt at normaliseringen ikke ødelegger mulighetene for lagring av data. All normalisering bygger derfor på Heath s regel: Ikke-taps projeksjoner ("Heath's regel"): En relasjon R(A,B,C) der R.B er fullt funksjonelt avhengig av R.A kan alltid "deles" i to relasjoner R(A,B) og R2(A,C) uten at informasjon går tapt. Denne regelen (som bruker ordet relasjon synonymt med tabell i databasen) forteller at det er mulig å dele en tabell etter bestemte regler. Et typisk eksempel på at dette er aktuelt, er PERSONPOSTTABELL(PostNr,PostSted,FødselsNr) der FødselsNr er primærnøkkel (angitt ved understreking), og PostNr determinerer PostSted. Dette gir redundans, men av Heath s regel fremgår det at man kan dele tabellen i to: POSTTABELL(PostNr,PostSted), PERSONTABELL(PostNr,FødselsNr) uten å miste informasjon. Faktisk er det mulig etter deling å registrere f.eks. PostNr som ikke (enda) er knyttet til noen person. Vanlige regler for normalisering, deler modellen opp i normalformer fra første via Boyce- Codds til femte normalform. Disse reglene har, etter mitt syn, kun historisk interesse de har oppstått over tid og isteden kan man normalisere RDBMS til fjerde normalform 7 i to trinn kalt A og B etter følgende regler 8 : 7 Det finnes også en 5NF, men den har bare teoretisk interesse fordi den tar sikte på å løse problemer som ikke påtreffes i praksis. 5NF er den ultimale normalform mht projeksjoner. Det kan nok tenkes ytterligere problemer, men i så fall kan de ikke løses ved projeksjon. 8 Hentet fra mitt notat NORMALISERING AV RELASJONSDATABASER the Quick Hansson Way for Real Experts!, 990-93 Knut W. Hansson Høgskolen i Buskerud Side 8 av 3
STEP A - "DATABASESYN": Gjør om modellen slik at: ) Alle entitetstyper har minimal identifikator, og 2) Alle relasjonstyper er eksplisitt gitt ved fremmednøkkel, og 3) Alle attributtyper er atomære STEP B - 4NF: Gjør om modellen slik at: 4) alle determinander er kandidatnøkkel Min erfaring er at disse reglene er enklere for studenter å benytte, og jeg vil derfor basere meg på dem her. Det er en fordel at reglene er målorientert istedenfor aktivitetsorientert. Noe løses ved projeksjon, annet med andre teknikker det avhenger av situasjonen (slette, flytte, projisere, entitetisere, splitte attributter, innføre nye attributter osv.). Reglene har kjapt vært sjekket av C. J. Date og brukt mye av studenter og meg. Reglene passer imidlertid bare delvis for objektorienterte systemer, og må tilpasses. Regler for normalisering av OO-systemer Argumentasjonen knyttes her tett til de som ble gjengitt for RDBMS i forrige avsnitt. Jeg gjengir derfor disse og kommenterer hvert enkelt av dem nedenfor. ad Ikke-taps projeksjoner ("Heath's regel") Heath s regel gjelder relasjonsdatabaser, men kan brukes tilsvarende for klassene i OO-systemer. Siden OO-systemer ikke bruker logiske pekere ( fremmednøkler ) behøver man imidlertid ikke ha noe felles attributt i de to delklassene man realiserer assosiasjonen med mengder e.l. Vi kan derfor omskrive Heath s regel til Heath-Hansson s regel for OO-systemer: Ikke-taps projeksjoner for OO-systemer ("Heath-Hansson's regel"): En klasse R med attributtene (A,B,C) der R.B er fullt funksjonelt avhengig av R.A kan alltid "deles" i to assosierte klasser R med attributtene (A,B) og R2 med attributtet (C) uten at informasjon går tapt. Eksemplet brukt ovenfor for RDBMS, blir da slik for OO-systemer: Personpost(postNr,poststed,fødselsNr) der fødselsnr determinerer de to andre, og postnr determinerer poststed. Dette gir redundans, men Heath-Hansson s regel viser at man kan dele klassen i to assosierte klasser: Post(postnr,poststed), Person(fødselsNr) 9 uten å miste informasjon. Faktisk er det mulig etter deling å registrere postnr som ikke (enda) er knyttet til noen person. (Metoder som er lagt inn, må flyttes eller skrives om.) 9 Vil ha en referanse (peker) fra Personobjekt til Postobjekt og evt. en strukturert referanse (mengde e.l.) fra hver Postobjekt til en mengde Personobjekter. I figuren er disse tatt eksplisitt med. Knut W. Hansson Høgskolen i Buskerud Side 9 av 3
ad mål ) Alle entitetstyper har minimal identifikator I OO-systemer har alle objekter automatisk en entydig identifikator, nemlig minneadressen. Dette punktet bortfaller derfor helt, fordi det automatisk er oppfylt. Selv om alle objekter har en ID, er det likevel ikke sikkert at den er kjent for programmereren. Det kan jo genereres såkalte anonyme objekter der minneadressen kun er kjent for operativsystemet eller runtime systemet. Dette kan imidlertid programmereren stort sett styre selv. Videre kan det hende at brukeren må ha et attributt som identifikator for å kunne skille to ellers like forekomster fra hverandre. Dette vil nok forekomme sjelden, for hvis de to forekomstene har samme verdier for alle attributter, er det antakelig likegyldig for brukeren hvilken han/hun velger. Når dataene skal lagres i en RDBMS, foreslår noen forfattere å legge til en eksplisitt, logisk ID for alle objektklasser den får da navn etter klassen (så f.eks. klassen Person får attributtet personid). Ingen regel dette er automatisk oppfylt i OO-systemer (men må oppfylles hvis dataene skal lagres i en relasjonsdatabase) ad mål 2) Alle relasjonstyper er eksplisitt gitt ved fremmednøkkel Med relasjonstyper menes her assosiasjoner mellom objekter. Slike assosiasjoner realiseres enkelt i objektorientering ved at det opprettes strukturer, f.eks. lister, mengder, bags eller arrays. Dette er fullt mulig selv om assosiasjonen er av typen mange-til-mange. Også dette punktet kan man altså se bort fra under modellering av OO-systemer. Imidlertid bør alle referanser vises eksplisitt i modellen under normaliseringen de kan gi opphav til redundans. Ingen regel dette oppfylles enkelt i OO-systemer under realiseringen når referanser til andre objekter vises i modellen. ad mål 3) Alle attributtyper er atomære Dette kravet kan ikke oppfylles i objektorientering, fordi attributter kan være komplekse data som f.eks. et objekt eller en vektor. Jeg må derfor gå litt inn på hvorfor kravet er stillet til relasjonsdatabaser. Problemet med ikke-atomære attributter, er at de kan inneholde (en skjult) redundans, f.eks. Navn Sted Knut 0280 Oslo Thor 355 Hvoristan Erik 0280 Oslo I tabellen er Sted sammensatt, ikke-atomær, og det oppstår redundans ved at Oslo alltid må etterfølge 0280. Dette kan man ikke formelt oppdage ved de vanlige regler om determinander, fordi en del av et attributt ikke kan determinere en del av et attributt. Jeg tror at kravet i OO-systemer må gjøres om slik at hver kompleks del for seg må ha atomære attributtyper. Det innebærer at et man må gå nærmere inn i de komplekse attributtene (og evt deres komplekse attributter igjen osv) helt ned til bladene, det vil si helt ned til de enkle Knut W. Hansson Høgskolen i Buskerud Side 0 av 3
attributtene. Kravet om at attributtyper skal være atomære, stilles da til de enkle (ustrukturerte) attributtene. Her er et eksempel: Person poststed : Post juleønske : Set of String Post (f rom Person) postnr : Integer poststed : String Klassen Person har to komplekse data: poststed som er et objekt med to, enkle attributter, og juleønske som er en mengde med (enkle) tekster. Person er persistent, mens Post er en indre klasse i Post så alle instansene forekommer som attributt til Person. Kravet om at alle attributter skal være atomære, må da antakelig stilles til attributtene på laveste nivå, her: Person.Post.postnr og Person.Post.poststed og hver enkelt streng i mengden Person.juleønske. Regel 7: Alle enkle (ustrukturerte) attributter skal være atomære anvendes evt. rekursivt på alle strukturerte attributter som inngår i normaliseringen. ad mål 4) Gjør om modellen slik at alle determinander er kandidatnøkkel I OO-systemer finnes ikke nøkler i relasjonsdatabaseforstand, hverken primær-, kandidat-, alternativ- eller fremmednøkkel. Likevel finnes determinander. Determinander kan være et klart signal om uønsket redundans, også i OO-systemer. I OO-systemer finnes klasseattributter og objektattributter. Det finnes bare ett eksemplar av klasseattributtene, som del av klassen. Der kan det således ikke oppstå redundans, og man kan konsentrere seg om bare objektattributtene som instansieres sammen med hvert objekt. Problemet med redundans i RDBMS oppstår når det finnes determinander som ikke er kandidatnøkler, det vil si determinanden determinerer bare en del av de andre attributtene i tabellen og ikke alle. (En kandidatnøkkel determinerer alle.) Omskrevet til OO-systemer kan man helt tilsvarende kreve at en determinand skal determinere alle de andre attributtene i klassen inklusive objektets minneadresse (som alltid er en del av objektenes attributter og entydig identifiserer klassen på samme måte som primærnøklene i RDBMS). Midlertidig Regel 8: Alle objektattributter som er determinander, må determinere alle de andre, enkle objektattributtene i klassen eksklusive objektets ID-attributt. Jeg er usikker på hvordan man skal forholde seg til de strukturerte attributtene, men det må i alle fall være slik at en klasse ikke bør inneholde flere like objekter som attributtverdi, når alle objektene i klassen ses under ett. Ovenfor så jeg på eksempelet Person poststed : Post juleønske : Set of String Post (f rom Person) postnr : Integer poststed : String I denne sammenheng mener jeg at ikke mer enn ett objekt av klassen Person bør innehold et bestemt Post-objekt, ellers oppstår det redundans. Det er neppe noen determinander i klassen Person, men det kan rimeligvis være redundans i attributtet poststed når poststedene for alle Knut W. Hansson Høgskolen i Buskerud Side av 3
Person-objekter ses under ett. I Post-klassen finnes det jo et attributt postnr som er determinand for poststed, uten å determinere objektets minneadresse (som alltid er en del av objektets egenskaper/attributter). Derfor mener jeg at den midlertidige regel 8 ovenfor ikke er tilstrekkelig. I eksempelet bør det lages en egen, persistent, ytre klasse Post, og en assosiasjon (ikke aggregering) mellom Person og Post. Deretter kan de to klassene normaliseres hver for seg. Helt tilsvarende kan man argumentere for en mulig redundans i mengdene juleønske, hvis det finnes et element i mengden som determinerer andre elementer (selv om det synes søkt her). Igjen kommer altså den midlertidige regel 8 til kort. En mulig løsning på dette problemet er å innføre følgende tillegg til regel 8: Før regel 8 anvendes, skal alle komplekse attributter tenkes løst opp, slik at alle attributter som er innkapslet i strukturen inngår i klassen. Jeg foreslår derfor følgende, endelige regel 8: Regel 8: Anta at all komplekse objektattributter er løst opp, slik at alle de objektattributtene som er innkapslet i strukturen inngår direkte i klassen. Da må alle de enkle objektattributter som er determinander, determinere alle de andre, enkle objektattributtene i klassen, inklusive objektets ID. Eksempel: Kunde med indre klasse Kunde navn : String adresser : Set of Adresse Kunde navn : String adresser : Set of Adresse Kunde kundenavn : String adresser : Set of Adresse 0..n Adresse (from Kunde) gateadresse : String postnr : integer poststed : String 0..n Adresse gateadresse : String post : Post 0..n Post postnr : integer poststed : String Til venstre er klassen Kunde vist med en indre klasse Adresse som ikke er nærmere spesifisert. Problemet er at dette skjuler redundans, fordi attributtene postnr og poststed inngår i klassen Adresse. Etter regel 8 er klassen Kunde vist i midten med den indre klassen Adresse spesifisert. Det er da lett å se at de er avhengighet mellom attributtene postnr og poststed og det blir enkelt å normalisere modellen slik det er vist helt til høyre. Konklusjon I det ovenstående har jeg tatt utgangspunkt i teorien for relasjonsdatabaser og diskutert normalisering. Normalisering er solid teoretisk fundamentert og har vært anvendt lenge, så man kan være rimelig sikker på at de er korrekte. For objektorienterte systemer har man, så vidt jeg har kjennskap til, ikke tilsvarende teori. Jeg har derfor anvendt reglene fra relasjonsdatabaser analogisk for objektorienterte databaser. Det er alltid en fare med analogier de kan bli trukket lenger enn det er holdbarhet for. Hvorvidt jeg har gjort det i dette notatet, vet jeg ikke. En debatt om disse spørsmål kan muligens avklare det. Knut W. Hansson Høgskolen i Buskerud Side 2 av 3
Oppsummering Reglene jeg foreslår, er slik: Regler for hvordan: Regel : Normaliser bare klasser med flere objekter, men vær spesielt oppmerksom på at ett attributt kan representere mange objekter. Regel 2: Konsentrer innsatsen om persistente klasser. Regel 3: Normaliser alle persistente klasser, eller i alle fall entitetsklassene. Regel 4: Normaliser også assosiasjonsobjekter, og med særlig oppmerksomhet og kontroller at det ikke mangler en assosiasjonsklasse (da finnes isteden attributter som beskriver assosiasjonen). Regel 5: Normaliser bare dataene, ikke metodene. Regel 6: Start normaliseringen øverst i arvehierarkier og ta med alle arvede attributter under normaliseringen av subklasser. Regler som angir mål: Regel 7: Alle enkle (ustrukturerte) attributter skal være atomære anvendes evt. rekursivt på alle strukturerte attributter som inngår i normaliseringen. Regel 8: Anta at all komplekse objektattributter er løst opp, slik at alle de objektattributtene som er innkapslet i strukturen inngår direkte i klassen. Da må alle de enkle objektattributter som er determinander, determinere alle de andre, enkle objektattributtene i klassen, inklusive objektets ID. Oslo, 22.0.200/august 2003 Knut W. Hansson Førstelektor, Høgskolen i Buskerud Knut W. Hansson Høgskolen i Buskerud Side 3 av 3