3.2 Designovervejelser


3.2.1 Indledning

Før systemet implementeres er der en række design-overvejelser der skal tages stilling til. Teknologien er fastlagt, men der er stadig mange måder grundlæggende at designe sit system på. Et godt grundlæggende design giver et mere velstruktureret og ensartet system. Det gør det nemmere at udvikle og frem for alt nemmere at ændre/vedligeholde senere hen. I det følgende er beskrevet de forskellige overvejelser vi har gjort, og en gennemlæsning bør give en bedre forståelse af kodens opbygning.


3.2.2 Størrelsen af Objekterne

Den del vi skal implementere ligger mellem Portal-to-Go og diverse databaser. Selv om der er mange funktioner i MAOV-systemet, vil hver enkelt funktion grundlæggende blive opbygget ens. Det handler om at hente data fra databasen, formatere det til XML og sende det til Portal-to-Go.

På denne model er systemet delt op i fem objekter, der hver har en meget begrænset opgave. Ved at dele systemet op i mange objekter, vil det være nemmere at tilpasse systemet, hvis det skal flyttes, da nogle af objekterne kan forblive uændrede. Eksempelvis hvis databasen ændres, så data kommer til at ligge på en anden måde, er det kun "Data Reader"-objektet der skal ændres. "DB Access"-objektet er meget generelt, og vil kun skulle ændres hvis det er en væsentlig anderledes database. Objekterne på ovenstående figur har følgende funktioner:

Ideelt objektorienteret, skal systemet deles op i de mange objekter, men vi kan allerede nu forudse, at flere af objekterne vil blive meget små. Det kan derfor være en fordel, at flere af objekterne smelter sammen. Nogen ændringer vil alligevel kræve ændringer i flere objekter alligevel. Eksempelvis, hvis man skal have en ny oplysning med på en side, skal Data Readeren hente den nye information, Entity-objektet skal kunne indeholde den, og GUI Buideren skal vise den. Der er to grundlæggende muligheder for sammensmeltning:

Vi vælger løsningen med 2 objekter i et, da det giver en logisk opdeling af systemet, så den ene halvdel koncentrerer sig om at generere XML'en der skal vises, mens den anden sørger for at hente de relevante oplysninger i databasen (layers, se bilag XXX side XXX).

Der er en helt anden model vi har overvejet men gået bort fra. Det går ud på at der er een klasse der kan generere samtlige entitets-objekter, på tværs af funktionerne. Det vil være nogenlunde ens hvordan de forskellige entitetsobjekter hentes fra databasen, så det kunne være en fordel at samle dem. Dette er illustreret på nedenstående model.

Konklusionen af disse overvejelser er, at vi samler Entity og Data Reader i eet objekt for hver funktion. Der vil blive een Adapter som fordeler opgaverne ud, og kun een DB Access der bruges af alle entitets-objekterne. Hvis der skal tilføjes nye funktioner så er det kun Adapteren der skal kende den nye funktion, ingen af de andre objekter skal modificeres. På nedenstående figur er afbilledet tre vilkårlige funktioner.

Entitets-objekter henter selv deres data fra databasen når de oprettes. Dataene gemmes i instansvariabler i entitets-objektet, så de er lige til at få fat på, med get-metoder.


3.2.3 Public variabler vs. get- og setmetoder

Det er anset som god skik at lave get- og setmetoder, frem for bare at definere sine variabler som public, men det er nemmere og mere direkte at arbejde med public variabler. Get- og setmetoder anbefales for at beskytte sine variabler. Man udelader sin setmetode for at skrivebeskytte variablen, men det er ikke ligegyldigt om man returnerer en primitiv variabel, eller en reference til et objekt.

Returnerer man en primitiv variabel (int, char, float o.s.v) er den oprindelige variable beskyttet, da det kun er en kopi af variablens indhold der returneres. Returnerer man derimod et objekt eksempelvis en Vector, returnere man en reference til selve objektet, og modtageren kan så frit ændre i objektet med de metoder der er i klassen som addElement(Object) og clear() i eksemplet med en Vector. Man bør derfor ikke returnere objekter med get-metoder.

String er også et objekt, og man bør derfor umiddelbart ikke returnere String-objekter. Men String-objektet er specielt idet at det ikke kan ændres. En metode som eksempelvis substring som skærer noget af en String ændrer ikke i selve den String man udfører den på, men derimod oprettes en ny String med resultatet af substring-kaldet og returnerer den. Derfor er den oprindelige String beskyttet, og man kan derfor uden bekymring returnere String-objekter i get-metoder.

Et array oprettes ikke helt som et objekt, men det er lige så ubeskyttet som eksempelvis en Vector. Hvis man returnerer referancen til et array kan modtageren frit indsætte falske værdier på de forskellige pladser i array'et. Man bør derfor give array-indexet med til get-metoden, som så kun returnerer den enkelte primitiv eller String som er på den plads i Array'et. Der er dog ikke noget galt i at returnere et helt array som er oprettet og fyldt med primitiver/Strings i get-metoden, hvis det kun skal returneres, og ikke gemmes i objektet der lavede det. Hvis der bliver sat falske værdier i et sådant array, vil det ikke påvirke objektet der oprettede det.

MAOV-systemet stiller ikke de store krav til at beskytte data, som ovenfor beskrevet. Men når man bruger tid på at lave get-metoder kan man lige så godt gøre det ordentligt. Erfaringerne for dette afsnit bygger på forsøgene i klassen TestPassingObjects (også beskrevet i afsnit XXX om design-test side XXX).


3.2.4 Genbrug objekter vs. opret nye

Systemet består af flere objekter af forskellige klasser. Man kunne oprette samtlige objekter, når programmet startes, men det er tidskrævende, og det er ikke nødvendigvis alle objekterne der skal bruges. Derfor er det smartere, kun at oprette objekterne når de skal bruges. Men hvad gør man så når man skal bruge dem flere gange.

Enten opretter man dem hver gang man skal bruge dem. Det tager tid, og er unødvendigt, hvis indholdet ikke skal ændres i objektet. Man kunne istedet undersøge om de er oprettet hver gang de skal bruges, og så kun oprette dem, hvis de ikke allerede er oprettet. Det er simpelt at programmere:

  • if(entity == null) entity = new Entity(arguements);

    Entitets-objekterne henter selv deres indhold ud fra databasen når de oprettes, eksempelvis oplysninger om licenser for et firma. Hvis brugeren vil se licenser for et andet firma, skal entitets-objektet opdateres med oplysninger om det andet firmas licenser. Spørgsmålet er så om objektet skal have en update-funktion, som gør det samme som constructoren, eller om constructoren skal kalde update-funktionen?

    Vi har valgt ikke at kunne opdatere et entitets-objekt. Man opretter objektet når man skal bruge det, og opretter et nyt, hvis man skal bruge et med nyt indhold, men af samme type. Det giver ingen mening at oprettet et af vores entitets-objekter uden indhold, så constructeren skal indeholde den kode der henter data op fra databasen.

    Noget af det der tager relativt lang tid i java er oprettelse af objekter og garbage-collection, men om vi vælger at genbruge frem for at oprette nye af vores objekter kommer ikke til at betyde noget mærkbart i vores samlede system, da der bliver oprettet mange objekter af de andre java-klasser vi bruger (PtG, java.sql). Vi kunne godt lide ideen med at entitets-objektet selv fylder sig med data, og det virker mest logisk at man opretter et nyt, når man skal have nye data.

    Det har vist sig under implementationen at det ikke har været alle informationer man kan hente fra databasen ved oprettelse, så de hentes senere med et metodekald. Hvis vi skulle følge ideen med kun at hente oplysninger i constructoren, skulle vi have lavet endnu flere entitets-klasser. Vi mente dog at yderligere klasser ville gøre systemet unødvendigt uoverskueligt.


    3.2.5 Hvad læses, og hvad skrives

    Systemets primære opgave er at hente (læse) data fra Oracle DK's databaser, og præsentere dem for brugeren på en håndholdt enhed (WAP). MAOV-systemet kan på ingen måde få skrive-rettigheder til Oracle's centrale databaser, da projektet som skole-projekt ikke kan opnå nok tillid. Det er dog ikke noget problem, da vi kun skal læse de centrale oplysninger.

    Det har ikke været muligt at opnå læserettigheder til samtlige af Oracle DK's centrale databaser, og det har i sig selv begrænset systemet. Det har faktisk været grunden til de fleste afgrænsninger af systemet. Der er dog rigeligt tilgængelig data til at lave et brugbart MAOV-system.

    Det skulle være muligt at tilmelde kunder til seminarer med MAOV-systemet, hvilket umiddelbart kræver at vi kan skrive til databasen. Det er dog ikke tilfældet, idet tilmelding til seminarer kun kan udføres af HR-afdelingen, af organisatoriske årsager. MAOV-systemet skal derfor sende en e-mail til HR, som foretager skrivningen i databasen. Med andre ord, skrivning til databasen foregår ved at sende en e-mail til en der har skrive-rettigheder. Det virker besværligt at skulle blande et menneske ind i systemet, men det er den måde det skal foregå hos Oracle DK.

    MAOV-systemet har adgang til en database med fuld læse/skrive-rettigheder. I den kan MAOV-systemet gemme data, der kun skal bruges til MAOV-systemet. Det kan være oplysninger om hvilke kunder en bruger sidst har søgt på, så brugeren ikke skal søge de samme kunder igen og igen. Desuden vil de mulige action-points blive gemt i en tabel, så nye kan tilføjes uden at koden skal re-compiles.