27.07.2013 Views

Carletti A/S 2012 - Kalabakas.dk

Carletti A/S 2012 - Kalabakas.dk

Carletti A/S 2012 - Kalabakas.dk

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

<strong>Carletti</strong> A/S <strong>2012</strong><br />

Lavet af<br />

Mads Pedersen<br />

Robert Kristian Nogal<br />

Frederik Emil Pontoppidan Thygesen<br />

Side 1 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

______________________________________________<br />

Mads Pedersen<br />

______________________________________________<br />

Robert Kristian Nogal<br />

______________________________________________<br />

Frederik Emil Pontoppidan Thygesen<br />

Side 2 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Indhold<br />

Informations Teknologi i Organisationer ............................................................................................. 5<br />

<strong>Carletti</strong> A/S (Robert & Frederik) ..................................................................................................... 5<br />

SWOT (Fælles) ................................................................................................................................ 6<br />

Organisations form (Frederik) ......................................................................................................... 6<br />

Produktionssystem (Mads) ............................................................................................................... 7<br />

Produktions-filosofi ................................................................................................................................... 7<br />

Produktions-layout .................................................................................................................................... 8<br />

Produktionsstyring..................................................................................................................................... 9<br />

Produktionsformer .................................................................................................................................... 9<br />

Business Case (Fælles)................................................................................................................... 10<br />

Formål ...................................................................................................................................................... 10<br />

Forretningsmæssigt omfang .................................................................................................................... 10<br />

IT omfang & krav ..................................................................................................................................... 11<br />

Interessenter ........................................................................................................................................... 11<br />

Alternativ løsning ..................................................................................................................................... 11<br />

Risici ......................................................................................................................................................... 11<br />

Implementeringsstrategi ......................................................................................................................... 11<br />

Organisation ............................................................................................................................................ 12<br />

Key Performance Indicators (KPI) ............................................................................................................ 12<br />

Konsekvens af løsningen ......................................................................................................................... 12<br />

Logistisk effektivitet – hvordan opnås det? (Robert) ..................................................................... 12<br />

Leveringsservice ...................................................................................................................................... 13<br />

Logistikomkostninger .............................................................................................................................. 14<br />

Vurdering af logistiksystemet .................................................................................................................. 15<br />

Software Design ................................................................................................................................. 16<br />

Vision (Fælles) ............................................................................................................................... 16<br />

Krav (Mads & Frederik) ................................................................................................................ 16<br />

Use-cases (Fælles).......................................................................................................................... 16<br />

Use-case oversigt ..................................................................................................................................... 17<br />

Aktør beskrivelse ..................................................................................................................................... 17<br />

Use-case beskrivelser .............................................................................................................................. 17<br />

Sporbarhedsmatrix (Frederik) ................................................................................................................. 19<br />

System sekvens diagram (SSD) (Frederik) .................................................................................... 19<br />

Side 3 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Design sekvens diagram (DSD) (Fælles) ....................................................................................... 21<br />

Analyse Klasse Diagram (Fælles) .................................................................................................. 24<br />

Tilstandsdiagrammer (Mads) ......................................................................................................... 25<br />

Design Klasse Diagram (Fælles).................................................................................................... 26<br />

Arkitektur (Mads) .......................................................................................................................... 29<br />

Testrapport (Mads) ......................................................................................................................... 29<br />

Modultest af Proces-klasse ...................................................................................................................... 29<br />

Use-case test af Opret Opskrift ............................................................................................................... 33<br />

Status (Mads) ................................................................................................................................. 34<br />

Resume af forløbet (Robert) .......................................................................................................... 35<br />

Refleksioner (Robert) ..................................................................................................................... 36<br />

Ordbog ........................................................................................................................................... 37<br />

Software konstruktion ........................................................................................................................ 38<br />

Klassemodel (Fælles) ..................................................................................................................... 38<br />

Implementering af design-modellen ....................................................................................................... 38<br />

Sammenhæng mellem klasserne ............................................................................................................. 38<br />

Polymorfi ................................................................................................................................................. 40<br />

JavaDoc .................................................................................................................................................... 40<br />

Design Mønstre ....................................................................................................................................... 42<br />

Implementering af arkitektur (Robert) ........................................................................................... 45<br />

Fejl håndtering (Frederik) .............................................................................................................. 46<br />

JUnit test (Mads) ............................................................................................................................ 47<br />

Specielt interessant kode (Fælles) .................................................................................................. 49<br />

TimeThread & SystemDato klasserne ..................................................................................................... 49<br />

checkVareStatus & beregnStatus metoderne ......................................................................................... 51<br />

ColorRender-klassen ................................................................................................................................ 53<br />

Guided Tour (Fælles) ..................................................................................................................... 54<br />

Konklusion ......................................................................................................................................... 58<br />

Bilag ................................................................................................................................................... 60<br />

Klassebeskrivelser .......................................................................................................................... 60<br />

Design Klasse Diagram .................................................................................................................. 74<br />

<strong>Carletti</strong> Tidslinje ............................................................................................................................ 75<br />

Side 4 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Informations Teknologi i Organisationer<br />

<strong>Carletti</strong> A/S (Robert & Frederik)<br />

<strong>Carletti</strong> A/S er en dansk chokolade- og slikfabrik, der har eksisteret siden 1918. Siden da er virksomheden<br />

vokset og er i dag en virksomhed, der i 2011, havde en omsætning på 644 mio. kr. 1 . <strong>Carletti</strong> A/S producerer<br />

og sælger et bredt sortiment af chokolade og konfektureprodukter, som findes hovedsagligt i Danmark og<br />

Nordeuropa.<br />

Koncernen er vokset stødt siden da hvor de har in<strong>dk</strong>øbt mange maskiner, fabrikker m.m. For den fulde<br />

tidsoversigt henviser vi til bilaget med tidslinjen over udviklingen. I dag består virksomheden af et<br />

moderselvskab, <strong>Carletti</strong> A/S, samt datterselskaberne, ASM Foods AB i Sverige, samt <strong>Carletti</strong> Polska i Polen<br />

hvor de ejer størstedelen af selskaberne. Derudover har de en stor andel af Oy NIS – Nordic Industrial Sales,<br />

dog uden at have størstedelen.<br />

Hele koncernen har ikke skiftet ejerskab under forløbet og bliver den dag i dag stadig ejet af Givesco A/S i<br />

Give.<br />

Virksomheden består af en forholdsvis dyb funktionsbaseret struktur, med en vertikal arbejdsdeling, der er<br />

baseret på et linje- og stabsprincip. 2 . Dette betyder at centraliseringen dannes i form af et hierarki. I toppen<br />

af dette hierarki finder vi administrerende direktør Niels Petersen, med et kontrolspænd på 7<br />

underafdelinger.<br />

Stabsfunktionen findes i form af in<strong>dk</strong>øbsdirektør Børge Hejlesen, der kan være med til at aflaste linjeledere<br />

og underafdelinger på tværs af organisationsdiagrammet.<br />

Denne type virksomhedsstruktur, der er baseret på funktionsprincippet, er meget typisk for en<br />

stordriftsfungerende produktionsvirksomhed som <strong>Carletti</strong> A/S. Idet der er mulighed for udvikling af<br />

kernekompetencer i nogle standardiserede opgaveudførelser som fx i produktionen.<br />

1 www.carletti.com/default.aspx?ID=471<br />

2 baseret på bilag 1 ”Organisationsdiagram”.<br />

Side 5 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

SWOT (Fælles)<br />

INTERNE SITUATION<br />

Stærke sider (strengths) Svage sider (weakness)<br />

Stor erfaring<br />

Solidt produkt<br />

Malkekos produkter<br />

Produktudvikling<br />

Faste storkunder (indtægter)<br />

Høj indgangsbarriere<br />

Leveringsservice<br />

Stor målgruppe<br />

Stort sortiment<br />

Dedikeret arbejdskraft<br />

Mellemlager problem<br />

Spild i produktion<br />

Sårbare overfor politiske tiltag (fx sukkerafgift)<br />

Finanskrise (en varer der let kan tilsidesættes)<br />

Dragémaskiner kører langsomt<br />

EKSTERNE SITUATION<br />

Muligheder (opportunities) Trusler (threats)<br />

Robotstyret lager og produktion<br />

Større produktudvikling<br />

Opkøbe<br />

Udvide markedet<br />

Flytte produktion til udlandet<br />

Forbedringer i produktionslinjen<br />

(dragéprodukter)<br />

Markedsføring (fx tv)<br />

Finanskrise<br />

Sukkerafgift<br />

Sundhedstrend<br />

Maskinstop<br />

SWOT-analysen er med i denne del af rapporten for at danne grundlag for de øvrige afsnit. For at tage et<br />

eksempel kan vi afsløre at senere i rapporten vil vi have fokus på bl.a. at komme med et forslag til en<br />

løsning der ville kunne løse problemstillingen i form af deres mellemlager-problem. Dette kan ses i SWOTanalysen<br />

som værende en af virksomhedens svage sider. Grunden til SWOT-analysen er med er for at få et<br />

overblik over de ting som virksomheden gør godt, samt virksomhedens svage sider som kan optimeres for<br />

bedre produktion.<br />

Organisations form (Frederik)<br />

<strong>Carletti</strong> A/S kan karakteriseres til at være en blanding af den mekaniske og organiske organisations struktur.<br />

<strong>Carletti</strong>s produktion styres efter ordrebestilling, sæson udsving og i støre mængder til lager bliver<br />

produceret efter tidligere års tendenser.<br />

En produktionsvirksomhed hvor der arbejdes i stabile omgivelser og med gentagne ensformige opgaver, er<br />

det mest effektivt, at designe organisationen efter mekanistiske principper, såsom: stabil arbejdsdeling og<br />

fast produktions rutine, præcise foreskrevne pligter, position i hierarkiet og faste kommunikations kanaler.<br />

Hvorimod virksomheder der skal have en hurtig reaktionsevne til at ændre arbejdsrutinerne, så de passer til<br />

de komplekse opgaver de får ind, er mere effektive ved at anvende de organiske principper – opdeling af<br />

arbejdet varierer efter viden og erfaring, ansvaret bliver mere generelt fordelt og hvor den personlige<br />

erfaring tæller mere end ens position hierarkiet.<br />

Side 6 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Den mekaniske forms stabile og funktionsbaserede arbejdsdeling er mest hensigtsmæssig ved<br />

produktionen af de større faste mængder slik til lageret. Hvor den organiske producerer efter<br />

ordrebestillinger og tidligere års tendenser.<br />

Udgangspunktet for Mintzberg´s model er stabilitet, intern såvel som ekstern og hvordan man kan indstille<br />

strukturen i forhold til stabiliteten.<br />

Produktionssystem (Mads)<br />

For at kunne beskrive det egentlige produktionssystem som danner grund for den storproducerende<br />

<strong>Carletti</strong> Koncern skal man se på de fire dele som udgør dette. I den følgende tekst kan man læse omkring<br />

gruppens analyse af opbygningen af <strong>Carletti</strong>s produktionssystem. De fire dele er: produktions-filosofi,<br />

layout, styring samt form. Dette afsnit er lavet på baggrund af teksten omkring produktion samt logistik.<br />

Produktions-filosofi<br />

Da <strong>Carletti</strong> er en masseproducerende virksomhed inden for konfekture og chokolade ville dette gøre dem<br />

til en perfekt virksomhed til at benytte sig af Ford ismens principper. Når man snakker om Ford ismen<br />

inkludere det automatisk et vist fokus på området omkring høj produktivitet. Dette betyder at man opnår<br />

et så højt output af de specifikke vare hvor der er blevet brugt en så lille ressourceindsats som muligt. For<br />

at optimere denne produktivitet kræver det at man opdeler procesforløbet i forskellige underprocesser<br />

hvor der nemmere kan benyttes forskellige maskiner til at fuldføre denne. Samtidig gør det<br />

arbejdsopgaverne nemmere for de forskellige ansatte da de så kun skal tage sig af en lille, simplere, del af<br />

produktionsprocessen. Dette gør også at det er nemmere at oplærer nye ansatte i virksomhedens<br />

produktion da dette ikke kræver nær så lang tid, grundet den simplificerede proces.<br />

For at tage udgangspunkt i <strong>Carletti</strong> produktionsbeskrivelsen ved produktionen af dragé-produkter kan man<br />

ane brugen af Ford ismen. Denne proces er ideel til at benytte denne da der automatisk er så mange<br />

underprocesser. For at nævne nogle af underprocesserne hvor der indgår forskellige maskiner i kan man<br />

tage fat i:<br />

Støbning af kernen hvor der benyttes kedler<br />

Blanding af basisdrageringen<br />

Tørring af mellem- og færdigprodukter<br />

Påføring af ydre dragering.<br />

Ved hver af disse processer opholder produktet sig et bestemt sted i produktionen hvor lige præcis denne<br />

opgave bliver udført. Når man så står og mangler en medarbejder skal denne medarbejder ikke forstå<br />

hvordan hele produktionen af et dragé-produkt forløber men blot forstå og lære hvordan lige præcis hans<br />

station skal køres. Ulempen kan så være at hvis han skal forflyttes til en anden station i produktionen skal<br />

han på ny oplæres i denne funktion.<br />

Når man så tager fat i den anden kendte produktions-filosofi som kaldes Lean, er der både for og<br />

modargumenter for brugen af denne filosofi i en virksomhed som <strong>Carletti</strong>. En af hovedpointerne i denne<br />

filosofi er at man skal undgå at producere til et færdigvare-lager da dette gør at produktet bliver dyrere for<br />

kunden eftersom et lager medfører ekstra omkostninger. Dog kan det være svært for en virksomhed som<br />

<strong>Carletti</strong> at være så dynamiske at de hele tiden kan skifte deres produktions-opsætning til fordel for de<br />

forskellige kunders behov. Her er det relevant at finde en mellemvej hvor der stadig bliver benyttet et lager<br />

så kunderne altid kan få deres vare efter deres eget behov. Det at indføre en ren Lean filosofi som værende<br />

den eneste er ikke optimalt for virksomheder der producere i så stor kvantitet som en virksomhed af<br />

<strong>Carletti</strong>s størrelse.<br />

Dette kan forstås i forhold til et eksempel hvor en stor kunde laver en uforudset bestilling som en Lean<br />

tilgang ellers ikke ville kunne producere. Hvis denne storkunde ikke får sine vare til tiden kan <strong>Carletti</strong><br />

risikere at miste kunden fordi de ikke havde varerne til tiden pga. Produktionssystemets filosofi. Derfor er<br />

Side 7 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

det vigtigt for en producent som dem at have et relativt stort lager så det ikke er grundet overskredne<br />

deadlines at kunder evt. forsvinder.<br />

Lean-tilgangen bliver derfor oftest benyttet på producenter der har forholdsvist små ordrestørrelser og<br />

derfor kan omstille sig meget hurtigt til de forskellige kundebehov der er i forhold til ordrene.<br />

Det en Lean-manager dog kan gøre i en virksomhed som <strong>Carletti</strong> er at se på de processer som allerede<br />

eksistere og gå ind og optimere på disse. Som et eksempel kan det være at Lean-manageren skal<br />

omrangere produktions-layoutet for at optimere det vare-flow der er, sørge for at spild på mellem-vare<br />

lageret bliver minimeret og andre lignende optimeringer. Her er det også aktuelt for at snakke om selve<br />

opgaveformuleringens problem stilling. Det at et mellem-vare lager er en flaskehals vil også være et af de<br />

områder som ville kunne løses af en Lean-manager.<br />

Produktions-layout<br />

Det er meget begrænset hvad vi igennem den udleverede beskrivelse har fået at vide omkring det fysiske<br />

layout af mellem-lager rummet samt produktionen i hele taget. Derfor holdes der fokus på det som der<br />

rent faktisk er viden om, nemlig mellemlageret hvor de forskellige bakker bliver lagret til tørring i perioder<br />

med forskellig tidslængde.<br />

Det der sker når en produktion har færdiggjort en proces som kræver en tørretid er at køre den ind og<br />

sætte den på mellem-lageret hvor den så, ved hjælp af ruller, bliver transporteret ned i den anden ende<br />

hvor den bliver plukket til dragering.<br />

Her kan man måske overveje om de forskellige procesforløb ikke skal have hver deres række eller endda<br />

deres helt eget niveau så man hele tiden kan holde styr på hvilken proces de skal til næste gang de bliver<br />

plukket. Men mere om det senere.<br />

Når man skal sammenholde det med den udleverede teori kan man begynde at argumentere for og imod<br />

forskellige typer af layouts. Som et eksempel kan man godt argumentere for at <strong>Carletti</strong> benytter et<br />

funktionslayout eftersom man kunne antage at der ikke var en lakridsstøbe kedel for hver type slik som<br />

benytter en eller anden lakrids komponent i den. Her vil man nok have et centralt lakridsstøbe kedel rum<br />

hvor al lakrids i virksomheden ville blive produceret hvor det efterfølgende vil blive transporteret videre til<br />

de processer som tager udgang i grundproduktet lakrids.<br />

Samtidig med at de måske benytter sig af et funktionslayout kan man også kigge på andre typer, så som<br />

linjelayoutet, flow produktionen. Som nævnt før er <strong>Carletti</strong> en virksomhed som producere en stor kvantitet<br />

af standardiserede vare, både ud fra ordre men også til lagering. Her vil et linjelayout være ideelt da der<br />

bliver produceret store mængder af det samme produkt på en kontinuerlig linje uden sideløbende<br />

produktioner af andre produkter (der ses her bort fra at de sandsynligvis har en fælles lakridsstøbe<br />

produktion til mange produktprocesser). Dette layout bliver benyttet til de produkter i et firma som firmaet<br />

ved, pr. statistik og erfaring, er rentable og de er sikre på at kunne få afsat. Dette kan i <strong>Carletti</strong>s tilfælde<br />

være skumbananer og P-tærter som de har stor succes med at sælge.<br />

Ser man det fra en medarbejders synspunkt kan denne type layout blive meget umotiverende og<br />

ensformigt hvilket i værste tilfælde vil resultere i utilfredse medarbejdere. Her er det en god ting at <strong>Carletti</strong><br />

har multifunktionelle medarbejdere som hele tiden kan finde nye produktionsforløb at indgå i hvis de<br />

finder den nuværende monotom. På den måde får man en mere fleksibel arbejdsstyrke som gør at man<br />

ikke ligger inde med produktionsforløb der er afhængig af specialiserede medarbejdere som ikke ville<br />

kunne erstattes af andre. Dette problem har de dog med de medarbejdere der ligger inde med nogle af de<br />

få truckcertifikater. Dette er et typisk specialiseringsproblem hvor firmaet kan risikere store<br />

flaskehalsproblemer hvis disse medarbejdere er syge.<br />

Ud fra alt dette kan man komme med begrundelser for at disse to typer layout kombineret giver et gruppelayout<br />

som passer på <strong>Carletti</strong>s produktion som blev klassificeret som en jobshopproduktion. Dette giver<br />

nemlig et miks mellem linje og funktionslayout som gør at de kan kører små serier med svingende<br />

afsætning i selvstyrende teams.<br />

Side 8 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Produktionsstyring<br />

Da teksten på dette område har været meget sparsom omkring viden på produktionsstyrings området kan<br />

vi dog kun komme ind på principperne og drage paralleller til den sparsommelige viden fra teksten.<br />

Produktionsstyringen består som basis af to dele, nemlig en planlægningsdel samt en overvågningsdel.<br />

Planlægningsdelen er typisk en funktion som bliver håndteret på mellemleder niveau, bl.a. fordi det er for<br />

administrativt for folket på gulvet og det ve<strong>dk</strong>ommer bl.a. heller ikke virksomhedens øverste direktør. På<br />

<strong>Carletti</strong> ville denne opgave typisk gå til produktionsplanlæggerne Peter og Leif. De vil få de forskellige<br />

ordrer passet ind så leveringstidspunktet samt kvantiteten bliver overholdt så det resultere i kunder der<br />

kommer igen. Når man så kigger på overvågningssystemet af produktionsstyringen bliver man nød til at<br />

lave nogle antagelser når det kommer til den konkrete virksomhed, i dette tilfælde <strong>Carletti</strong>. I denne<br />

virksomhed vil det typisk være en teamleder som rapportere til produktionsplanlæggerne om de<br />

overholder tidsplanen eller om planerne skal omlægges så de kommer til at passe.<br />

Produktionsformer<br />

Når man ser på de forskellige produktionsformer som bliver nævnt i den udleverede tekst er der to former<br />

giver mere mening at benytte i virksomheden <strong>Carletti</strong>. Den ene er typen jopshop produktionsformen. Det<br />

er her virksomhedens forskellige vare er standardiseret i forskellige udgaver som bliver produceret i små<br />

serier flere gange om året. Dog kan man debattere hvornår noget er i små serier, men ikke desto mindre<br />

kan man argumentere ud fra oplægget.<br />

Det der sker for <strong>Carletti</strong> nogle gange om året er at de enten får en stor ordre som kræver at hele fabrikken<br />

bliver omstillet på at producere lige præcis den kundes ordre, eller hvis det f.eks. bliver jul hvor der<br />

igennem prognoser for salg har vist sig at kræve ekstra arbejde for at holde trit med udbud og<br />

efterspørgsel. Dette kan argumentere for at <strong>Carletti</strong> benytter jobshop formen.<br />

Når det kommer til et argument for at <strong>Carletti</strong> benytter sig af flowproduktions formen kan man gå ind og se<br />

på hvor ofte deres produktion bliver omstillet for at tilgodese et specifikt produkt eller ordre. Hvis der dog<br />

forekommer relativt få omstillinger om året kan man godt argumentere for at virksomheden benytter<br />

flowproduction. Mens hvis der sker en omskiftning f.eks. to gange om måneden er virksomheden nok<br />

tættere på at benytte en jobshop form.<br />

Det der argumentere for en flowproductions form lige meget omstillings hyppigheden er det flow som<br />

produkterne gennemgår. Dette flow minder meget om en standard samlebånds princip som er en fast del<br />

af flow-produktions virksomheders opbygning.<br />

Side 9 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Business Case (Fælles)<br />

Formål<br />

At få en bedre styring af mellemvarelageret, så tørretiderne bliver overholdt bedre og spildet formindskes.<br />

Forretningsmæssigt omfang<br />

En opdeling af mellemvarelageret, tilsvarende de 3 tørretidskategorier: min, perfekt og maks. Det skal<br />

fortsat fungere efter FIFO-princippet for at få en bedre styring af pluknings-rækkefølgen og sørge for at<br />

produkterne får den rette tørreperiode. Hvis der er en dominerende størrelse indenfor en bestemt<br />

kategori, så skal dette område kunne overtage den ubrugte plads fra de andre kategoriers lagerdel.<br />

For at holde styr på bakkernes indhold og vedrørende informationer implementeres hver bakke med en<br />

RFID-chip. Denne chip bruges også til at lokalisere bakkens placering og resterende tørretid. For at denne<br />

løsning kan anses for at værende succesrig, skal det systemet kunne måle den maksimale spildprocent på 2<br />

% - alt over ville vise løsningen værende ineffektiv.<br />

En problemstilling ved denne løsning ville være at brugeren i mellemvarelageret ikke får lagt den rette<br />

information ind i bakkens chip, hvilket vil resultere i at bakkens indhold ikke vil være brugbart. Dette vil<br />

resultere i et yderligere spild i stedet for det ønskede resultat.<br />

De berørte brugere er de ansatte der styrer mellemvarelageret, der skal efteruddannes i brugen af det<br />

implementerede system. Dette inkluderer både indtastningen af information til chippen, samt placeringen<br />

af pallen på dens rette placering. Derudover skal brugerne også kunne aflæse bakkens information korrekt<br />

og derved få plukket korrekt.<br />

Side 10 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

IT omfang & krav<br />

Først og fremmest skal chippen fungere og implementeres i bakkerne. Når bakkerne kommer ind på<br />

mellemvarelageret skal de forbi et check-in ved indgangen, hvor informationen bliver skrevet til chippen,<br />

som blandt andet inkluderer dead-line for endt tørretid. Dette bliver gjort igennem computer. Det skal<br />

være muligt at aflæse bakkens information på et givent tidspunkt med en håndholdt scanner. Efter endt<br />

tørretid vil en alarm gøre medarbejderen opmærksom på at bakken/pallen skal sendes videre til<br />

forarbejdning. Bakkens placering kan ses på en skærm i lageret placeret og evt. på en skærm på trucken.<br />

På denne måde sikres det at den rette bakke bliver taget på det rette tidspunkt. Når bakken forlader<br />

mellemvarelageret skal det checkes ud. Systemet er delt op i 2 under systemer, overvågningsdelen og<br />

registrerings delen.<br />

Så hele systemet kommer til at bestå af RFID-chips i bakkerne, skærme til at aflæse bakkernes placering,<br />

samt scannere til aflæsning og indlæsning af data. Alt i alt bliver der brugt eksisterende og velfungerende<br />

teknologier, hvilket gør at der ikke skal investeres i yderligere udvikling.<br />

ID Beskrivelse Type Prioritet<br />

1 Systemet skal have en alarm funktion ved endt tørretid Funktionelt M<br />

2 Skal kunne vise en placering på et display Funktionelt M<br />

3 Chippen i bakkerne skal kunne læses og ændres efter behov Funktionelt M<br />

4 Systemet skal være brugervenligt og overskueligt Ikke<br />

funktionelt<br />

S<br />

5 Oppetid på minimum 98 %. Stabilt og driftssikker, samt hurtigt. Ikke<br />

funktionelt<br />

M<br />

6 Nemt at brugerdefinere til andre lagere Funktionelt C<br />

7 Hver bakke skal kunne læses på et givent tidspunkt af en Funktionelt<br />

skanner.<br />

S<br />

8 Muligt at printe en liste med alle bakker og deres informationer Funktionelt S<br />

Interessenter<br />

Interessenterne i dette system er hovedsagligt personalet der er tilknyttet mellemvarelageret, som direkte<br />

kommer til at bruge det. Derudover kan der argumenteres for at mellemledelse samt topledelsen har<br />

interesse i systemet eftersom det vil formindske spildet og forøge overskuddet.<br />

Alternativ løsning<br />

Nulløsningen ville være at fortsætte med det nuværende system og dermed acceptere spildet på min. 2 % -<br />

hvilket er et tabt pr. måned på minimum 270 000 kr. (30 000 kg*15 kr.*30 dage *0,02). Denne løsning løser<br />

intet!<br />

Risici<br />

En risiko kunne være at implementerings fasen bliver meget lang og brugerne har svært ved at vende sig til<br />

det nye system, dermed vil produktionsstyrken blive nedsat og der kan så opstå længere leveringstider.<br />

Eftersom dette system skal udvikles fra bunden vil der også være behov for opgradering når fejl findes.<br />

Dette kan også medføre stillestående produktion i visse tilfælde.<br />

Implementeringsstrategi<br />

Alt hardware installation foregår imens den daglige produktion foregår mere eller mindre uforstyrret. Dette<br />

gøres ved at nogle teknikkere bliver sendt ud på fabrikken for at sætte skærme og scannere til og chippen i<br />

bakkerne bliver implementeret når de løbende bliver ”ledige”.<br />

Når alt udstyret er sat til og funktionstestet skal de forskellige teams fra fabrikken undervises i brugen af<br />

det nye system. Dette inkluderer brug af scannere, samt benyttelse af skærmene til plukning af bakker.<br />

Side 11 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Dette kunne evt. foregå over en weekend i fabrikkens konference lokaler, hvor de ansatte også kommer ud<br />

og kan afprøve systemet grundigt igennem med en tekniker/underviser.<br />

Organisation<br />

Gruppen vil være repræsenteret som projektejere og har dermed ansvaret for evt. opdatering af business<br />

case. Gruppen er blevet nøje sammensat efter individuelle spidskompetencer og er derfor velkvalificeret til<br />

at løse <strong>Carletti</strong> A/S problemstilling.<br />

Key Performance Indicators (KPI)<br />

Det gennemgående nøgletal i denne case er spildprocenten på maks. 2 %. Problemstilling vil vise sig<br />

værende løst eller ej når spildprocenten ligger stabilt under 2 %.<br />

Konsekvens af løsningen<br />

Omkostninger til systemudvikling, hvilket inkluderer hardware så vel som software udvikling, vil blive dens<br />

største post i forløbet med implementering af systemet. Disse omkostninger kan forsvares, hvis man<br />

sammenligner dem med hvad virksomheden taber på nuværende tidpunkt pr. måned. Hvis vi antager at<br />

prisen for det færdige fungerende produkt ender på 1 million kroner og at de i øjeblikket har en spild<br />

procent på 4, vil det efter 4 måneder begynde at give overskud – eftersom systemet garanterer en<br />

maksimal spildprocent på 2. Hvis virksomheden er villig til at investere dette beløb vil resultatet hurtigt<br />

kunne måles.<br />

Logistisk effektivitet – hvordan opnås det? (Robert)<br />

Logistik stammer fra det græske ord logistikos og blev oprindeligt brugt i militære sammenhænge omkring<br />

håndteringen af forsyning i kamp. Lidt på samme måde bruger vi logistik i erhvervsmæssige<br />

sammenhænge, som færdigheden i håndtering og styring af blandt andet varer og informationer. Helt<br />

præcist inkluderer det strategisk håndtering af in<strong>dk</strong>øb, transport, lagring, varer samt de dertil hørende<br />

knyttede procedurer.<br />

Side 12 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Vi vil derfor lægge vægt på, hvad det betyder at være logistisk effektiv, ved at tage udgangspunkt i noten<br />

om logistik, der betegner effektiviteten som værende indeholdende to modsatrettede mål, nemlig<br />

leveringsservice samt logistikomkostninger. Hvert af disse mål indeholder nogle deleelementer, som vi vil<br />

gennemgå og diskutere hvordan kommer til udtryk hos <strong>Carletti</strong> A/S.<br />

Logistisk effektivitet<br />

Leveringsservice Logistikomkostninger<br />

Leveringstid<br />

Lagerservicegrad<br />

Leveringsoverholdelse<br />

Leveringsfleksibilitet<br />

Leveringsinformation<br />

Lageromkostninger<br />

Transportomkostninger<br />

Emballage- og<br />

håndteringsomkostninger<br />

Administrative omkostninger<br />

Mangelomkostninger<br />

Kort om de to mål kan der siges, at leveringsservice er en del af virksomhedens forhold til kunder i form af<br />

kundeservice (fx kort leveringstid som forøger salgsvolumen), mens logistikomkostninger indbefatter de<br />

omkostninger der skal til hos virksomheden, for at overholde den leveringsservice man stræber om at opnå<br />

til kunderne(fx lagerføre varer så man kan opnå kort leveringstid).<br />

Logistisk effektivitet er altså et samspil mellem disse to mål og kan for eksempel vurderes på at levere en<br />

god service og et godt produkt for at beholde og tiltrække potentielle kunder på en så omkostningseffektiv<br />

levering af in<strong>dk</strong>omne ordre som muligt.<br />

Vi vil nu komme ind på nogle af de forskellige delemner<br />

Leveringsservice<br />

Leveringstiden går ud på, hvor hurtigt en kunde får sin vare, fra ordren er givet til kunden har modtaget<br />

varen. Denne proces kaldes også den logistiske leveringstid og indeholder fem delelementer.<br />

Afhængigt af, hvilken ordre der er givet behøves alle delelementer ikke indgå i en ordre. Da <strong>Carletti</strong> A/S<br />

arbejder både i jobshop-produktionsform og flow-produktionsform, betyder det at de har mange varer på<br />

lager, men at de samtidigt kan omstille sig til specialordre.<br />

At <strong>Carletti</strong> A/S har mange varer på lager, kan vi se ud fra et billede taget på <strong>Carletti</strong> A/S 3 (reference), som<br />

viser at de har en lagerservicegrad i gennemsnit på cirka 98 %. Lagerservicegrad regnes som en procentvis<br />

størrelse og er altså et tal der viser hvor mange ordrer der leveres direkte fra et lager.<br />

Antager vi, at der gives en ordre udelukkende indeholdende en meget populær vare som fx skumbananer,<br />

kunne man forestille sig, at denne ordre leveres direkte fra et lager. I sådan en situation, vil leveringstiden<br />

være kort, da ordren kun bliver berørt af en administrativ afdeling der tager imod ordren og betaling, og<br />

derefter distributionsafdelingen der sender varen.<br />

Antager vi, at det er en ordre der kræver at <strong>Carletti</strong> A/S skal lave produktet fra bunden af, går ordren<br />

igennem alle fem punkter. Teknisk ordrebehandling der laver beregninger for hele ordren (det kan fx være<br />

udregning af estimeret leveringstid, pris osv.), en administrativ afdeling, in<strong>dk</strong>øbets leveringstid der står for<br />

in<strong>dk</strong>øb af råvarer til produktion, produktionen samt distributionen.<br />

3 Udleveret materiale ”<strong>Carletti</strong> billeder til ITO”<br />

Side 13 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

For at levere en god kundeservice, skal man også kunne overholde leveringstiden, for blandt andet skabe<br />

tillid til kunderne og skabe et godt ry.<br />

I dette projekt har vi en problemstilling, der består af nogle problemer på et mellemvarelager og ifølge en<br />

dansk undersøgelse fra 2002 4 , er det også i produktionen at de fleste forsinkelser opstår. Her kan der altså<br />

opstå leveringsoverholdelsesproblemer. <strong>Carletti</strong> har som sikkerhed til kunderne, hvis <strong>Carletti</strong> skulle gå hen<br />

og være forsinket i leveringen, en aftale med kunder på forhånd, om en bøde til <strong>Carletti</strong> A/S.<br />

Fleksibiliteten kan måles i mange forskellige aspekter. Produktfleksibilitet vedrører evnen til at levere nye<br />

produkter. Her er <strong>Carletti</strong> A/S meget fleksible, ifølge årsrapporten lægges der stor vægt på udvikling af nye<br />

produkter 5 og ganske vist er der på deres hjemmeside også information om tre typer nyt slags slik 6 .<br />

Funktionsfleksibilitet vedrører evnen til at levere forskellige varianter af samme varetype. <strong>Carletti</strong> A/S har<br />

en gang i en haste sag taget imod en ordre der skulle lave en type slik om til kosher-slik. Dette må siges at<br />

være utrolig fleksibelt, men samtidig blev de også betalt godt for dette 7 . <strong>Carletti</strong> A/S ligger desuden inde<br />

med over 100 opskrifter chokolade 8 , og man kunne godt forestille sig, at de kunne ændre<br />

chokoladeopskriften i en bestemt type vare, hvis ønsket.<br />

Leveringsinformationen er et svært punkt at komme ind på, da vi ikke rigtig ved hvordan <strong>Carletti</strong> A/S<br />

samarbejder helt præcist med sine kunder, udover de føromtalte sanktioner til dem selv.<br />

Logistikomkostninger<br />

Logistikomkostninger er som nævnt tidligere, en slags styring mod, hvordan man vil opnå den ønskede grad<br />

af leveringsservice.<br />

<strong>Carletti</strong> A/S har en relativ høj lagerservicegrad, hvilket betyder at de har bundet meget kapital i form af<br />

varer i store lagre, hvilket er en del af lageromkostninger. Ifølge årsrapporten 9 ligger de inde med<br />

varebeholdning for cirka 31 mio. kr., som også er en lageromkostning. Disse lagre kræver også de<br />

omkostninger de indbefatter(husleje, varme osv.).<br />

Da <strong>Carletti</strong> A/S både er masseproducerende, men samtidig også kan tage imod specialordre, må de også<br />

have maskiner til at kunne omstille sig efter ordre og behov. Dette må kræve avancerede maskiner, som<br />

også er en del af lageromkostninger.<br />

Valget om transportform har stor betydning for den logistiske effektivitet. Selve omkostningerne hos<br />

<strong>Carletti</strong> A/S er svære at vurdere, dog ses en gæld hos leverandører på cirka 16 mio. kr. 10 .<br />

<strong>Carletti</strong> A/S’s marked strækker sig over Danmark og Nordeuropa. Det er derfor måske sandsynligt, at der<br />

ikke er behov for dyre transportmidler som fx fly, men derimod noget billigere som fx tog.<br />

<strong>Carletti</strong> A/S har ikke de største omkostninger mht. emballage. Meget af <strong>Carletti</strong> A/S slik er pakket i standard<br />

plastikposter og med relative simple design. Pakningen af deres produkter sker fuldautomatisk på<br />

fabrikken, og nogle varer bliver endda ikke rørt af menneskehænder fra råvarerne bliver sendt fra fx Afrika,<br />

til kunden har slikket i hånden 11 . Disse maskiner skal selvfølgelig købes, men pengene bliver nok tjent hjem<br />

igen, i forhold til at have personer til at pakke.<br />

4 Note fra Fronter ”Logistikmål og logistikstrategier”<br />

5 Udleveret materiale ”Årsrapport del 1 – side 9”<br />

6 www.carletti.com/Default.aspx?ID=467<br />

7 Undervisning + www.hebrewear.com– her ses en pose slik af ”Kosher Balls” til 20 pund pr pose. (produktet findes<br />

ved at søge på ”Balls” i søgefeltet)<br />

8 Bilag 2 i udleveret ITO projekt-materiale<br />

9 Udleveret materiale ”Årsrapport del 1 – side 21”<br />

10 Udleveret materiale ”Årsrapport del 1 – side 22”<br />

11 Bilag 2 i udleveret ITO projekt-materiale<br />

Side 14 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Vurdering af logistiksystemet<br />

Grundet de mange kvalitative metoder logistisk effektivitet er baseret på, samt den begrænsede<br />

information tilgængelig, er det svært at give en helhedsvurdering af logistisk effektivitet hos <strong>Carletti</strong>. Vi har<br />

dog valgt at sammenligne nogle tal, fra nok den største danske slikproducent Toms med <strong>Carletti</strong> A/S, for<br />

derefter at give en vurdering.<br />

Vi kunne godt have tænkt os at vide mere om selve produktionen af fx dragéprodukterne. Ifølge<br />

procesbeskrivelsen af dragéprodukter 12 , tager denne produktion 1-2 uger. Vi har dog ingen information<br />

om hvor lang hver proces er, udover to gange tørring som tager ”nogle dage”. Antager vi, at ”nogle dage”<br />

er to dage, kunne det godt ligne at vi har nogle logistikproblemer i forhold til hele processens længde på<br />

hele to uger, da også markedet ikke strækker sig længere end Nordeuropa.<br />

Her kan der måske være problemer med leverandører der er for langsomme. Desuden opstår der<br />

flaskehalsproblemer på mellemlageret, da selve dragéringsprocessen ikke kan følge med selve<br />

produktionen, hvilket også er et logistisk problem.<br />

Ser vi bort fra dette og sammenligner med Toms 13 , kunne det måske alligevel tyde på, at <strong>Carletti</strong> A/S’s<br />

logistiksystem er ret velfungerende, dog har det sin pris.<br />

12 Udleveret ITO projekt-materiale side 12<br />

13 De følgende udregninger er lavet ud fra bilag 3<br />

Side 15 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Software Design<br />

Vision (Fælles)<br />

It-systemets formål er at understøtte en rationalisering af arbejdsgangene i forbindelse med<br />

mellemvarelageret hos <strong>Carletti</strong> samt at minimere spildet i forbindelse med dragering og tørring.<br />

Krav (Mads & Frederik)<br />

ID Beskrivelse Type Prioritet<br />

K1 Enkeltbrugersystem Funktionelt M<br />

K2 Afvikles på en almindelig computer Ikke Funktionelt M<br />

K3 Skal kunne finde næste portion der skal plukkes Funktionelt M<br />

K4 Det skal være hurtigt og nemt at finde placeringen på den<br />

ønskede portion.<br />

Ikke Funktionelt M<br />

K5 Systemet skal kunne vise de portion som er klar til plukning Funktionelt M<br />

K6 Systemet skal kunne registrere en portion & en opskrift og<br />

dens behandlingsforløb.<br />

K7 På en behandling skal det være muligt at registrere<br />

minimums, ideal og maksimum tørretid.<br />

K8 Det skal være muligt at kunne oprette en portion i systemet<br />

og registrere påbegyndt tørretid (timestamp).<br />

K9 Man skal med systemet kunne kalde en oversigt frem over<br />

portioner der står til tørring, der har overskredet maksimal<br />

tørretid.<br />

K10 Systemet skal kunne beregne den gennemsnitlige tid en<br />

portion befinder sig på lageret.<br />

K11 Skal kunne holde styr på hvor mange portioner der når at<br />

blive forældet.<br />

K12 Systemet skal kunne beregne den optimale placering af en<br />

portion ud fra FIFO-princippet<br />

Funktionelt M<br />

Funktionelt M<br />

Funktionelt M<br />

Funktionelt S<br />

Funktionelt S<br />

Funktionelt S<br />

Funktionelt S<br />

K13 Informationerne skal gemmes i en relationel database Funktionelt M<br />

Use-cases (Fælles)<br />

Følgende afsnit beskriver de use-cases vi er kommet frem til. Disse bliver uddybet igennem brug af vores<br />

use-case skabelon.<br />

Side 16 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Use-case oversigt<br />

ID Navn<br />

U1 Find vare<br />

U2 Pluk vare<br />

U3 Beregn gennemsnitlig tid på lager<br />

U4 Beregn antallet af forældede mellemvarer<br />

U5 Print oversigt<br />

U6 Opret opskrift<br />

U7 Opret portion<br />

U8 Registrer behandling<br />

U9 Tilknyt behandling<br />

Aktør beskrivelse<br />

Brugerne af dette system vil være almene lagerarbejdere og en lagerchef, hvor vi antager at deres IT<br />

kunnen er begrænset. Systemet vil blive brugt i den daglige drift.<br />

Use-case beskrivelser<br />

Use Case Name: U6 - Opret opskrift<br />

Scenario: Lagerchef opretter en opskrift<br />

Trigger Event: Der skal oprettes en opskrift<br />

Brief Description: Der oprettes en opskrift til brug i systemet<br />

Actors: Lagerchefen<br />

Related use cases: Opret eller tilføj behandling<br />

Postcondition: Opskrift oprettet<br />

Flow of events: Actor<br />

1. Lagerchefen taster navn ind i<br />

systemet<br />

Exceptional<br />

Flows:<br />

2. Lagerchefen opretter opskrift eller<br />

tilknytter behandling.<br />

System<br />

1. Systemet gemmer opskrift<br />

med navn.<br />

Side 17 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Use Case Name: U2 - Pluk vare<br />

Scenario: Lagermedarbejder skal plukke en vare<br />

Trigger Event: Varen er færdig med at tørre eller tørret for lang tid.<br />

Brief Description: Når en vare er færdig med at tørre eller tørretiden er for længe – skal den<br />

flyttes videre til behandling eller til spild.<br />

Actors: Lagermedarbejder<br />

Related use cases: Frigør lokation<br />

Stakeholders <strong>Carletti</strong> A/S<br />

Precondition: Der er en vare på lager<br />

Postcondition: Varen er flyttet til viderebehandling<br />

Flow of events: Aktør<br />

1. Lagermedarbejder finder varen<br />

i systemet<br />

2. Varen sendes til<br />

viderebehandling<br />

Exceptional<br />

Flows:<br />

Use Case Name: U7 - Opret portion<br />

System<br />

1. Placering vises<br />

2. Placering bliver frigjort<br />

Scenario: Produkt/portion kommer fra produktionen og skal behandles i form af tørring<br />

og/eller dragering.<br />

Trigger Event: Portion skal behandles<br />

Brief Description: Portionen får et varenummer, en start tid og bliver tilknyttet en behandling<br />

Actors: Lagerchefen<br />

Related use cases: Tilknyt behandling<br />

Stakeholders <strong>Carletti</strong> A/S<br />

Precondition: Der kommer et produkt/portion til<br />

mellemlager<br />

Postcondition: Portion oprettet med tilknyttet behandling<br />

Flow of events: Aktør<br />

Exceptional Flows:<br />

1. Lagerchefen opretter<br />

portion<br />

System<br />

1. Portion oprettes med<br />

navn, id og start tid<br />

1.1 Der tilknyttes<br />

behandling(tørring<br />

og/eller dragering)<br />

Side 18 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Sporbarhedsmatrix (Frederik)<br />

Tabellen viser sammenholdet imellem vores use cases og de liste krav fra kravspecifikationen,<br />

ID K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13<br />

U1 X X X X<br />

U2 X X X X X<br />

U3 X X X<br />

U4 X X X<br />

U5 X X X X<br />

U6 X X X X<br />

U7 X X X X<br />

U8 X X X<br />

U9 X X X<br />

System sekvens diagram (SSD) (Frederik)<br />

System sekvens diagrammer har vi brugt til at illustrerer hvordan en use-case interagerer imellem aktøren<br />

og systemet. Dette skaber en forståelse for hvordan systemet fungerer, ved at bruge en beskrivelsesform<br />

der ligger sig tæt til programmeringsformen.<br />

Opret opskrift – U6:<br />

Aktøren i denne use case er lagerchefen som interagerer med systemet.<br />

Lagerchefen opretter en opskrift ved at indtaste navnet på opskriften og tilknytte behandlinger. Den<br />

oprettede opskrift kan nu ses på listen.<br />

Side 19 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Opret portion – U7:<br />

Aktøren i denne use case er lagerchefen som interagerer med systemet.<br />

Lagerchefen opretter en portion ud fra den valgte opskrift, som indeholder behandlinger og<br />

behandlingsindeks. Her tildeles portionen et id og en starttid per automatik. Efter oprettelse bliver<br />

portionen flyttet til lageret og behandlingen går i gang.<br />

Pluk vare – U2:<br />

Aktøren i denne use case er lager medarbejderen som interagerer med systemet.<br />

Systemet viser at en portion er færdig med den igangværende behandling, og dermed at den er klar til<br />

plukning dvs. at portionen enten skal sendes videre til den nye behandling eller til pakning. Når portionen<br />

sendes til pakning bliver den placering frigjort.<br />

Side 20 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Design sekvens diagram (DSD) (Fælles)<br />

Design sekvens diagram er en udvidelse af SSD. Her udvides beskrivelsen så den ligger nærmere<br />

programmeringssproget, hvilket der er det centrale i DSD. Dette design giver et tilnærmelsesvis billede af,<br />

hvordan den specifikke use case en gang skal kodes.<br />

Opret opskrift:<br />

Der bliver oprettet en ny opskrift igennem service klassen, som kalder contructeren i Opskrift. Det nye<br />

objekt bliver returneret og tilføjet til listen i Dao. Ud fra en liste af behandlinger tilføjes disse til opskriften<br />

og der tildeles behandlingsindekser til behandlingerne. Processen i at tilføje behandlinger foregår i et loop<br />

da der kan være 1 til mange behandlinger.<br />

Side 21 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Opret portion:<br />

Når der oprettes en portion, går vi igennem den pågældende Opskrift og tilføjer den en portion. Da vi i<br />

oprettelsen af opskriften har tilknyttet dens behandlinger, kan vi igennem portionen oprette processer,<br />

hvor der tilknyttes netop opskriftens behandlinger, behandlingsindeks samt starttider og behandlingen kan<br />

gå i gang.<br />

Side 22 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Pluk vare:<br />

I denne use case forestiller vi os eksemplet hvor varen er blevet for gammel og derfor tilføjes til spild. Når<br />

portionen bliver markeret i listen over processer, har vi fat i en portions aktuelle proces hvor netop denne<br />

proces’ status bliver beregnet. Får vi som i eksemplet returneret statustypen ”old”, fjernes portionen fra<br />

lageret og portionen tilføjes til spildlisten.<br />

Side 23 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Analyse Klasse Diagram (Fælles)<br />

Dette diagram er som titlen indikerer meget generelt, derfor bliver klasserne forklaret i forhold til de<br />

koncepter og begrebsområder titlerne dækker over. Hvis større detalje ønskes, henledes<br />

opmærksomheden til Klassebeskrivelserne.<br />

Som en start kan man tage udgangspunkt i det man kan kalde systemets centrale klasse, nemlig Opskriftsklassen.<br />

Ud fra denne klasse bliver hele produktionsforløbet oprettet igennem. Det vil sige at det er denne<br />

klasse der kommer til at stå for oprettelsen af Portioner samt holde styr på den rækkefølge en Portion skal<br />

gennemgå for at kunne blive erklæret færdig. Dernæst kan man se på de forskellige behandlinger som en<br />

Portion skal igennem.<br />

De konkrete klasser er alle sammen en udvidelse af en fælles superklasse så det er muligt at have en<br />

generel liste i de forskellige klasser der finder dette nødvendigt. Disse Behandlings sub-klasser kan oprettes<br />

udenom fx Opskrift-klassen. Dette er fordi det skal være muligt for mange forskellige opskrifter at benytte<br />

sig af en fælles behandling fx Tørring, som har de samme minimum, ideel og maksimum værdier for<br />

tørretider. Der ville ikke være nogen grund til at tvinge oprettelsen af behandlinger til at skulle gå gennem<br />

en anden klasse. Dette bevirker også en hvis grad af re-use.<br />

Ligeledes har vi Placerings-klassen som også kan oprettes uden at skulle igennem en anden klasse. I dette<br />

design går vi ud fra at lageret består af et stort firkantet areal som kan omdannes til et stort gitter så det er<br />

muligt at benytte x og y koordinater til at lokalisere en given Portion som står til tørre.<br />

I designet er der også inkluderet to associationsklasser der er der af to forskellige grunde. Til at starte med<br />

kan man kigge på Proces-klassen. Lige præcis denne klasse giver designet et sted hvor man kan trække en<br />

hvis mængde statistik ud fra. For at tage et eksempel kan det være at man gerne ville gennemløbe en<br />

Portions processer for at finde ud af hvor lang tid den har stået til tørring. Det er her Proces-klassen<br />

kommer ind. Den indeholder både start og stop tider for alle de behandlinger en Portion har været<br />

igennem, som alle vil blive gemt i en liste i Portions-klassen. Den anden associationsklasse i designet er<br />

BehandlingsIndeks-klassen. Denne klasse er der for at holde styr på den rækkefølge en Opskrifts forskellige<br />

Side 24 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

behandlinger skal komme i. Disse objekter af denne type bliver opbevaret i Opskrift-klassen, hvor en<br />

portion altid har styr på hvilket indeks den er kommet til, hvor opskrift-objektet så kan kalkulere den næste<br />

behandling ud fra det nuværende indeks.<br />

Når man snakker om multipliciteter kan man starte med at kigge på forholdet mellem Placering og Portion.<br />

Grunden til at det er nul til en, til nul til en, er fordi en Portion kan enten være under en Dragerings- eller en<br />

Tørringsbehandling. Men eftersom den kun skal tildeles en placering hvis dens behandling er en<br />

Tørringsbehandling er det ikke et krav at den skal have en placering som standard. Når den så skifter<br />

behandlingstype fra fx Tørring til Dragering ville dette placeringsobjekt så blive frigjort og mulig for andre<br />

portioner der skal tørre.<br />

Som nævnt tidligere vil Opskrift-klassen i implementeringsfasen få en liste over Processer. Grunden til det<br />

er, at man skal kunne følge og evt. generhverve en portions proces-forløb samt udregne forskellige ting ud<br />

fra dette.<br />

Tilstandsdiagrammer (Mads)<br />

Eftersom lagersystemet er bygget på at en vare kan have forskellige tørretider, som forklaret i det<br />

udleverede oplæg, kan dette illustreres igennem et tilstandsdiagram. Grunden til at dette er muligt er fordi<br />

man kan antage at de forskellige tørretider samt start og slut knuderne i systemet er stadier en portion kan<br />

antage mens den er på lageret til tørring.<br />

I følgende afsnit vil x være et udtryk for de dage en given portion har stået og tørret. Både minimum, ideal<br />

og maksimum er tal som lagt til 0 beskriver den deadline hvor en portion skifter status.<br />

Til at starte med, når portionen først lige kommer til lageret, er den i en start-tilstand hvor den endnu ikke<br />

kan plukkes til videre behandling. Dette er ikke muligt da man ellers ville kunne plukke portioner der stadig<br />

er 'våde'. Så derfor vil det ikke være muligt at plukke portionen i intervallet 0 < x < minimum. Når en portion<br />

så har stået i minimum tørringstid vil det være muligt for den at blive plukket til behandling. Det skal dog<br />

siges at varen vil have minimum som status indtil den når ideal tørretiden, altså: (minimum


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

muligt at kunne plukke varen i dette stadie og lige som tidligere vil den have denne status i følgende<br />

interval: (ideal maksimum, ender portionen automatisk i en slut-tilstand som er et udtryk for at den er overgået til<br />

spild. Disse intervaller er også et godt udgangspunkt for videre testing.<br />

Design Klasse Diagram (Fælles)<br />

Dette diagram findes også som bilag.<br />

Dette diagram er den centrale del af Design-Modellen i rapporten. Det er lavet på baggrund af analyse<br />

diagrammet som tidligere er beskrevet. Forskellen på analyse og design diagrammet er basalt set<br />

detaljeniveauet som kommer til udtryk i bl.a. indførelsen af typer på attributter samt metoderne der er i<br />

design klasse diagrammet. Dette er dog set med et meget generelt syn. Følgende er derfor en uddybelse af<br />

den udbygning der er på baggrund af analyse-diagrammet som ender med et produkt i form af design<br />

klasse diagrammet.<br />

Til at starte med kan man gå ind og se på hvad de forskellige værdier på de forskellige attributter skal være.<br />

For at tage et eksempel kan man se på Placerings-klassen. Her er der mange der vil argumentere for at dens<br />

x og y attributter burde være strings, så man måske kunne sætte et 'b' foran begge værdier for at indikere<br />

at placerings-objektet er den placering i buffer-området af lageret. Dette blev dog fravalgt da vi gik ud fra at<br />

lageret var et stort firkantet område i en hal hvor man kunne opdele dette i små firkanter og navngive dem<br />

med koordinater i form af tal, x og y. Disse attributter fik derfor værdien integers (hel tal).<br />

Der er ligeledes andre eksempler på disse valg, men for hurtigt at dække de trivielle valg kan man se på de<br />

forskellige tider (startTid og slutTid) som logisk nok blev sat til at være det allerede eksisterende Date<br />

objekt, da de skal være fælles for begge.<br />

Side 26 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Dernæst er der sådan noget som vareNr på en portion, samt navnet på en opskrift. Begge af dem kan man<br />

argumenter for og imod de valgte typer men at sætte vareNr til at være et integer og navnet på opskriften<br />

til at være en string virkede som det mest logiske for udviklerne.<br />

I Proces-klassens status attribut kunne man have gjort mange forskellige ting, for at indikere hvilken status<br />

et givent proces-objekt har på et givent tidspunkt. Som et primitivt udgangspunkt kunne man give den en<br />

string værdi, hvor man så skulle sørge for at alle statusser blev skrevet på præcis samme måde, for at sikre<br />

at de agerede på samme måde ved en given status. Problemet med denne tilgang er den menneskelige del.<br />

Her vil der være for stor risiko for at der på et eller andet tidspunkt vil være en stavefejl, som vil kunne få<br />

systemet til at indeholde proces-objekter med ugyldige statusser.<br />

En anden tilgang, som i dette tilfælde er blevet benyttet, er at have en enum-klasse som indeholder statiske<br />

elementer som så skal benyttes som typen for status attributten i Proces-klassen. På den måde er det sikret<br />

at der kun bliver benyttet de konstanter som er defineret i enum-klassen<br />

Vi vil nu kigge på de to ovenstående associationsklassers implementering. Som man kan se ud fra det<br />

øverste billede, som er et lille del af det tidligere beskrevet analyse diagram, kan man se at der er en<br />

associationsklasse mellem opskrift og behandling. Denne klasse sørger for at en behandling ikke har den<br />

samme placering i alle opskrifter. Måden dette gøres på er at indføre den som en fast klasse mellem de to<br />

klasser: Opskrift og Behandling. Denne BehandlingsIndeks klasse sikrer at behandlinger kan benyttes i<br />

forskellige opskrifter med forskellige placeringer i rækkefølgen.<br />

Men der bliver overset en lille ting, nemlig overgangen fra analyse diagrammets multiplicitet til design<br />

klassens, hvor der lige nu er inkluderet en BehandlingsIndeks klasse. Til at starte med kan man se at<br />

multipliciteten 0..* til 1..* forstået på den måde at intentionen var at en opskrift skal have mindst en<br />

behandling i rækkefølgen men en behandling kunne godt indgå i flere opskrifter. For at dette kunne lade sig<br />

gøre at holde styr på, blev BehandlingsIndeks indført.<br />

For at overføre dette til design klasse diagrammet kan man i dette tilfælde argumentere for, at et<br />

behandlingsindeks godt kan indgå i flere opskrifter. Derfor bliver diagrammet implementeret som<br />

.<br />

Side 27 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

ovenstående illustrationer. At et behandlingsindeks skal have en opskrift, som den ikke kender til, og at et<br />

behandlingsindeks kan indgå i flere opskrifter (1 → 1..*).<br />

Dernæst kan man se at behandlingsindekset skal have en behandling og en behandling sagtens kan indgå i<br />

flere behandlingsindekser, men som før skal behandlingerne ikke vide hvilke behandlingsindekser de indgår<br />

i (0..* → 1).<br />

Denne overgang er også gældende for den anden associationsklasse der indgår i analyse-diagrammet. Dog<br />

med den forskel at udviklerne fastslog at forholdet mellem Portion og Proces blev nødsaget til at være en<br />

komposition da det ikke ville give mening at en proces kunne stå alene uden nogen tilhørende Portion.<br />

Som man kan se af det over-all design klasse diagram er der en lille klasse som virker som om den er meget<br />

isoleret fra resten af modellen - nemlig SystemDato-klassen. Grunden til denne klasse er med i modellen, er<br />

for at kunne have et centralt sted for alle modelklasserne at hente deres Date-objekter til startTid og<br />

slutTid. Mange vil sige at det ville være nok bare at kalde new Date på disse tider når de skulle sættes, men<br />

eftersom udviklerne gerne ville kunne teste systemet ved at få tiden til at gå hurtigere, blev denne klasse<br />

implementeret så man fra andre klasser kunne sætte en ny tid for systemet. Derfor blev der også<br />

implementeret en TimeThread-klasse i Service pakken så den kunne håndtere hvornår og hvor ofte en ny<br />

dato skulle sættes. I selve implementeringen er denne klasse implementeret med to modes – et test og<br />

real-time mode. I det sidste mode vil der blive tjekket om computerens dato er en ny dato til forskel for den<br />

der allerede er sat i SystemDato-klassen efter et givent interval indtil systemet lukkes.<br />

Hvis man ser bort fra interfacet der også er med i ovenstående illustration, kan man se sammenhængen<br />

mellem de tre klasser: Service, TimeThread og SystemDato. Tanken bag denne kobling er at vi gerne vil tilgå<br />

en 'nuværende' dato i modellen uden at kalde op i DAO-en og Service klasserne. Derfor var det nødvendigt<br />

at oprette SystemDato-en. For hvert interval der går i TimeThread-tråd klassen skal dens run-metode sætte<br />

en ny dato i SystemDato klassen, samtidig med at den skal kalde en metode i Service klassen der tjekker<br />

Side 28 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

hele systemets objekters status. Dette gør at vi kan forkorte en flere dages lang proces ned til fx et par<br />

sekunder. Alt dette overholder stadig at der ikke bliver kaldt ned i lagene i den brugte arkitektur.<br />

Arkitektur (Mads)<br />

Når man snakker om arkitektur i et software-udviklingsprojekt har undervisningen givet os to modeller at<br />

vælge imellem. Den ene er den traditionelle fire-lags arkitektur hvor alt går strikt gennem alle tre lag for at<br />

tilgå modellen i bunden. Altså GUI → Service → DAO → Model, med ingen undtagelser. Der er mange<br />

forskellige holdninger til denne model. En af dem benytter argumentet med, at den ligger bund for mange<br />

unødvendige metodekald, eftersom alt skal igennem Service for bl.a. at kunne tilgå en given liste i DAO-en.<br />

Men på den anden side kan man også sige at det giver en større kontrol omkring hvad der virkelig foregår i<br />

de lavere-liggende lag i arkitekturen.<br />

Til dette projekt er der valgt en lidt anden tilgang til arkitekturen, ved at benytte en arkitektur som består af<br />

tre lag, men stadig med de samme fire elementer. Grunden til at denne er valgt, er for at effektivisere<br />

systemet, ved ikke at skulle følge en nær så stor 'method-call-path' ved evt. debugging.<br />

Desuden bliver det muligt at tilgå DAO-en direkte fra GUI-en. Det skal dog siges at der kun benyttes denne<br />

tilgang til at læse lister fra DAO-en, ikke til at ændre objekter i systemet. Denne arkitektur gør også at<br />

Service-klassen ikke bliver nær så lang og med et mindre indhold af lettere trivielle metoder.<br />

Som man kan se på modellen afhænger Service stadig af DAO-en. Grunden til dette er at når man endelig<br />

skal opdatere et objekt – i dette tilfælde et objekt af typen Opskrift – går dette stadig igennem Service for<br />

stadig at have en kontrol med hvad der bliver opdateret med hvilke værdier.<br />

Testrapport (Mads)<br />

Dette afsnit indeholder et afsnit omkring modul-test af en forretningsorrienterede klasse, i dette tilfælde er<br />

der valgt at det skal være Proces-klassen i en kobling med Toerring-klassen. Derudover er der et afsnit<br />

omkring en use-case test for en central use-case, her er der valgt use-casen: Opret Opskrift.<br />

Modultest af Proces-klasse<br />

/**<br />

Side 29 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

* Beregner den status en proces har ved metode-kaldet. Dette er forskelligt<br />

* alt afhængig af hvilken subklasse en behandling er. <br />

* Krav: currentDate skal være 'større' end startTid<br />

*<br />

* @param currentDate<br />

* den dato som systemet har på det givne tidspunkt<br />

* @return den aktuelle status for den nuværende proces som vil være<br />

* portionens aktuelle proces<br />

*/<br />

public StatusType beregnStatus(Date currentDate)<br />

I klassen Proces er der en metode der hedder beregnStatus som skal beregne den status den pågældende<br />

proces har ud fra en given dato som bliver givet med til metode-kaldet gennem en parameter. Det der<br />

kommer til at ligge bund for dette test-case er at Toerrings-klassen også benyttes da det er denne klasse der<br />

definere hvornår en proces har forskellige statuser.<br />

Så defor startes der med at definere et 'objekt' af klassen Toerring med værdier for minimum, ideal og<br />

maksimum tørringstider. Men for at dette kan lade gøres skal der kigges på de krav som er opstillet for<br />

oprettelse af denne klasse. Eftersom programmet ikke garantere brugbare resultater hvis disse krav ikke er<br />

opfyldt fra brugerens side. Derfor kigges der i dokumentationen for konstruktoren for denne klasse.<br />

/**<br />

* Oprettelse af en Tørring <br />

* Krav: 0 < minimum < ideal < maksimum<br />

*<br />

* @param minimum<br />

* @param ideal<br />

* @param maksimum<br />

*/<br />

public Toerring(int minimum, int ideal, int maksimum)<br />

Her kan man se hvordan konstruktoren for oprettelsen af dette objekt ser ud. Og der kan derfor læses at for<br />

at programmøren garentere et valid objekt af denne type skal følgende krav være opfyldt:<br />

0 < minimum < ideal < maksimum<br />

Dette krav bunder i opfattelsen omkring problemstillingen for systemet. Her forståes der at en tørring ikke<br />

kan vare nul dage og der skal mindst være en dags forskel mellem de tre stadier for at et valid Toerrings<br />

objekt bliver returneret. Derfor vil det objekt der bliver benyttet bruge følgende værdier for tørringer:<br />

Side 30 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Parameter Værdi<br />

Minimum 1<br />

Ideal 3<br />

Maksimum 5<br />

Disse værdier overholder det opstillede krav fra programmørens side og vil derfor give et valid objekt til<br />

videre brug i test-casene.<br />

Når det så kommer til oprettelse af proces-objektet antages der at der er et tilhørende portions-objekt som<br />

selvfølgelig også har et opskrifts-objekt. Dernæst antages der at startTid attributten på proces-objektet er<br />

sat til <strong>2012</strong>-05-05 som udgangspunkt.<br />

Når der så skal testes antages der at currentDate (parameteren i metodekaldet) er en nyere Date-objekt end<br />

startTid – så at sige. I tabellen over tests der er foretaget vil det være differencen mellem startTid og<br />

currentTid-parameteren som er med.<br />

Det der så testes for er om de forskellige StatusTyper der bliver returneret er passenden i forhold til den<br />

difference der er mellem startTid og currentTime. Følgende tabel giver et overblik over hvornår procesobjekten<br />

skal have specifikke status i henhold til differencen. De variabler som bliver brugt i beskrivelsen af<br />

intervalet for hvornår statusen er valid er en reference til de tørretidsspecifikationer som er opgivet ved<br />

oprettelsen af Toerrings-objektet. Ligeledes er x et udtryk for den førnævnte difference mellem startTid og<br />

currentDate.<br />

StatusType Inteval for status Ækvivalensklasse<br />

StatusType.NOT_DONE 0


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Altså er grænseværdierne for disse test et udtryk for en specifik difference mellem startTid og currentDate.<br />

startTid - currentDate Forventet resultat Faktiske resultat<br />

0 StatusType.NOT_DONE StatusType.NOT_DONE<br />

minimum - 1 StatusType.NOT_DONE StatusType.NOT_DONE<br />

minimum StatusType.MINIMUM StatusType.MINIMUM<br />

minimum + 1 StatusType.MINIMUM StatusType.MINIMUM<br />

ideal - 1 StatusType.MINIMUM StatusType.MINIMUM<br />

ideal StatusType.IDEAL StatusType.IDEAL<br />

ideal + 1 StatusType.IDEAL StatusType.IDEAL<br />

maksimum - 1 StatusType.IDEAL StatusType.IDEAL<br />

maksimum StatusType.MAKSIMUM StatusType.MAKSIMUM<br />

maksimum + 1 StatusType.OLD StatusType.OLD<br />

maksimum + n StatusType.OLD StatusType.OLD<br />

Som man kan se ud fra ovenstående tabel overholder metoden de forventninger der er stillet til den. Der vil<br />

dog ikke blive testet for ulovlige værdier som fx en negativ difference mellem startTid og currentDate da<br />

dette ikke er en mulighed i systemet.<br />

Nu hvor hele processen af testing er gennemgået for den største del af Proces-klassen, kan den følgende del<br />

let gennemgåes ud fra nogle få linjers forklaring. Det vil sige at følgende tabeller er en test gennemgang hvis<br />

en proces' behandling er af typen Dragering. Det brugte Dragerings-objekt har en varigheds-attribut med<br />

værdien tre. Denne attribut er den eneste interessante i Dragerings-klassen.<br />

StatusType Inteval for status Ækvivalensklasse<br />

StatusType.NOT_DONE 0 = varighed [varighed;varighed]<br />

I ovenstående tabel bliver der gået ud fra at der er plads på lagerert når en proces er færdig, har fået<br />

statustypen StatusType.DONE, hvilket forklare den sidste ækvivalensklasse. Hvis dette ikke var en antagelse<br />

ville det være nødvendigt at udvide ækvivalensklassen til at have følgende opbygning: [varighed;∞[ og<br />

endda gennemtænke om en dragering skal have muligheden i at blive for gammel selvom den endnu ikke er<br />

kommet ind på lageret.<br />

Med ækvivalensklasserne deffineret kan grænseværdierne samt de forventede resultater opsættes<br />

efterfulgt af testenes egentlige resultater.<br />

Side 32 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

startTid - currentDate Forventet resultat Faktiske resultat<br />

0 StatusType.NOT_DONE StatusType.NOT_DONE<br />

varighed - 1 StatusType.NOT_DONE StatusType.NOT_DONE<br />

varighed StatusType.DONE StatusType.DONE<br />

varighed + 1 StatusType.DONE StatusType.DONE<br />

Ovenstående antagelse med at værdierne for x er en difference som er udtrykt fra den forud-deffineret<br />

værdi for Dragerings-objektets varigheds-attribut.<br />

Use-case test af Opret Opskrift<br />

I nedenstående mock-up af den tidligere beskrevet use-case er der kort forklaret lidt omkring use-casen<br />

'Opret Opskrift'. Denne case er opdelt i fire kategorier som der bliver arbejdet udfra ved udarbejdelsen af<br />

denne use-case test.<br />

Use-case #U6<br />

Opret en opskrift<br />

Success guarantees<br />

Der bliver opretttet en opskrift i systemet<br />

Main success scenario<br />

1. Brugeren indtaster et navn på en opskrift<br />

2. Brugeren tilføjer x antal behandlinger til opskriften.<br />

3. Brugeren vælger at konfirmere oprettelsen af opskriften.<br />

Extensions<br />

1a. Brugeren glemmer at skrive navnet på opskriften<br />

2a. Brugeren kan ikke finde en given behandling og ønsker at oprette en ny<br />

2aa. Der eksistere ikke den ønsket behandlingstype (hverken tørring eller dragering kan bruges)<br />

2b. Brugeren tilføjer ingen behandlinger<br />

Ud fra ovenstående use-case mock-up kan man så danne et use-case test skema som danner bund for alle<br />

de kombination af udfald den givne use-case kan resultere i. Nedenstående tabel er af sådan en type tabel:<br />

Side 33 af 75


Test<br />

case<br />

ID<br />

23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Test Source Initial System<br />

State<br />

U6-1 Use case #6 Programstart<br />

fra<br />

hovedvindue<br />

U6-2 Use case #6<br />

extens. 1a<br />

U6-2 Use case #6<br />

extens. 2a<br />

U6-3 Use case #6<br />

extens. 2aa<br />

U6-4 Use case #6<br />

extens. 2b<br />

Programstart<br />

fra<br />

hovedvindue<br />

Programstart<br />

fra<br />

hovedvindue<br />

Programstart<br />

fra<br />

hovedvindue<br />

Programstart<br />

fra<br />

hovedvindue<br />

Input Expected Results<br />

(a) Opskrift<br />

navn ”Lakrids”<br />

(b) Mindst en<br />

behandling tilføjes<br />

(c) Trykker på OK<br />

(a) Mindst en<br />

behandling tilføjet<br />

(b) Trykker på OK<br />

(a) Opskrift<br />

navn ”Lakrids”<br />

(b) Trykker på 'Opret<br />

Behandling'<br />

(c) Mindst en<br />

behandling tilføjes<br />

(d) Trykker på OK<br />

(a) Opskrift<br />

navn ”Lakrids”<br />

(b) Trykker på 'Opret<br />

Behandling'<br />

(c) Trykker på luk i<br />

'Opret<br />

Behandling's-vinduet<br />

(d) Trykker på luk i<br />

'Opret Opskrift'svinduet<br />

(a) Opskrift<br />

navn ”Lakrids”<br />

(b) Trykker på OK<br />

(a) En ny opskrift vil blive oprettet<br />

(b) Brugeren kommer tilbage til hovedvinduet<br />

(c) Listen over opskrifter vil vise den nye opskrift<br />

(a) Brugeren får at vide de skal angive et navn for<br />

at kunne oprette en opskrift<br />

(a) Brugeren opretter en ny behandling med de<br />

nødvendige og gyldige værdier<br />

(b) En ny opskrift vil blive oprettet<br />

(c) Brugeren kommer tilbage til hovedvinduet<br />

(d) Listen over opskrifter vil vise den nye opskrift<br />

(a) Brugeren kommer ud til hovedvinduet<br />

(b) Ingen ny opskrift er oprettet eller vises i listen<br />

over opskrifter.<br />

(a) Brugeren vil få at vide at der skal være mindst<br />

en behandling tilføjet<br />

(b) Brugeren bliver på 'Opret Opskrift's-vinduet<br />

Status (Mads)<br />

Som systemet ser ud nu på et designmæssigt niveau er der stadig nogle fejl, dog skal det siges at det ikke er<br />

noget udviklerne på nuværende tidspunkt kan identificere. Der er dog stadig mulighed for videre udvikling<br />

af systemet. Der vil fx kunne blive implementeret et kort over det pågældende lager hvor man selv ville<br />

kunne assigne forskellige fysiske områder til at have buffer-status eller lignende. Ud over det kan der<br />

implementeret en fane i GUI-en til at håndtere den over-all statistik så der fx kan blive genereret grafer ud<br />

fra gennemsnitlige tørretider over et foruddeffineret tidsinterval.<br />

Side 34 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Hvis man skal kigge på manglerne er der rigtig mange ting man kan argumentere for og imod. Men for at<br />

tage nogle eksempler kan man tage udgangspunkt i håndteringen af opskrifter. Lige nu kan systemet ikke<br />

håndtere hvis en lagerchef gerne vil slette en opskrift. Grunden til dette ikke er implementeret er fordi der<br />

på nuværende tidspunkt ikke er en log-tabel i databasen som man kan gemme sådanne ændringer i. Hvis<br />

man lige nu kunne slette en opskrift ville man ikke kunne fortryde det ved at hente dens data i log-tabellen.<br />

Dernæst kan man se på en lignende sag, nemlig håndteringen af behandlinger i systemet. Disse objekter<br />

kan heller ikke opdateres til at have andre attributværdier. Dette er valgt eftersom hvis det var muligt ville<br />

det påvirke alle de opskrift og portions-objekter som benytte det pågældende behandlings-objekt. Derfor er<br />

disse gjort 'statiske'.<br />

For at runde af på denne status del af rapporten kan man godt konkludere at hvis det som blev beskrevet i<br />

oplægget er det som kunden gerne ville have ville dette system godt kunne tages i brug.<br />

Resume af forløbet (Robert)<br />

Som udgangspunkt har vi aftalt at mødes kl. 08:30 hver dag, for derefter at arbejde til omkring middag eller<br />

til målene for dagen er nået.<br />

Vi startede med ITO-delen og blev hurtigt enige om at vi ville arbejde med klar arbejdsfordeling, for<br />

derefter at samle vores materiale og gennemgå det og eventuelt tilpasse det.<br />

Efter et kort møde med vores vejleder, holdte vi i gruppen et møde om hvordan opgaven skulle løses. Det<br />

største problem vi havde med ITO er fagets omfang og derfor at finde vores relevante fokuspunkter.<br />

Efter at have løst problemet angående relevant materiale og endelig overvandt frustrationen, nåede vi<br />

hvad der lignede et færdigt resultat og slog derefter over til næste opgave, nemlig software design delen.<br />

Vi fastholdte under hele processen de samme arbejdstider, med små dellegeringer til hjemmearbejde og<br />

begyndte nu på software design. Dette krævede en del gruppearbejde og de første par dage foregik meget<br />

på samme skærm, for at være fælles om den endelige grundstruktur for software konstruktionen.<br />

Arbejdsmetoden ændredes dog efter at have lavet analyse og design diagrammer. Ligesom i ITO var det<br />

nemlig fordelagtigt at dele arbejdet op i tre dele, da mange af opgaverne i software design er relative<br />

overkommelige for ene mand.<br />

Da vi følte os godt klædt på til at begynde med kodning, gik vi i gang med at kode modellen. Dette gjorde vi<br />

i nogenlunde fællesskab, for hele tiden at kunne diskutere den optimale løsning af metoder og være sikker<br />

på at vi overholdte blandt andet vores multipliciteter.<br />

Vi kom hurtigt i gang med GUI og efter at have tegnet og blevet enig om vores design, blev vi enige om at<br />

lave GUI hver mand for sig, da det viste sig at vi havde hver sin måde at programmere det på. Det største<br />

problem her var, at blive enige om brugen af Layouts, hvor vi endte med at blive enige om et par specielle<br />

Layouts men også absolutte designs hvor mange knapper og lister drillede. Da vi var færdige med denne<br />

version af programmet, var vi klar til JPA-versionen.<br />

Vi implementerede JPA uden de store problemer og testede derefter at objekterne blev gemt i mySQL. Da<br />

dette var en succes, følte vi os nu godt klædt på til at kalde os stort set færdige med programmeringsdelen.<br />

Enden på projektet synes endelig håndgribelig og vi satte os sammen for at lave en liste med nuværende<br />

mangler. Disse opgaver blev fordelt og lavet over en weekend, for derefter at blive samlet. Sidste proces gik<br />

ud på at samle projektet og rette for fejl og mangler.<br />

Side 35 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Refleksioner (Robert)<br />

Unified process(UP) er et redskab til at skitsere systemudviklingens cyklus. Det er ud fra denne cyklus, at vi<br />

har arbejdet med <strong>Carletti</strong> projektet. For at forstå denne cyklus, skal man præsenteres for de fire faser som<br />

beskriver cyklussen. I dette projekt lægger vi dog ikke vægt på den fjerde og sidste fase transition, som<br />

omhandler udførelsen (også kaldet deployment) af projektet i form af implementering hos kunden.<br />

Et redskab man bruger mens man arbejder ud fra UP er det iterative princip. Ved at arbejde iterativt,<br />

arbejder man sig igennem nogle faser, hvormed projektet vokser inkrementelt og de isolerede faser samles<br />

til en enhed.<br />

Man deler altså projektet op i små miniprojekter, hvor man opstiller nogle målbare artefakter eller krav.<br />

Dette hjælper med at skabe et overblik over projektet og dets forløb.<br />

Den første fase hedder inception og inkluderer faget ITO og SD. Denne fase handler blandt andet om<br />

business modelling eller med andre ord forretningsudvikling. For at kunne gennemføre et projekt, skal man<br />

skabe sig noget overordnet baggrundsviden og forståelse for hvilket forretningsområde man befinder sig i. I<br />

denne fase udvikles desuden nogle simple use cases, der skaber forståelse for simple overordnede<br />

funktioner i systemet.<br />

Dette er hvad vi har gjort i ITO og SD. Denne viden har kunnet bringe os videre til næste fase, elaboration.<br />

I denne fase arbejder vi videre med software design. Her skabes de centrale dele af systemet samt en<br />

dybere forståelse af systemets krav. Her udarbejdes detaljerede forklaringer af use cases,<br />

klassediagrammer og andre software design redskaber. Efter denne fase skal man have nået så langt, at<br />

man kan udarbejde en grovplan for resten af projektet. Man er nået så langt, at enden er håndgribelig.<br />

Disse redskaber udvikles i en iterativ proces, hvor man med udgangspunkt i den midlertidige løsning,<br />

gentager processen og skaber en bedre løsning. Et nyt krav kan for eksempel være grunden til ændring i en<br />

use case og på den måde forbedrer vi produktet.<br />

De centrale dele af systemet skabes og en simpel version af programmet kodes. Her blev der lavet en lille<br />

version af programmet, som var i stand til at køre en simpel simulering af en opskrift som skulle igennem<br />

en behandling.<br />

I den sidste fase construction, forsættes implementeringen af programmet. Her er der arbejdet på at samle<br />

alt vores materiale samt færdiggørelsen af programmet, så det er klar til præsentation.<br />

Udviklingsværktøjer:<br />

I dette projekt har vi udover det udleverede materiale også hentet information fra internettet. Kilderne fra<br />

internettet, der er brugt i projektet, er selvfølgelig refereret til.<br />

Derudover har vi til udviklingen af vores system design brugt Visual Paradigm og til vores java-kodning<br />

programmet Eclipse. Til JPA delen brugte vi mySQL til at teste, at vores program virkede efter hensigt.<br />

Side 36 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Ordbog<br />

Udtryk Definition<br />

Analyse Diagram Et generelt diagram der viser koblingerne mellem begreber i systemet<br />

Associationsklasse En klasse der bliver indsat i en forbindelse mellem to klasser for at sørge for at<br />

alle klasser af en given type ikke.<br />

BehandlingsIndeks En associationsklasse der håndtere den rækkefølge forskellige behandlinger har i<br />

en opskrift.<br />

Behandling En abstrakt klasse der gør det muligt at have en liste med både tørring og<br />

drageringsbehandlinger i<br />

Collection-framework Dette er et framework som Java er udstyrret til håndtere forskellige former af<br />

samlinger af objekter – Set, Tree, List<br />

Dragering En klasse der modellere en drageringsbehandling hvor den er deffineret med en<br />

varighed en drageringsbehandling tager<br />

DrageringsType En enumklasse der indeholder to konstanter som beskriver en type af dragering,<br />

enten en farve- eller en sukker-dragering.<br />

DSD Design Sekvens Diagrammer – Disse diagrammer bliver brugt i design fasen<br />

hvilket inkludere kaldene klasserne imellem<br />

Enkeltbrugersystem Et system der kun skal bruges af en bruger af gangen – dette gør at der ikke skal<br />

tages nær så høj forbehold for samtidighedsproblemer<br />

Grænseværdier Bruges i test-verdenen sammen med ækvivalensklasser hvor grænseværdier er et<br />

udtryk for de tal i ydrekanten af intevallet.<br />

Lagermedarbejder Aktør som hovedsageligt står for at plukke portionerne og sende dem videre til<br />

behandling<br />

Lagerchef Aktør som hovedsageligt står for at oprette opskrifter samt portioner.<br />

Modultest Dette er en testform hvor man kigger på fx en metode som tager forskellige<br />

parametre for derefter at resultere i noget bestemt. Ved at bruge denne<br />

testmetode kan man kontrollere udfra intervaller om disse resultater er valide.<br />

Opskrift En klasse der indeholder en liste over de BehandlingsIndekser (behandlinger) en<br />

portion skal igennem for at få en status som færdigbehandlet<br />

Placering En klasse der modellere en placering på lageret ud fra et koordinatsystem<br />

Plukke vare Når en portion har opnået en hvis status har den mulighed for at blive plukket.<br />

Dette betyder at portionen<br />

Portion En klasse der modellere en portion af en opskrift, altså en form for aktivt objekt i<br />

proces-forløbet.<br />

Proces En klasse der modellere en aktuel proces som en given portion lige nu er ved.<br />

slutTid Beskriver det tidspunkt når enten en portion eller en proces bliver afsluttet.<br />

SSD System Sekvens Diagrammer – Disse diagrammer bliver brugt for at give et<br />

helhedsindtryk af hvordan interaktionen mellem system og bruger er.<br />

startTid Beskriver det tidspunkt når enten en portion eller en proces bliver påbegyndt.<br />

StatusType En enumklasse der indeholder alle de konstanter som beskriver en pågælden<br />

Side 37 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

status for en proces.<br />

Tilstandsdiagram Et diagramtype der viser hvornår man kan gå fra en tilstand til en anden og hvad<br />

der skal være opfyldt for at det er validt. Sagt på en anden måde så er det et<br />

diagram der viser systemets forskellige tilstande.<br />

Toerring En klasse der modellere en tørringsbehandling som er deffineret med en<br />

minimal, ideal og maksimum tørretid<br />

Usecase test En testtype som tester om den interaktion mellem aktøren og systemet er<br />

håndteret korrekt eller om der sker uforudsete ting.<br />

Ækvivalensklasse Et begreb der bliver brugt indefor test-verdenen. Det beskriver basalt set et<br />

interval af tal hvor alle de tal resultere i det samme resultat når de sættes ind<br />

som parametre i en metode.<br />

Software konstruktion<br />

Klassemodel (Fælles)<br />

Følgende tekst beskriver hvordan den teoretiske model fra Software Design er implementeret ud fra de<br />

mønstre og principper fra undervisningen de foregående to semestre. Der vil være en beskrivelse af selve<br />

modellen i form af en forklaring af sammenhængene mellem klasserne, hvilket inkluderet en begrundelse<br />

for de valg af Collection-frameworket, samt en gennemgang af evt. polymorfi. Dernæst vil der være en kort<br />

forklaring på den genererede Java-doc, som er blevet genereret ud fra de kommentarer som ligger i koden.<br />

Der udover er der en gennemgang af de design-mønstre der er valgt, både mellem klasserne men også af<br />

opbygningen af individuelle klasser.<br />

Implementering af design-modellen<br />

Dette delafsnit beskæftiger sig mest med de valg der er blevet truffet ved implementeringen af modellen<br />

med hovedfokus på koblingerne mellem klasserne samt de Collections dette medfører.<br />

Sammenhæng mellem klasserne<br />

For at starte et sted kan der med fornuft begyndes med koblingen mellem Opskrift-klassen og Portion-<br />

klassen. Ifølge modellen er denne kobling af typen komposition. Dette betyder at en række ting skal være<br />

opfyldt for at denne kobling kan siges at være korrekt implementeret. For det første må det ikke være muligt<br />

at kunne oprette objekter af typen Portion på andre måder end igennem et objekt af typen Opskrift. Derfor<br />

skal konstruktoren i Portion-klassen have access-modify-eren 'package-private' da dette gør at det kun er<br />

muligt at oprette Portions objekter inde i den pågældende package og på den måde begrænse muligheden<br />

for oprettelse af det pågældende objekt. Nu hvor emnet er konstruktoren i Portions-klassen skal man huske<br />

at kigge på den pågældende multiplicitet for denne association. Her er det nemlig en kobling med<br />

multipliciteten en til mange hvilket betyder at det oprettede objekts konstruktor skal medtage et objekt af<br />

typen som oprettende objekt har.<br />

Side 38 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Dernæst kan der ses nærmere på de metoder som skal være til stede for at en komposition er gyldigt<br />

implementeret. Der skal som minimum være en metode som opretter Portions objekter. Normalt vil sådan<br />

en metode få de samme parametre med, som konstruktoren for den klasse som gerne vil oprettes har. Dog<br />

skal det siges, at i dette tilfælde har Opskrift-klassen alle de fornødne data til at kunne oprette et objekt af<br />

typen Portion, hvilket resulterer i at metoden ikke har nogle parametre med og derfor er kommet til at se<br />

ud som følger:<br />

public Portion opretPortion()<br />

Ovenstående metode kalder så konstruktoren i Portion-klassen som returnerer det nyoprettede objekt til<br />

brugeren som så kan benytte det derfra. Ved kald til denne metode bliver objektet også tilføjet til en liste<br />

over portioner som Opskrift-objektet har oprettet indtil nu.<br />

Der udover har udviklerne valgt at implementere en valgfri metode som gør det modsatte af den<br />

ovenstående metode. Den går nemlig ind og fjerner et Portions-objekt fra listen hvis listen vel at mærke<br />

indeholder det givne Portions-objekt. Her skal der lægges mærke til at valget af listen er faldet på typen<br />

ArrayList med en generisk type Portion. Baggrunden for dette valg ligger i at man er garanteret for at det<br />

samme objekt aldrig kan finde sted to gange i denne liste, da der for det første ikke er nogen 'tilføj'-metode<br />

som tilføjer objekter til listen. Dette ekskluderede valget af et Set da dette interface primært bliver brugt<br />

pga. denne egenskab. Derudover var det antagelsen at det altid skulle være muligt, hurtigt og nemt at tilgå<br />

og lave en iteration igennem listen, så man kunne tilgå et givent objekt nemmest, hvilket et ArrayList giver<br />

mulighed for.<br />

Vi hopper nu videre til koblingen mellem Portion-klassen og Placering. Denne association er en<br />

dobbeltrettet association med multipliciteten 0..1 til 0..1. Dette betyder at man her enten kan vælge at lade<br />

begge klasser stå for vedligeholdelse af dette link, eller man kan se på det forretningslogiske og vælge én<br />

klasse til at tage dette ansvar. I denne implementering er det Placering-klassen der skal stå for<br />

vedligeholdelse af dette link, da tanken bag dette var, at man gik hen til en placering og aktivt fjernede<br />

portionen fra placeringen. Derfor har Portion-klassen en 'package-private' setPlacering metode som kun kan<br />

tilgås gennem et Placerings-objekt, ergo har Placerings-klassen ansvaret.<br />

Med denne multiplicitet er ingen af klasserne tvunget til at have et objekt af modsatte parameter i dens<br />

konstruktor. I stedet har klassen en private attribut som har denne type, som så kan sættes til at være et<br />

konkret objekt af denne type på et givent tidspunkt. Dette gælder både for Placerings- og Portions-klassen.<br />

Dernæst kan man se på associationen mellem Portion- og Proces-klassen. Dette er af den samme type med<br />

Side 39 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

samme multiplicitet, som den sidst beskrevet komposition mellem Opskrift og Portion. Det inkluderer de<br />

samme krav for en gyldig implementation, i form af en ændring på konstruktorens access-modifyer, samt<br />

metode til oprettelse af objekter af typen Proces. Valget af collections i denne klasse er igen af typen<br />

ArrayList af den simple grund, at det skulle være muligt at få fat på den sidst tilføjede proces i listen over<br />

processer oprettet af den pågældende portion. Dette betød at Set ikke ville kunne benyttes da dette<br />

interface ikke indeholder implementering, som giver mulighed for at udtage specifikke elementer i henhold<br />

til et givent indeks.<br />

For at afslutte gennemgangen af valg af Collections skal der ses på associationen mellem Opskrift- og<br />

BehandlingsIndeks-klassen. Denne association vil resultere i, at der skal være en form for Collection i<br />

Opskrift-klassen over de BehandlingsIndeks-objekter som udgør den rækkefølge af behandlinger en portion<br />

skal igennem. Denne Collection kunne godt have været, uden problemer, af typen Set. Dog kom udviklerne<br />

ud for at dette var sværere at teste på under udviklingen af model-pakken. Et andet argument for at det<br />

kunne have været af typen Set var at lige præcis Opskrift-klassen indeholder en metode til at tilføje<br />

BehandlingsIndekser til listen. Dette kunne medføre at et objekt af denne klasse kunne blive tilføjet to<br />

gange, hvilket ikke vil give mening, da der så vil være to behandlingsindekser med den samme værdi for<br />

deres indeks attribut.<br />

Polymorfi<br />

I denne implementering er der næsten ikke benyttet polymorfi. Og her understreges ”næsten”. I denne<br />

implementering har man, som man kan se af design klasse diagrammet, valgt at have en superklasse –<br />

Behandling som også er en abstrakt klasse. Denne klasse har to subklasser som i teorien ville nedarve alle<br />

dens egenskaber. Men eftersom der her er valgt, at Behandling-klassen ikke har skullet have nogen<br />

egenskaber, hverken attributter eller metoder, men blot være der for at man kunne skabe en liste som både<br />

indeholdte objekter af typen Toerring samt Dragering, nedarver de to subklasser derfor ikke nogen<br />

egenskaber.<br />

JavaDoc<br />

Som en fast del af udviklingen af software systemer er det vigtigt at kommentere alle de metoder og svære<br />

logiske valg man har lavet inde i fx en metode. Dette har derfor resulteret i, at der i source-koden er blevet<br />

kommenteret for alle de metoder som ikke gav sig selv ud fra metodenavnet. Det skal derfor forstås på den<br />

måde at trivielle gettere og settere ikke er blevet kommenteret, da dette kun vil gøre source-koden<br />

linjemæssig længere.<br />

Måden der er blevet kommenteret på er ifølge en generel skabelon, som kan beskrives ud fra dette<br />

eksempel:<br />

Side 40 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

/**<br />

* Metoden opretter et objekt af typen Portion. Den får det første<br />

* behandlingsindeks med i constructoren så den ved hvilken behandling den<br />

* skal gennemføre først.<br />

* Hvis der ikke er noget behandlingsindeks med indeks nummer 1 vil det<br />

* returnerede portions-objekt blive sat til null.<br />

* Krav: En gyldig startTid, opskrift-objektet har et behandlingindeks i sin<br />

* liste med indeks-nummer 1<br />

*<br />

* @return skabte portions objekt til senere brug til fx. styrring af<br />

* behandlinger<br />

*/<br />

public Portion opretPortion()<br />

Den ovenstående kommentar er taget fra Opskrift-klassen for opretPortion-metoden. Her kan man se en<br />

lang beskrivelse som indeholder forskellige elementer som indgår i en JavaDoc (alle er dog ikke<br />

repræsenteret her). Det første er en kort beskrivelse af hvad den gør, efterfulgt af et html-linjeskift. Dernæst<br />

kommer der en uddybende forklaring på hvad der sker ved forskellige tilstande af objekter og systemer.<br />

Denne del indeholder også en beskrivelse af de krav metoden kræver, for at metoden opfører sig gyldigt og<br />

ikke sætter systemet i fare for evt. sammenbrud. Hvis en udefrakommende programmør skal benytte denne<br />

klasse til noget andet, er det kun garanteret at den vil fungere, hvis disse krav er opfyldt og ellers er det<br />

han/hendes egen skyld.<br />

I ovenstående eksempel er der vist hvordan et return-statement er medtaget. Denne del indeholder ikke et<br />

navn på det returnerede objekt eftersom et evt. navn på den interne variabel ikke påvirker objektet. I stedet<br />

er der en kort beskrivelse af det objekt som der bliver returneret og hvorfor det bliver returneret som det<br />

gør.<br />

For at vise en metode som medtager parametre tages der udgangspunkt i følgende eksempel:<br />

/**<br />

* Oprettelse af en Tørring <br />

* Krav: 0 < minimum < ideal < maksimum<br />

*<br />

* @param minimum<br />

* @param ideal<br />

Side 41 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

* @param maksimum<br />

*/<br />

public Toerring(int minimum, int ideal, int maksimum)<br />

Dette eksempel er forholdsvis simpelt da det er en konstruktor som tager tre heltal som parametre som har<br />

navnene minimum, ideal og maksimum. Når en kommentar-blok så bliver genereret bliver det vist som<br />

ovenstående @param notation. Hvis det ikke var fordi disse tre værdier er meget trivielle og lette at gætte<br />

sig til hvad repræsenterer, så ville man kunne give en kort beskrivelse af hvad de betød og evt. skulle bruges<br />

til. Som før ses, der at der til denne metode er stillet et krav for gyldig udførelse, som her er et simpelt<br />

matematisk udtryk, hvor de tre parametre indgår i.<br />

Hvis det ønskes kan resten af dokumentationen, JavaDoc, findes i source-koden eller bagerst i denne<br />

rapport som bilag.<br />

Design Mønstre<br />

For at optimere systemet så meget som muligt, er der også i dette system blevet benyttet design-mønstre. I<br />

dette system er der blevet brugt tre mønstre som udgangspunkt: observer-, singleton-, og strategy-pattern.<br />

Følgende tekst vil forklare hvordan og hvor disse patterns er fundet og implementeret i systemet.<br />

Observer<br />

Det klassiske observer mønster består normalt af fire elementer. For at starte på et generelt niveau er der to<br />

interfaces, Observer samt Subject, som indeholder metoder til at registrere og fjerne observerende objekter<br />

(Subject-interfacet) samt en metode til at update en observers tilstand (Observer-interfacet). Når man så<br />

har implementeret dem, kan man implementere de konkrete versioner af de to interfaces, som så er<br />

tvunget til at implementere de metoder som interfacene definerer.<br />

For at tage udgangspunkt i dette system er der også blevet implementeret to interfaceses med de<br />

repræsentative navne. Derudover er MainFrame klassen implementeret til at benytte Observer-interfacet<br />

og Service klassen til at benytte Subject-interfacet. Grunden til dette ligger i at udviklerne gerne vil have at<br />

visningen bliver opdateret når der rent faktisk er sket noget væsentligt i de underliggende lag i systemet.<br />

Dette gøres på den måde at MainFrame bliver registreret som observer på Service-klassen, som så siger til<br />

MainFrame at den skal opdatere visningen for hver gang TimeThread finder ud af at der er gået en ny dag<br />

og Service har opdateret alle portioners aktuelle processers status. Efter denne opdatering af status bliver<br />

update metoden i Observer-interfacet kaldt på den konkrete klasse MainFrame, som derefter vil opdatere<br />

visningen til at være akkurat som modellen. På den måde vil der altid være en valid aktuel visning af alle<br />

processer i GUI-en.<br />

I det normale Observer mønster er det muligt for det konkrete Subject at registrere mange observere. Dette<br />

Side 42 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

kunne også være gjort i dette systems tilfælde, men eftersom opgaven lød på at udvikle, og fremstille et GUI<br />

ville det ikke være nødvendigt, da det blev valgt kun at have ét sted som central visning med kun én klasse.<br />

Singleton<br />

Da det ønskes at der gemmes objekter et centralt sted i systemet, eller sørges for at der kun bliver<br />

opdateret igennem et objekt, var det nødvendigt at benytte dette mønster da det sikrer denne egenskab<br />

bedst. Pointen ved dette mønster er, at der kun bliver oprettet højest et objekt af klassen i hele systemets<br />

run time. Måden at gøre dette på er at gøre konstruktoren i klassen privat og lave en statisk metode som<br />

alle ville kunne tilgå, public access modifyer, som så tjekkede om der allerede eksisterede et objekt (statisk<br />

attribut af klassens type i klassen), hvorefter den enten vil oprette et hvis det ikke var tilfældet og så<br />

returnere det eller blot returnere det allerede oprettede objekt. Når denne getInstance metode først bliver<br />

kaldt bliver attributten sat til et nyt objekt af klassens type. Det betyder at hvis dette var et multi-bruger<br />

system skulle en klasse der var designet efter Singleton mønstret gennemtænkes endnu engang. Ved<br />

implementeringen af getInstance metoden skulle der så tages højde for at denne metode skulle<br />

implementeres så det ikke er muligt, ved et tilfælde, at systemet fx fik oprettet to objekter af typen DAO.<br />

Dette kunne gøres, og er gjort i dette system, ved at implementere metoden med acces-modifyeren<br />

synchronized. Dog er dette ikke nødvendigt da beskrivelsen af systemet inkluderede begrænsningen at<br />

systemet var et single-user system. Dette er dog gjort alligevel da det vil danne en bedre grund for evt.<br />

videreudvikling af systemet.<br />

public class Service implements Subject {<br />

private static Service unique;<br />

...<br />

public static synchronized Service getInstance() {<br />

}<br />

if (unique == null)<br />

unique = new Service();<br />

return unique;<br />

private Service() {<br />

}<br />

dao = DAO.getInstance();<br />

dato = SystemDato.getInstance();<br />

Side 43 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

}<br />

...<br />

I dette system er der benyttet singleton på DAO, Service og SystemDato. De to første klasser er allerede<br />

blevet forklaret hvorfor de er blevet implementeret således.<br />

Grunden til at SystemDato-klassen er implementeret på den måde ligger i at systemet kun skal hente de<br />

nødvendige datoer fra én klasse, så der ikke opstår en uens udvikling i tiden. Hvis der var to, ville det være<br />

muligt at nogle objekter fik deres datoer fra et SystemDato objekt mens andre fik fra en anden. Oven i det<br />

ville de to objekter af SystemDato kunne have to forskellige udgangsdatoer<br />

Strategy<br />

Pointen i strategy-mønstret er at generalisere klasserne hvor der på et eller andet punkt er en central klasse<br />

som alle subklasser nedarver fra. På den måde kan man benytte superklassen som en type definition på fx<br />

en attribut i ens application. På den måde kan der assignes et objekt af en subklasse til attributten som så<br />

ikke skal have skiftet værdi. Dette gør også at det er muligt at udvide systemet nemmere ved blot at lave en<br />

klasse som nedarver fra superklassen. Så længe attributten er defineret til at være af superklassens type, vil<br />

der ikke være noget yderligere problem i det.<br />

Grunden til at dette mønster er taget med i dette afsnit, ligger i implementeringen af Behandlings-,<br />

Toerrings- og Dragerings-klassen. Hele konceptet i strategy-mønstret kan ses her. Når et BehandlingsIndeks<br />

oprettes kræver det nemlig en eller anden form for behandling som en fast del af BehandlingsIndeks<br />

objektet. Hvis man ikke benyttede strategy mønstret kunne man fx have to attributter, en med typen<br />

Dragering, og en med typen Toerring. Så skulle der blot testes for hvilken af de to attributter der ikke var<br />

null for derefter at udføre behandling ud fra det andet. Men hvad hvis man havde ti forskellige<br />

behandlinger? Det ville så inkludere ti forskellige attributter i klassen der benytter en af behandlingerne,<br />

hvilket ikke er effektivt. Derfor er der i systemet implementeret en abstrakt klasse som både Toerring- og<br />

Dragering-klassen nedarver fra. På den måde skal der blot være en attribut i BehandlingsIndeks klassen som<br />

både kan have et konkret objekt værdi af typen Toerring og Dragering. Selv hvis systemet kommer til at<br />

inkludere flere behandlingstyper, er det kun oprettelsen af den nye behandlingstype som klasse der<br />

nedarver fra Behandling som skal implementeres, og intet i andre klasser - som udgangspunkt.<br />

Side 44 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Implementering af arkitektur (Robert)<br />

Vi vil nu vise hvordan vores 3 lags arkitektur er blevet implementeret i praksis. Dette vil vi gøre ved at vise<br />

hvordan en bestemt use case, nemlig ”Opret opskrift”, er implementeret. Som beskrevet i dens beskrivelse,<br />

går denne use case ud på at oprette og tilføje en opskrift til systemet.<br />

Den første fase i implementeringen gik ud på, hvad en opskrift skal indeholde. Vi blev enige om, at en<br />

opskrift som fx ”Lakrids”, skal gemmes i en liste, samt en antagelse om at en opskrift skal indeholde en eller<br />

flere behandlinger. Dette kræver at man har nogle behandlinger og disse et behandlingsindeks. Alt dette er<br />

blevet kodet på model-plan og sammenhængen kan tydes ud fra design klassediagrammet, samt DSD for<br />

use casen.<br />

For at vise sammenhængen i arktiekturen vil vi nu gennemgå use casen.<br />

Når vi opretter en opskrift i vores GUI, kalder vi en ”OpretOpskrift”-metode i vores service klasse. Denne<br />

metode henter da constructeren fra Opskrift-klasssen i modellen og kalder Dao for at gemme opskriften.<br />

De valgte behandlinger til opskriften bliver hentet til GUI fra Dao i form af en liste, hvor vi igen henter en<br />

metode fra service for at give behandlingerne til opskriften et behandlingsindeks..<br />

GUI:<br />

private class OkButtonActionListener implements ActionListener {<br />

….<br />

….<br />

if(opskrift == null){<br />

Opskrift o = Service.getInstance().opretOpskrift(navn);<br />

int indeks = 1;<br />

for (Behandling b : valgte) {<br />

o.addBehandlingsIndeks(Service.getInstance().opretBehandlingsIndeks(<br />

indeks, b));<br />

indeks++;<br />

}<br />

…<br />

…<br />

}<br />

Ovenstående viser hvordan vi kalder service klassen. Desuden henter listen ”valgte” sine behandlinger fra<br />

dao.<br />

Service:<br />

public Opskrift opretOpskrift(String navn) {<br />

Opskrift o = new Opskrift(navn);<br />

dao.addOpskrift(o);<br />

return o;<br />

}<br />

Ovenstående viser hvordan Service bruger modellen og Dao.<br />

Side 45 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Vi har i vores arkitektur model en forbindelse fra GUI’en direkte til DAO. Denne forbindelse er, udover<br />

eksemplet med listen ”valgte”, for eksempel implementeret når en portion har stået for længe til tørre og<br />

derfor skal tilføjes til spild. Tanken bag denne forbindelse ligger i, at der ikke skal andet end en simpel<br />

tilføjelse af et portion-objekt til en ArrayListe for at dette kan lade sig gøre. Her kunne man kalde en<br />

metode i Service som så kalder denne funktion i Dao, men det fandt vi i gruppen som unødvendigt da det<br />

blot skaber mere uoverskuelighed.<br />

private class BtnPlukListener implements ActionListener {<br />

public void actionPerformed(ActionEvent e) {<br />

if (!list.isSelectionEmpty()) {<br />

Proces p = (Proces) list.getSelectedValue();<br />

if (p.getStatus() != StatusType.NOT_DONE) {<br />

if (p.getStatus() == StatusType.OLD) {<br />

JOptionPane.showMessageDialog(MainFrame.this, "Tilføj til spild",<br />

"Næste behandling", JOptionPane.INFORMATION_MESSAGE);<br />

dao.addTilSpild(p.getPortion());<br />

} else {…}<br />

Her kalder vi direkte til Dao klassen for at tilføje den valgte Portion til spild (dao.addTilSpild(p.getPortion());<br />

Fejl håndtering (Frederik)<br />

I vores system har vi gået ud fra at den daglige bruger af systemet har modtaget et minimum af<br />

undervisning i hvordan systemet fungerer. Derfor har vi sigtet efter at gøre systemet meget brugervenligt<br />

og fejlfrit.<br />

Til at håndtere disse fejl har vi gjort følgende.<br />

If – sætninger<br />

Vi bruger hovedsagligt if - sætninger til at kontrollere at der bliver tastet et gyldigt input og at de<br />

overholder systemets krav, ved den pågældende handling der udføres.<br />

if (navn.length()!= 0 && valgte.size() != 0) {<br />

if (opskrift == null) {<br />

Opskrift o = Service.getInstance().opretOpskrift(navn);<br />

int index = 1;<br />

for (Behandling b : valgte) {<br />

o.addBehandlingsIndeks(Service.getInstance().opretBehandlingsIndeks(index, b));<br />

index++;<br />

}<br />

}<br />

else {<br />

Service.getInstance().updateOpskrift(opskrift, navn, valgte);<br />

}<br />

Det ovenstående eksempel viser at man ikke kan lave en opskrift uden at der er indtastet navn og valgt<br />

minimum en behandling, fra listen valgte behandlinger.<br />

Try – catch<br />

Try – catch bliver brugt til at håndtere exceptions. Ved oprettelsen af en behandling har vi eksempelvis<br />

brugt en Try – catch til at sørge for at der ikke bliver indtastet bogstaver, hvor der forventes en talværdi.<br />

try {……}<br />

catch (NumberFormatException ex) {<br />

Side 46 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

JOptionPane.showMessageDialog(BehandlingCDialog.this,<br />

"Vær venlig at brug tal", "Fejl ved input",<br />

JOptionPane.ERROR_MESSAGE);<br />

Til at vise hvilke fejl brugeren begår, har vi lagt stor vægt på fejlmeddelelser i Gui i form af en JOptionPane<br />

der kommer med en given løsning. Derudover er der også visse knapper og felter der først bliver aktiveret<br />

når de korrekte foregående handlinger er gjort. Dette viser vi senere i vores guidede tour af systemet.<br />

For at beskytte imod yderligere fejl har vi lavet JUnit-test. Her henviser vi til afsnittet med JUnit-test og<br />

testdata, for at vise netop hvilke fejl vi forebygger imod.<br />

JUnit test (Mads)<br />

Når en testcase er opstillet ud fra ækvivalensklasser samt grænseværdier skal det også bruges til noget.<br />

Derfor er der i den første version af dette system blevet implementeret JUnit test for de fleste af de mere<br />

interessante klasser med de metoder som ikke blot er af typen get og set.<br />

I dette afsnit vil der blive gennemgået en JUnit test ud fra den modul test som tidligere er blevet<br />

gennemgået af klassen Proces. Grunden til at denne klasse er valgt var af den grund at den indeholdte klare<br />

intervaller hvor objektet kunne have forskellige tilstande.<br />

Der er mange måder man kan implementere en sådan test og her vil der blive gennemgået to forskellige for<br />

at vise hvor meget kode der kan være til forskel, mellem en minimalistisk og en slavisk implementering.<br />

Til at starte med kan man kigge på grænseværdierne i tabellen som tidligere opstillet, og lave et assert-tjek<br />

for hver af resultaterne og sammenligne med de forventede resultater. Denne metode er en meget direkte<br />

tilgang, men kræver meget kopiering af kode som kan resultere i svær debugging ved evt. copy-paste fejl.<br />

Nedenstående udpluk af kode kommer fra testklassen for Proces-klassen. Her kan man se hvordan man kan<br />

tjekke for hver grænseværdi i tabellen.<br />

public class ProcesTest {<br />

...<br />

@Test<br />

public void testBeregnStatus_Toerring_SD(){<br />

Date curDate = null;<br />

proces = portion.getAktuelProces();<br />

Date start = proces.getStartTid();<br />

Toerring t1 = (Toerring) b1;<br />

curDate = DateUtil.createDate(start, 0);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.NOT_DONE);<br />

curDate = DateUtil.createDate(start, t1.getMinimum() - 1);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.NOT_DONE);<br />

curDate = DateUtil.createDate(start, t1.getMinimum() - 1);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.NOT_DONE);<br />

curDate = DateUtil.createDate(start, t1.getMinimum());<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.MINIMUM);<br />

curDate = DateUtil.createDate(start, t1.getMinimum() + 1);<br />

Side 47 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.MINIMUM);<br />

curDate = DateUtil.createDate(start, t1.getIdeal() - 1);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.MINIMUM);<br />

curDate = DateUtil.createDate(start, t1.getIdeal());<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.IDEAL);<br />

curDate = DateUtil.createDate(start, t1.getIdeal() + 1);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.IDEAL);<br />

curDate = DateUtil.createDate(start, t1.getMaksimum() - 1);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.IDEAL);<br />

curDate = DateUtil.createDate(start, t1.getMaksimum());<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.MAKSIMUM);<br />

curDate = DateUtil.createDate(start, t1.getMaksimum() + 1);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.OLD);<br />

curDate = DateUtil.createDate(start, t1.getMaksimum() + 5);<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.OLD);<br />

}<br />

}<br />

Som man kan se på ovenstående eksempel er der rigtig meget kode for ikke særlig meget test. Derfor kan<br />

man optimere det ved at lade kode itterere igennem alle værdier fra den første grænseværdi og til den<br />

sidste. Nogen vil argumentere for at dette ikke er i henhold til ækvivalensklasse-testing eftersom man<br />

benytter sig af alle værdierne frem for blot grænseværdierne.<br />

public class ProcesTest {<br />

...<br />

@Test<br />

public void testBeregnStatus_Toerring(){<br />

proces = portion.getAktuelProces();<br />

Date start = proces.getStartTid();<br />

Toerring t1 = (Toerring) b1;<br />

for(int i = 0; i < t1.getMaksimum() + 3; i++){<br />

Date curDate = DateUtil.createDate(start, i);<br />

if(i < t1.getMinimum())<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.NOT_DONE);<br />

else if(i >= t1.getMinimum() && i < t1.getIdeal())<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.MINIMUM);<br />

else if(i >= t1.getIdeal() && i < t1.getMaksimum())<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.IDEAL);<br />

else if(i == t1.getMaksimum())<br />

Side 48 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.MAKSIMUM);<br />

else<br />

assertTrue(proces.beregnStatus(curDate) == StatusType.OLD);<br />

}<br />

}<br />

...<br />

}<br />

Som man kan se på ovenstående eksempel er dette meget mere minimalistisk at læse og forstå. Dog skal<br />

det siges at det dog kræver at man sætter de forskellige if-else if statements rigtigt op for at få de korrekte<br />

resultater i henhold til programmets nuværende implementering. Dette er dog ikke noget problem da disse<br />

statements blot skal laves i henhold til ækvivalensklassernes deffinitationer fra før.<br />

For at færdigøre denne gennemgang af JUnit test skal der også tages forbehold for at det ikke blot er<br />

tørrings behandlinger der kan være i et proces-objekt. Dette tjek er designet på samme måde som ved<br />

Toerrings-objektet så derfor henvises der blot til source-koden da det ville være redundant at gennemgå<br />

dette igen.<br />

For at have endegyldigt testet denne klasse skal konstruktoren i klassen også testes. Dette kan gøres ved at<br />

opstille de forventninger man har til den, som fx initialisering af forskellige lister og elementer ved at tjekke<br />

om de er null. Grunden til at gøre dette er for at undgå forskellige exceptions som fx null-pointer exceptions<br />

pga. ikke initializerede lister.<br />

I dette test-case er tjekket af konstruktoren designet som følgende hvor største delen af klassens attributter<br />

bliver tjekket om de er sat til det ønskede.<br />

public class ProcesTest {<br />

...<br />

@Test<br />

public void testProces() {<br />

assertTrue(proces.getStartTid() != null);<br />

assertTrue(proces.getBehandling() == b1);<br />

assertTrue(proces.getPortion() == portion);<br />

assertTrue(proces.getStatus() == StatusType.NOT_DONE);<br />

}<br />

}<br />

Specielt interessant kode (Fælles)<br />

Som ved alle andre systemer er der altid noget kode som er mere interressant end så meget andet. Derfor<br />

er dette afsnit tildelt til lige præcis dette, nemlig en gennemgang af det kode som udviklerne har fundet<br />

særlig interessant at arbejde med.<br />

TimeThread & SystemDato klasserne<br />

En af de sjovere problemer som dette system har været udsat for har været, hvordan skal det testes nu hvor<br />

systemet skal opdatere hver gang der er gået en ny dag? Det nemme svar ville være at implementere en<br />

knap til opdatering, men nu hvor undervisningen har vist at dette kan håndteres igennem brugen af tråde i<br />

programmeringen var dette det absolutte mest optimale valg. Og det sjoveste, nu hvor det fik GUI-en til at<br />

skifte farve automatisk.<br />

Side 49 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Så hvad er det lige der er blevet gjort for at systemet er kommet til at kunne automatisk opdatere systemet i<br />

real-time men samtidig at opdatere lidt oftere når systemet bliver testet?<br />

Det første problem der skulle overvindes var at lave en tråd som konstant kører, sideløbende med hovedsystemet.<br />

Så derfor var det nødvendigt at implementere en klasse til lige præcis dette formål, nemlig<br />

TimeThread-klassen.<br />

public class TimeThread extends Thread {<br />

…<br />

private final int DELAY = 10000;<br />

private final boolean TEST = true;<br />

…<br />

}<br />

Denne klasse extender som en selvfølge Thread superklassen for at det er muligt at kører den som en tråd<br />

sideløbende med resten. For at håndtere både hvor ofte tråden skal tjekke for om der er gået en ny dag<br />

(real-time) eller inkrementere test-systemets dato med en (test), samt håndtere om den skal gøre det ene<br />

eller andet er der i klassen blevet deffineret to konstanter. Nemlig DELAY som håndtere hvor ofte den skal<br />

gøre noget samt TEST som håndtere om det er det ene eller andet mode systemet skal kører efter.<br />

public class TimeThread extends Thread {<br />

…<br />

public void run() {<br />

Date date;<br />

try {<br />

if (TEST) {<br />

while (true) {<br />

Thread.sleep(DELAY);<br />

date = DateUtil.createDate(dato.getDato(), 1);<br />

dato.setDato(date);<br />

service.checkVareStatus();<br />

}<br />

} else {<br />

while (true) {<br />

Thread.sleep(DELAY);<br />

date = new Date();<br />

if (DateUtil.daysDiff(date, dato.getDato()) != 0) {<br />

dato.setDato(date);<br />

service.checkVareStatus();<br />

}<br />

}<br />

}<br />

} catch (InterruptedException e) {<br />

}<br />

}<br />

…<br />

}<br />

Så er det basale på plads, så er der faktisk kun en interessant metode tilbage, nemlig run-metoden. Denne<br />

metode bliver brugt når tråden, som noget af det første i programmet, bliver initialiceret hvilket gør at det<br />

der er deffineret i denne metode skal danne rammer for hele systemets levetid. For at håndtere det at<br />

Side 50 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

tråden ikke skal slutte er der i denne lavet et tjek på om systemet er i det ene eller andet mode for derefter<br />

at begynde en uendelig løkke. Til at starte med i loopet bliver tråden sat til at sove i det antal milisekunder<br />

som er deffineret i DELAY konstanten for at danne et interval for hvornår tråden skal gentage sine aktioner.<br />

Når dette så er overstået er det så afhængigt af om systemet er i test-tilstand eller ej hvad den så gør. Hvis<br />

den er i test-tilstand henter den så systemets nuværende dato fra singleton klassen SystemDato som den så<br />

tilføjer en dag til efterfulgt af at den sætter SystemDato til at have den nye dato. Så for hver DELAY<br />

milisekunder bliver systemets dato inkrementeret med en.<br />

Men hvis systemet ikke er i test men i real-time tilstand går den ind og tjekker på om computerens<br />

nuværende dato er en anden end den i SystemDato klassen. Hvis dette er sandt vil SystemDato blive sat til<br />

at have den aktuelle computer dato. Igen, dette tjek vil blive foretaget for hvert DELAY milisekunder.<br />

Som en afsluttende del i både test og real-time modes bliver service metoden checkVareStatus kaldt. Denne<br />

metode bliver beskrevet som det næste.<br />

SystemDato klassen er en af de mere centrale klasser i systemet. Denne klasse holder altid den aktuelle<br />

dato om systemet så er i test-mode eller ej. Grunden til at denne klasse er i model pakken er alene fordi de<br />

klasser som fx Portion og Proces der skal tilgå en eller anden form for dato som skal repræsentere start- og<br />

slut-tider bliver nød til ikke bare direkte at tilgå computerens dato da dette ville gøre det umuligt at benytte<br />

et test-mode. På den måde henter de datoen fra denne klasse som altid har systemets aktuelle date objekt<br />

lige meget modet.<br />

checkVareStatus & beregnStatus metoderne<br />

Nu hvor systemets tidshåndtering er blevet forklaret er disse metoder det naturlige næste-valg, siden det er<br />

de metoder som bliver kaldt for hver gang TimeThread gennemgår en itteration.<br />

For hurtigt at gennemgå meningen med systemet, kan det sumeres op på få linjer. For hver 'dag' der går i<br />

systemet så skal systemets aktuelle processer (aktive portioner) opdateres, forstået på den måde at der skal<br />

tjekkes for om de skal have en ny status ud fra både den nuværende behandling samt forløbet de har været<br />

i behandlingen indtil nu.<br />

public class Service implements Subject {<br />

…<br />

public void checkVareStatus() {<br />

for (Opskrift o : dao.getOpskrifter()) {<br />

for (Portion p : o.getPortioner()) {<br />

Proces pp = p.getAktuelProces();<br />

if (pp.getStatus() != StatusType.DONE<br />

&& pp.getStatus() != StatusType.SPILD) {<br />

pp.beregnStatus(dato.getDato());<br />

}<br />

}<br />

}<br />

notifyObserver();<br />

}<br />

…<br />

}<br />

Den metode som så bliver kaldt for hver dags-inkrementering er checkVareStatus. Nogle vil nok mene at<br />

denne metode i sig selv, absolut ikke er interessat da det blot er to for-løkker med et enkelt tjek i midten.<br />

Men enkelt er nogle gange godt. Her tager vi alle opskrift-objekterne fra DAO-en, og som vi ved kan vi kører<br />

alle dens portioner igennem da de ligger som lister i opskrift-objekterne og derefter tjekke den aktielle<br />

processes status. Hvis den aktuelle proces ikke har status af DONE, hvilket vil betyde at portionen er færdig,<br />

Side 51 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

eller SPILD, hvilket betyder at den aktuelle portion er overført til spild, skal der kaldes en beregnStatus på<br />

portionen. Grunden til at dette tjek af den nuværende status er nødvendigt er fordi hvis de er færdige er de<br />

faktisk pakket og hvis de er spild, ja så er de godt på vej ud til en grisse-farm som fodder.<br />

public class Proces {<br />

…<br />

public StatusType beregnStatus(Date currentDate) {<br />

if (behandling instanceof Dragering) {<br />

if (DateUtil.daysDiff(<br />

getDoneDate(((Dragering) behandling).getVarighed()), currentDate) == 0) {<br />

slutTid = currentDate;<br />

status = StatusType.DONE;<br />

portion.naesteBehandling();<br />

}<br />

} else if (behandling instanceof Toerring) {<br />

Toerring t = (Toerring) behandling;<br />

int minDiff = DateUtil.daysDiff(getDoneDate(t.getMinimum()), currentDate);<br />

int idealDiff = DateUtil.daysDiff(getDoneDate(t.getIdeal()), currentDate);<br />

int maxDiff = DateUtil<br />

.daysDiff(getDoneDate(t.getMaksimum()), currentDate);<br />

if(status != StatusType.SPILD && status != StatusType.DONE){<br />

if (minDiff >= 0 && idealDiff < 0) {<br />

status = StatusType.MINIMUM;<br />

} else if (idealDiff >= 0 && maxDiff < 0) {<br />

status = StatusType.IDEAL;<br />

} else if (maxDiff == 0) {<br />

status = StatusType.MAKSIMUM;<br />

} else if (DateUtil.daysDiff(getDoneDate(t.getMaksimum()), currentDate) > 0) {<br />

status = StatusType.OLD;<br />

portion.setSlutTid(SystemDato.getInstance().getDato());<br />

}<br />

if (status != StatusType.NOT_DONE)<br />

slutTid = currentDate;<br />

}<br />

}<br />

return status;<br />

}<br />

…<br />

}<br />

Det beregnStatus så gør er faktisk slavisk arbejde, så at sige. Den har en parameter i form af den nuværende<br />

dato som start-tiden for processen skal tjekkes op i mod. Som man måske kan gætte sig til er det datoen fra<br />

SystemDato som normalt bliver givet med. Så hvorfor overhovedet have denne parameter med? Jo, for at<br />

kunne teste uden at skulle sætte SystemDato-klassen op, simpel dovenskab, og en lille bonus... Klassernes<br />

afhængighed bliver ikke nær så stor.<br />

Det selve metoden gør at tjekke for om behandlingen er af en bestemt type for efterfølgende at gennemgå<br />

en lang række tjeks for at se om der er sket nok til at processen skal skifte status. Som en start kan<br />

behandlingen fx være af typen Dragering. I dette tilfælde kan processen have to forskellige statustyper,<br />

NOT_DONE og DONE. Det skal så siges at en dragering har en varigheds-attribut som repræsentere den tid<br />

Side 52 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

behandlingen tager. For derfor at gå fra NOT_DONE til DONE kræver det at currentDate er lig med startTidattributten<br />

plus varigheds-attributten. Hvis dette er tilfældet skiftes der status og den næste behandling i<br />

opskriften bliver kaldet.<br />

Men hvad hvis den nu behandlingen er af typen Toerring? Jo her er det mere interessant da dette, som<br />

beskrevet i afsnittet omkring testing, indeholder nøje implementerede tjek for værdierne. Hver af disse<br />

tjeks kan resultere i at processen skifter status til MINIMUM til IDEAL til MAKSIMUM til OLD. Dette er den<br />

naturlige gang en proces kan komme igennem, forhåbentligt bliver portionen plukket før den ender med<br />

status OLD.<br />

Når alle portioner er blevet tjekket igennem kaldene i checkVareStatus er der et sidste metodekald til<br />

notifyObserver som leder til den sidste del af dette afsnit, nemlig ColorRender-klassen i MainFrame-klassen.<br />

ColorRender-klassen<br />

Det er okay bare at inkludere en processes status i dens toString metode for at indikere hvor langt den er<br />

nået i tørringen på lageret, men det giver ikke rigtig noget illustrativt til at idendikere den pågældende<br />

status. Altså det er nemmere at overse tekst med samme farve men med forskellig indhold. Derfor har<br />

udviklerne haft den ide, lige fra starten af designprocessen at der skulle være en eller anden form for farvekodning<br />

for hvornår en proces har en given status.<br />

public class MainFrame extends JFrame implements Observer {<br />

…<br />

private class ColorRenderer extends BasicComboBoxRenderer {<br />

private static final long serialVersionUID = 1L;<br />

@SuppressWarnings("unused")<br />

private JList list;<br />

@SuppressWarnings("unused")<br />

private Border border;<br />

public ColorRenderer(JList list) {<br />

this.list = list;<br />

border = new LineBorder(Color.WHITE);<br />

}<br />

public Component getListCellRendererComponent(JList list, Object value,<br />

int index, boolean isSelected, boolean cellHasFocus) {<br />

super.getListCellRendererComponent(list, value, index, isSelected,<br />

cellHasFocus);<br />

setText(value.toString());<br />

StatusType status = ((Proces) value).getStatus();<br />

if (status == StatusType.NOT_DONE)<br />

setBackground(listOpskrifter.getBackground());<br />

else if (status == StatusType.MINIMUM)<br />

setBackground(Color.yellow);<br />

else if (status == StatusType.IDEAL)<br />

setBackground(Color.green);<br />

else if (status == StatusType.MAKSIMUM)<br />

setBackground(Color.red);<br />

else if (status == StatusType.OLD) {<br />

Side 53 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

setBackground(Color.black);<br />

setForeground(Color.white);<br />

}<br />

if (isSelected)<br />

setBackground(new JList().getSelectionBackground());<br />

return this;<br />

}<br />

}<br />

}<br />

Til denne opgave er der blevet implementeret en privat klasse i GUI-pakkens MainFrame-klasse. Det klassen<br />

gør er at nedarve fra BasicComboBoxRender som basalt set er den der håndtere hvordan det illustrativt skal<br />

vises i GUI-en og ikke mindst hvad der skal stå i de forskellige elementer i JListen. Når listens indehold så<br />

bliver sat ved at kalde setListData bliver hver objekt som bliver sat i listen tjekket for dens pågældende<br />

status for derefter at sætte en tilhørende baggrundsfarve for at indikere den illustrativt.<br />

Denne illustrative funktion gør det muligt for folk der måske er ordblinde også at arbejde med dette system.<br />

Oven i det kan det være at det gør at folk, gennem læsningen af farver, undgår at der er særlig mange vare<br />

som går til spilde.<br />

Guided Tour (Fælles)<br />

Vi vil i vores guided tour vise hvordan vores system virker i en simulering. I det gennemgående eksempel vil<br />

vi vise hvordan en ny opskrift oprettes og oprette en portion med denne.<br />

Når programmet startes mødes vi af et vindue, hvor vi har valgt at bruge tabs til at manøvrere rundt i<br />

programmet. En opskrift tab der viser en liste over opskrifter, samt to knapper: enten til at oprette en ny<br />

opskrift eller få vist hvilke behandlinger en opskrift indeholder. Vi starter med at se hvad ”NiceLakrids”<br />

indeholder, for derefter at lave en ny opskrift.<br />

Side 54 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Vælges en behandling, aktiveres knapperne i midten, hvorefter man kan rykke op og ned på<br />

behandlingernes behandlingsindeks. Det er også muligt at fjerne en behandling fra NiceLakrids, eller tilføje<br />

en ekstra fra ”Alle behandlinger”. Det er ikke muligt at fjerne en behandling fra ”Alle behandlinger”.<br />

Vi opretter nu en ny opskrift og opretter og tilføjer denne en tørrings behandling, med minimum tørring 1<br />

dag, ideal tørring 2 dage og maksimum tørring 3 dage. Dette bliver denne opskrifts eneste behandling.<br />

Vi trykker nu ”Ok” knappen og opskriften bliver tilføjet listen over opskrifter i vores ”Opskrift” tab.<br />

Side 55 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Vi trykker nu på vores ”Portion” tab. Her findes en liste over alle igangværende processer. Til at starte med<br />

er listen altså lige nu tom. Vi trykker på ”Opret Portion” og får en liste med de mulige opskrifter. Vi vælger<br />

nu den netop oprettede opskrift og sætter en portion i gang.<br />

Da denne portions første og eneste behandling er af typen tørring, skal den ind på mellemvarelageret og<br />

have en placering. Vi vælger derfor en placering.<br />

Side 56 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Når en placering er valgt, sættes processen i gang. Portionens aktuelle proces vises i listen. I dette eksempel<br />

er der kun en behandling, som er en tørring. Denne tørring bør plukkes efter 2 dage, da den der har den<br />

ideelle konsistens. Til at illustrere processens status markeres portionen i listen i forskellige farver. Grå når<br />

portionen ikke har nået minimal tørring endnu og derfor ikke kan plukkes, gul ved minimal tørring, grøn ved<br />

ideel tørring, rød ved maksimal tørring og sort når tørringen har været for længe på lager og skal plukkes til<br />

spild. I dette eksempel plukker vi ved ideel tørring og portionen sendes derfor til pakning.<br />

Sammenligner vi de to virksomheders nettoomsætning, er Toms’ 4,31 gange større end <strong>Carletti</strong>s. Toms’ har<br />

dog endnu mere på lager end <strong>Carletti</strong> i forhold til omsætning da Toms’ varebeholdning er 5,9 gange større<br />

end <strong>Carletti</strong>s. Antager vi, at gælden til leverandørerne, er hvad der er blevet brugt på dette punkt, har<br />

Toms’ brugt 4,6 gange mere end <strong>Carletti</strong>.<br />

Side 57 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Toms har meget mere på lager, men <strong>Carletti</strong> bruger mere på leverandører i forhold til beholdningen. Dette<br />

kan tyde på at <strong>Carletti</strong> vil gøre mere for at komme af med deres varer, men at de også må betale sig fra det<br />

i form af flere penge på transport eller leverandører.<br />

Disse tal kan selvfølgelig ikke sammenlignes ordentligt, da vi har lavet nogle antagelser, samt vi ikke kender<br />

grunden til fx Toms store varebeholdning. Der kan være forskel på fx produktionstiden hos Toms, som gør<br />

at varerne skal ligge længere tid på lageret.<br />

Som endelig vurdering af logistik systemet, må man sige at <strong>Carletti</strong> A/S er velfungerende, da de trods alt har<br />

et stort overskud(reference). Det ser ud til, at de er gode til at få sendt deres varer af sted fra deres lager,<br />

selvom de har en høj lagerservicegrad. Deres samspil mellem leveringsservice og logistikomkostninger ses<br />

fx i form af, at de både er masseproducerende men samtidig kan omstille sig. Dette viser, at de er<br />

leveringsfleksible og samtidig har logistikomkostningerne til at kunne fuldføre dette. Et spil som resulterer i<br />

logistisk effektivitet.<br />

Konklusion<br />

Delkonklusion - Informations Teknologi i Organisationer:<br />

Arbejdet med ITO har været en stor udfordring og en periode med mange frustrationer. Det var utrolig<br />

svært at begrænse sideantallet, da ITO er et meget vidt begreb og de givne problemstillinger kunne<br />

angribes på mange måder. Da vi endelig synes at have overkommet vores frustration og vi var kommet<br />

frem til en fornuftig indgangsvinkel, kunne vi begynde at skrive.<br />

Vores resultat i ITO er endt med at have størstedelen af fokus på hvordan <strong>Carletti</strong> fungerer som<br />

produktionsvirksomhed, samt en løsning på mellemvarelager problemet.<br />

Delkonklusion - Software Design:<br />

Efter at have lavet en business case i ITO blev vi hurtigt enige om nogle centrale use cases. Dette gjorde at<br />

arbejdet med system design blev sat hurtigt i gang, da vi allerede har skabt os et godt overblik over,<br />

hvordan vores IT-løsning i sidste ende skal fungere. Dog faldt vi over nogle frustrationsmomenter, blandt<br />

andet synes iterationsprocessen uendelig, i det man hele tiden skulle vurdere og revurdere ens arbejde i<br />

forhold til nye tiltag.<br />

Vores resultat i SD gav et godt startskud til vores software konstruktionen. Vi synes især vores<br />

færdiggørelse af design diagrammet gav grundlag for gode centrale løsninger i forhold til use cases og<br />

derefter andre SD redskaber.<br />

Delkonklusion - Software Konstruktion:<br />

Vores software konstruktion er lavet på baggrund af vores system design. Det var derfor relativt hurtigt at<br />

få lavet programmets model og lave en simpel simulering uden GUI. SK forløbet handlede derfor at lægge<br />

sig tæt op ad vores design, som var en af udfordringerne i SK.<br />

Side 58 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Den største udfordring i software konstruktionen var at lave vores GUI, hvis simple design vi trods alt er<br />

meget tilfredse med. Alt i alt synes vi dog at vores program er yderst velfungerende og at det er lykkedes at<br />

opnå et brugervenligt enkeltbrugersystem.<br />

Overordnet konklusion:<br />

I dette projekt har vi arbejdet ud fra problemstillingen med et mellemvarelager problem angående<br />

overskridende tørretider, og vores opgave har været at lave et system der løser dette.<br />

Vores system håndterer oprettelsen af opskrifter, portioner, behandlinger, samt placeringer. Derudover<br />

bliver tørretidernes status vist i en liste med portioner i farvekoder til hurtigt at skabe et overblik over<br />

portionens status i handlingsforløbet. I forhold til <strong>Carletti</strong>s nuværende system med sedler, synes vi at dette<br />

er en fremragende løsning til deres problem med spildprocent.<br />

Samarbejdsmæssigt har vi været gode til i gruppen, at uddelegere opgaver men samtidigt assistere<br />

hinanden.<br />

Side 59 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Bilag<br />

Klassebeskrivelser<br />

Navn:<br />

Opskrift<br />

Mening med klassen:<br />

Denne klasse er roden til at hele modellen kan fungere. Uden den her klasse vil mange af de følgende<br />

klasser ikke kunne eksistere. Opskrift-klassen er en simpel klasse der modellere en opskrift på et produkt<br />

som fx drageret lakrids.<br />

Denne klasse kunne dog godt have indeholdt en liste over ingredienser og lignende, men eftersom dette<br />

er et lager system var det kun nødvendigt med en rækkefølge af behandlinger.<br />

Attributter:<br />

navn : String<br />

o Dette er en form for overskrift på opskriften – som fx ”Drageret Lakrids”, som identificere<br />

objektet<br />

count : int<br />

o Denne variabel holder styr på hvor mange portiner der er lavet af den specifikke opskrift<br />

og danner bund for et ID på portion-objekterne der bliver skabt ud fra opskriften<br />

portioner : List<br />

o Dette er en link-attribut som holder styr på alle de portioner som enten stadig er under<br />

behandlig eller som er færdigbehandlede. Spildte portioner bliver fjernet fra denne liste.<br />

behandlingsIndekser : List<br />

o Denne liste er også en link-attribut. Dens opgave er holde objekter af typen<br />

BehandlingsIndeks – som holder styr på de behandliger en opskrift skal igennem og i<br />

hvilken rækkefølge de skal igennem dem.<br />

Metoder:<br />

Opskrift(navn : String)<br />

o Konstruktoren for klassen som opretter et objekt med et specifikt navn<br />

opretPortion() : Portion<br />

o Metode til at oprette et nyt portions-objekt. Denne metode får ingen parametre med da<br />

klassen indeholder nok information til selv at oprette et Portions objekt med de rette<br />

informationer. Dette sikre også at brugeren ikke videregiver forkerte data til metoden. Når<br />

den objektet er blevet oprettet vil det oprettede objekt både blive tilføjet til listen over<br />

portioner samt returneret til brugeren.<br />

fjernPortion()<br />

o Metode til at fjerne et specifikt portions objekt fra listen med opskriftens portioner.<br />

Denne metode vil normalt vis kun blive brugt hvis en portion er blevet for gammel og skal<br />

flyttes til spild.<br />

naesteBehandlingsIndeks(indeks : int) : BehandlingsIndeks<br />

o Når en portion så er færdig med en behandlig og skal videre til den næste behandling i<br />

rækkefølgen af behandlinger bliver denne metode kaldt ud fra portionens nuværende<br />

behandlingsindeks. Det nye BehandlingsIndeks vil derefter blive fundet frem og<br />

returneret. Hvis portionen har været ved den sidste behandling vil der bliver returneret<br />

null.<br />

addBehandlingsIndeks(behandlingsIndeks : BehandlingsIndeks)<br />

o Denne metode tilføjer et BehandlingsIndeks til opskriften. Der skal dog sørges for at<br />

Side 60 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Multiplicitet og association:<br />

behandlingsindeksernes indeks kommer i en kontinuerlig rækkefølge så der startes fra<br />

nummer et og ellers to, tre, og fire osv. Der må bare ikke optræde nogle gaps mellem<br />

dem.<br />

Denne klasse har to associationer til andre klasser. Den ene er hen til klassen BehandlingsIndeks som er en<br />

enkeltrettede association mod den sidstnævnte klasse. Grunden til dette er at en Opskrift kan skal have<br />

mindst et BehandlingsIndeks, ergo mindst en behandling, men kan have flere. Modsat er det ikke<br />

nødvendigt for BehandlingsIndekserne at vide hvilken Opskrift de tilhører da man på den måde kan bruge<br />

dem til andre Opskrift-objekter så længe det giver meningen i deres rækkefølge. Denne multiplicitet bliver<br />

implementeret gennem en liste i Opskrift objektet over BehandlingsIndekser.<br />

Den anden association er over til klassen Portion (beskrevet senere). Denne sammenhæng er af typen<br />

komposition af den grund at en Portion altid skal have en Opskrift tilknyttet, derfor skal den af gode<br />

grunde oprettes igennem en Opskrift. Dette sikre at Portionen får en Opskrift tilknyttet da det kan<br />

videregives ved oprettelsen. Selve multipliciteten er næsten allerede forklaret. En Opskrift kan have<br />

mange portioner på en gangn men en Portion skal have en Opskrift. Selve implementeringen af dette<br />

ligger i bl.a. en liste i Opskrift-klassen samt metoder til at oprette en Portion. Portions-klassens<br />

konstruktor er derfor gjort package-private så det kun er interne klasser i model pakken der kan benytte<br />

den – her tiltænkt Opskrift-klassen.<br />

Side 61 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Portion<br />

Mening med klassen:<br />

Denne klasse er til for at modellere en portion af en opskrift – forstået på den måde at det er når man har<br />

besluttet sig for at der skal laves mere af en type Opskrift oprettes der et objekt af Portions-klassen for at<br />

illustere en nybegyndt omgang af en Opskrift.<br />

Attributter:<br />

vareNr : int<br />

o Dette nummer et ID på hvor i rækkefølgen af oprettede portioner af en specifik opskrift<br />

denne portion er. Dette nummer er videregivet fra Opskrift-objektet som opretter<br />

Portionen.<br />

startTid : Date<br />

o Når en portion bliver oprettet gennem en opskrift bliver der registreret en dato på<br />

hvornår portionen blev startet/oprettet.<br />

slutTid : Date<br />

o Når en portion har været gennem alle behandlinger bliver der registreret en dato for<br />

hvornår portionen blev færdig.<br />

opskrift : Opskrift<br />

o Som beskrevet tidligere er dette en link-attribut til Opskrift-klassen som bliver videregivet<br />

ved oprettelsen af Portions-objektet gennem kaldet til opretPortion.<br />

processer : List<br />

o Liste over de processer (behandlinger) en portion har været igennem indtil nu. Hvis det<br />

sidste element i listen er null er det en indikation på at portionen er færdig.<br />

placering : Placering<br />

o Denne attribut beskriver den placering den specifikke portion har på lageret når den står<br />

og udfører en proces med en behandling af typen Toerring<br />

Metoder:<br />

Portion(opskrift : Opskrift, vareNr : int, behandlingsIndeks : BehandlingsIndeks)<br />

o Klassens konstruktor, package private, som opretter og initialisere de forskellige<br />

attributter klassen har. Her iblandt sætter opskrifts objektet, vareNr samt det første<br />

behandlingsindeks i rækkefølgen af behandlingsindekser<br />

naesteBehandling()<br />

o Denne metode får fat i det næste BehandlingsIndeks fra Opskrift objektet hvor efter den<br />

begynder en ny Proces med den pågældende Behandling som ligger i BehandlingsIndeksobjektet<br />

opretProces(behandling : Behandling) : Proces<br />

o Når et Portions-objekt skal til sin næste behandling skal denne registreres gennem<br />

oprettelsen af et Proces-objekt som holder behandlingen samt status for denne.<br />

getAktuelProces() : Proces<br />

o Når man ønsker at finde ud af hvor en Portion pt. er i hele forløbet kaldes denne metode.<br />

Hvis en portion er færdig vil den returnere null ellers vil den sidste proces i portionens<br />

liste over processer blive returneret.<br />

Multiplicitet og association:<br />

Denne klasse har tre associationer til andre klasser, men eftersom den ene af dem allerede er blevet<br />

beskrevet vil der her blive forklaret de to andre. Den første association er til klassen Placering. Her kan en<br />

Side 62 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

portion enten have nul eller en placering forstået på den måde at enten er Portionen på lageret (optager<br />

en placering) ellers er den til dragering (optager ingen placering). Implementeringen af denne er en simpel<br />

attribut i klassen af typen Placering som kan sættes gennem kald til setPlacering(placering : Placering).<br />

Den anden association er til klassen Proces. Denne association er af typen komposition som gør at Portion<br />

skal stå for oprettelsen af objekter af Proces-klassen. Forholdet mellem Portion og Proces er en til nul til<br />

mange, alene af den grund at en portion har været igennem mange processer. Nogen vil dog mene at en<br />

portion kun burde have en proces, men eftersom vi gerne vil holde styr på hvad en portion har været<br />

igennem og hvornår, er der her valgt at holde multipliciteten som en til nul til mange. Implementeringen<br />

af dette forhold er som i tidligere beskrivelse. Nemlig i form af en liste med processer i Portions-klassen<br />

samt et objekt af typen Portion i Proces-klassen som bliver givet ved oprettelsen af Proces-objekterne.<br />

Side 63 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Proces<br />

Mening med klassen:<br />

Klasse til at modellere en proces, en specifik portion har været igennem på en specifikt tidspunkt. En<br />

proces er derfor noget der bliver oprettet løbende når en Portion er blevet færdig med en foregående<br />

behandling og så skal til en ny.<br />

Attributter:<br />

startTid : Date<br />

o Når en proces bliver oprettet bliver der registreret en tid<br />

slutTid : Date<br />

o Når en proces, dens behandling, er færdig bliver der ligeledes registreret en tid<br />

behandling : Behandling<br />

o Link-attribut som beskriver den behandling en proces skal igennem før den kan erklæres<br />

færdig.<br />

portion : Portion<br />

o Link-attribut som er det objekt, af typen Portion, som har oprettet den specifikke proces.<br />

status : StatusType<br />

o For hver gang beregnStatus() bliver kaldt bliver attributten sat til at være den nye status<br />

processen har – se beskrivelse af enumklasse. Attributten beskriver hvor i behandlingen<br />

en proces er.<br />

StatusType.NOT_DONE – når en behandling ikke er færdig<br />

(behandlingsuafhængig)<br />

StatusType.MINIMUM – når en tørring har opnået minimum tørretid<br />

StatusType.IDEAL – når en tørring har opnået ideal tørretid<br />

StatusType.MAKSIMUM – når en tørring har opnået maksimum tørretid<br />

StatusType.DONE – når en dragering er færdig<br />

StatusType.OLD – når en portion har tørret længere tid end maksimum<br />

Metoder:<br />

Proces(behandling : Behandling, portion : Portion)<br />

o Konstruktoren for klassen. Denne er package-private da denne klasse har et kompositionsforhold<br />

til Portions-klassen. Når denne bliver kaldt bliver den kaldt så den kan oprette en<br />

ny proces for en specifik portion med en specifik behandling.<br />

beregnStatus(currentDate : Date) : StatusType<br />

o Metode til at beregne en eventuel ny status for processen. Denne metode får en dato<br />

med som den bruger til at sammenligne med Proces-objektets startTid. Hvis<br />

beregningerne ud fra currentDate så opfylder kravet for et status-skift bliver statusattributten<br />

sat til den nye beregnede status. Denne vil også blive returneret. Det er<br />

forskelligt hvad kravenen for sådan et skift er, alt afhængig af om det er en behandling af<br />

typen toerring eller dragering.<br />

Multiplicitet og association:<br />

Denne klasse har to associationer, hvor af den ene allerede er blevet forklaret. Der vil nu blive forklaret<br />

den anden. Den anden er en enkeltrettet association til klassen Behandling. For at forklare dette er det<br />

vigtigt af forstå at grunden til at Proces-klassen er i modellen er for at vi kan køre statistik på hvornår de<br />

forskellige processer er startet, sluttet og for hvilke behandling. Derfor er en proces en form for<br />

indpakning af en behandling der gør at vi kan tilføje flere data til en behandling som ikke ville have noget<br />

Side 64 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

direkte med en behandling at gøre. Så en proces har en behandling den holder styr på men behandlingen<br />

kender ikke noget til processen da den er enkeltrettet og kan derfor bruges i mange processer, bl.a. for<br />

andre portioner og opskrifter samt behandlingsindekser.<br />

Side 65 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Placering<br />

Mening med klassen:<br />

Klassen skal repræsentere de placeringer der er på lagergulvet på lageret. De bliver beskrevet ud fra to<br />

koordinater så de nemt kan findes.<br />

Attributter:<br />

x : int<br />

o Koordinat værdien for x-aksen<br />

y : int<br />

o Koordinat værdien for y-aksen<br />

portion : Portion<br />

o Objektet af typen Portion som bliver sat når en portion kommer ind på den specifikke<br />

placering.<br />

Metoder:<br />

Placering(x : int, y : int)<br />

o Klassens konstruktor som opretter et objekt med et koordinatsæt x og y<br />

frigoer()<br />

o Når en portion skal til en dragerings-behandling og lige har stået på lageret bliver denne<br />

metode kaldt som så vil frigive placeringen og sætte portionens placerings-attribut til null<br />

så placerings-objektet kan optages af en ny portion<br />

optag(portion : Portion)<br />

o Når en portion skal have en plads på lageret kaldes denne metode som så både vil sætte<br />

dens egen portions-attribut til at være portionen men også sætte portionens placeringsattribut<br />

til at være den valgte placering.<br />

isFri() : Boolean<br />

o Tjekker om portions-attributten er sat, hvis den er bliver der returneret false ellers true.<br />

Multiplicitet og association:<br />

Denne multiplicitet er allerede forklaret tidligere.<br />

Side 66 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

BehandlingsIndeks<br />

Mening med klassen:<br />

Klasse til at kunne holde styr på i hvilken rækkefølge de forskellige behandlinger skal komme i.<br />

Attributter:<br />

indeks : int<br />

o Nummer som beskriver den placering en behandling har i forhold til andre i opskriftens<br />

behandlingsforløb<br />

behandling : Behandling<br />

o Behandlingen på det specifikke indeks som en portion skal igennem når den kommer til<br />

dette indeks<br />

Metoder:<br />

Indeholder almene get metoder til brug i andre klasser.<br />

Multiplicitet og association:<br />

Denne klasse har to associationer hvoraf den ene er beskrevet tidligere. Den anden association er en<br />

enkeltrettet nul til mange til en til klassen Behandling. Der skal derfor forståes at et behandlingsindeks skal<br />

have en behandling for at kunne eksistere men behandlingen behøver ikke at vide hvilket indeks den ingår<br />

i. Dette gør derfor også at den samme behandling kan indgå i mange forskellige behandlingsindekser.<br />

Side 67 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Behandling<br />

Mening med klassen:<br />

Denne klasse er en abstrakt klasse der gør det muligt at generalisere de to under-klasser som værende<br />

den samme type. Dette er den hovedsagelige grund til at denne klasse er med i systemet. Eftersom de to<br />

under-klasser ikke har noget attribut-mæssigt til fælles er denne klasse tom.<br />

Attributter:<br />

Metoder:<br />

Multiplicitet og association:<br />

Side 68 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Toerring<br />

Mening med klassen:<br />

Denne klasse skal modellere en tørring af en portion ud fra nogle givne attributter der beskriver hvor lang<br />

tid en portion skal være på lager for at opnå en specifik tørre-status.<br />

Hvis en portion står længere end til maksimum tid vil portionen få StatusType.OLD. Dette bliver beregnet,<br />

som beskrevet, i Proces-klassen<br />

Attributter:<br />

minimum : int<br />

o Antal dage en portion skal stå, beregnet ud fra processens startTid, for at få<br />

StatusType.MINIMUM<br />

ideal : int<br />

o Som ved minimum blot får portionen StatusType.IDEAL<br />

maksimum : int<br />

o Som ved minimum blot får portionen StatusType.MAKSIMUM<br />

Metoder:<br />

Multiplicitet og association:<br />

Denne klasse er en sub-klasse til super-klassen Behandling. Grunden til dette er en del af designet, er for<br />

at man kan generellisere mellem de to behandlingstyper, tørring og dragering, så man kan lave en liste<br />

med begge typer behandlinger i, i Proces klassen.<br />

Side 69 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Dragering<br />

Mening med klassen:<br />

Er med i modellen for at modellere en behandling af typen dragering<br />

Attributter:<br />

type : DrageringsType<br />

o Denne attribut er af en enum-type som begrænser hvilke værdi attrubutten får<br />

DrageringsType.FARVE – type en Dragering får hvis portionen skal have et farvelag<br />

på<br />

DrageringsType.SUKKER – type en Dragering får hvis portionen skal have et<br />

sukkerlag på<br />

varighed : int<br />

o Beskriver den varighed det tager, i dage, før at portionen er færdig med den pågældende<br />

dragerings-behandling.<br />

Metoder:<br />

Multiplicitet og association:<br />

Denne klasse er en sub-klasse til super-klassen Behandling. Grunden til dette er en del af designet, er for<br />

at man kan generellisere mellem de to behandlingstyper, tørring og dragering, så man kan lave en liste<br />

med begge typer behandlinger i, i Proces klassen.<br />

Side 70 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

SystemDato<br />

Mening med klassen:<br />

Denne klasse er med for at have et centralt sted objekter i modellen kan hente en dato fra. I samarbejde<br />

med TimeThread gør det det muligt at simunere en eksekvering af systemet så man ikke skal vente en hel<br />

dag på at se om systemet opdatere en proces' status. Grunden til at den ligger i modellen er at hvis den lå<br />

andre stedder vil model-klasserne ikke kunne tilgå den da det vil give et kald op i de fire(tre) lag af<br />

modellen, hvilket ikke er en valid aktion.<br />

Klassen er designet efter singleton-mønstret hvilket betyder at der i hele systemet kun er et objekt af<br />

denne type.<br />

Attributter:<br />

dato : Date<br />

o Denne attribut holder på systemets nuværende dato. Den vil ved initialisering blive sat til<br />

systemets nuværende dato igemmen kald til Date-konstruktoren<br />

Metoder:<br />

Multiplicitet og association:<br />

Denne klasse har ikke et forhold til andre klasser som den har kendskab til. Se beskrivelsen for<br />

TimeThread-klassen for større uddybelse.<br />

Side 71 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

TimeThread<br />

Mening med klassen:<br />

Denne klasse håndtere det at tjekke for om der er gået en dag. Klassen er en udvidelse af java klassen<br />

Thread hvilket gør at den kører sideløbende med resten af programmet. Klassen er opbygget så den har to<br />

tilstande, en til test og en til real-time. Det gør at man kan teste så man siger at for hver gang der er gået<br />

et konstant antal sekunder vil der være 'gået' en dag. Dette gør at når systemet skal testes for fx skift i<br />

portioners statuser skal programmøren der tester det ikke vente en hel dag på at se et skift i status. Den<br />

anden tilstand er den som bliver valgt når systemet skal kører ude på lageret. Her tjekker tråden for om<br />

der er gået en dag, igen, hver gang der er gået et antal sekunder.<br />

I begge tilstande vil der ske det samme når kravene for et dag-skifte er opfyldt, uafhængig af hvilken<br />

tilstand der er tale om. Det der sker er at singleton-objektet af klassen SystemDato bliver sat til en ny dato<br />

og Service klassens metode, checkVareStatus bliver kaldt for at opdatere alle portioners status.<br />

Attributter:<br />

final DELAY : int<br />

o Denne konstant bestemmer hvor ofte der skal ske noget, om det er tjek for ny dag (realtime<br />

mode) eller om det er at der skal inkrementeres en dag. Denne konstant er udtryk for<br />

de millisekunder tråden skal sove før den tjekker igen.<br />

final TEST : boolean<br />

o Konstant til at holde styr på om det er test-mode eller ej. Hvis true den sat til test-mode.<br />

Metoder:<br />

Multiplicitet og association:<br />

Denne klasse har to forhold der er værd at forklare, dette er kort beskrevet i meningen med klassen. Når<br />

kriterierne for et tjek er opfyldt går klassen ind og opdatere datoen på singleton objektet af SystemDato<br />

samt kalder checkVareStatus i singleton objektet i Service. Multipliciteten er lidt triviel at forklare da den<br />

kun kan trække et objekt fra hver klasse da der kun er muligt at oprette et af begge objekter.<br />

Side 72 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Navn:<br />

Service<br />

Mening med klassen:<br />

Klasse som har ansvaret for at oprette objekter samt lagre dem i DAO-en. Det er også denne klasses<br />

ansvar at tjekke alle portioners dato hver gang TimeThread sætter den til det. Denne klasse er som DAO<br />

og SystemDato også designet ud fra singleton-mønstret.<br />

Attributter:<br />

Metoder:<br />

opretOpskrift(navn : String) : Opskrift<br />

o Metode til at oprette og opbevare et Opskrift-objekt ud fra et givent navn.<br />

opretBehandlingsIndeks(indeks : int, behandling : Behandling) : BehandlingsIndeks<br />

o Metode til at oprette og returnere et behandlingsindeks ud fra et indeks og en behandling<br />

opretPlacering(x : int, y : int) : Placering<br />

o Metode til at oprette et Placerings-objekt samt opbevare det.<br />

opretToerring(minimum : int, ideal : int, maksimum : int) : Toerring<br />

o Metode til at oprettet et Toerrings-objekt ud fra givne værdier for forskellige stadier for<br />

tørring. Det er dog et krav at følgende udtryk er overholdt: 0 < minimum < ideal <<br />

maksimum. Dette objekt bliver også opbevaret i DAO-en.<br />

opretDragering(type : DrageringsType, varighed : int) : Dragering<br />

o Metode til at oprette et Dragerings-objekt udfra dens type samt varighed. Dette objet<br />

bliver også opbevaret i DAO-en.<br />

checkVareStatus()<br />

o Denne metode bliver hovedsageligt kaldt af TimeThread som efter et givent tidsrum<br />

kalder den. Derefter tjekker metoden om der er nogle ændringer i de forskellige<br />

portioners status ved at kalde beregnStatus(currentDate : Date) hvor parameteren er<br />

datoen fra SystemDato-klassen. Når disse er tjekket bliver der kaldt en notifyObserver<br />

metode der siger til GUI-en at der er sket ændringer i de forskellige statuser og den skal<br />

derfor opdatere sine grafiske repræsentationer i form af lister.<br />

Multiplicitet og association:<br />

Denne klasse er en af de mere centrale og interessante klasser når man snakker om forhold til andre<br />

klasser. Til at starte med så har den et forhold til SystemDato-singletonklassen. Grunden til dette er at når<br />

TimeThread-klassen tjekker og udfører aktionerne ved et gyldigt tjek er at kalde checkVareStatus som går<br />

ind og sammenligner den nuværende SystemDato dato med de forskellige deadlines som portionerne har.<br />

Derfor skal den kunne hente SystemDato objektet for at hente dens dato og sammenligne ud fra den. Der<br />

udover har den et forhold til DAO-klassen. Da denne klassen fx opretter en Opskrift skal denne også kunne<br />

gemmes efter oprettelsen. Dette gøres ved at hente DAO-singleton-objektet og gemme den i det. Dog<br />

behøver DAO-en ikke kende noget til Service klassen, derfor den givne multiplicitet.<br />

Dernæst har denne klasse en implementering af interfacet Subject. Grunden til dette er for at hvergang<br />

klassen har kørt dens checkVareStatus skal den sende besked til dens observere, som i dette tilfælde er<br />

GUI-en, MainFrame, da denne så skal opdatere dens respektive grafiske lister.<br />

Side 73 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

Design Klasse Diagram<br />

Side 74 af 75


23. april - <strong>2012</strong> Robert Nogal<br />

24. maj - <strong>2012</strong> <strong>Carletti</strong> Projekt <strong>2012</strong> Emil Thygesen<br />

Mads Pedersen<br />

<strong>Carletti</strong> Tidslinje<br />

Historisk tilbageblik fra 1990<br />

1990 – første pc bliver købt<br />

Posepakkemaskine anskaffes til dragé<br />

afdelingen – omsætningen stiger til 109<br />

mio. kroner<br />

1991 – stor ekspansion ved tilkøb af nye<br />

maskiner. 1992 – opkøb af tempereringsmaskiner<br />

fra nedlagte tyske fabrikker.<br />

1992 – køb af affugtningsanlæg til<br />

forbedring af skumprodukter. Salg og<br />

eksport stiger til 125 mio. kroner<br />

1992 – edb-systemet Concorde<br />

anskaffes.<br />

1994 – Jomet-pakkemaskine bliver købt<br />

til pakning af posevarer og p-tærter.<br />

Salget af posevarer fortsætter med at<br />

stige.<br />

Big Ben flyttes til Bentsfors hvorefter<br />

det flyttes til Warszawa et par år senere.<br />

Erling støbeanlægget flyttes ligeledes til<br />

Polen.<br />

1996 – Nordic Candy lukker – opkøber<br />

bøttepakker og SQC-system. Mangel på<br />

tørreplads og udbygning af kontor.<br />

1998 – Pålægschokolade pakningen<br />

bliver fuldautomatisk.<br />

2000 – Fabrik i Mjölby opkøbes.<br />

Fabrikken i Skødstrups pakkesystem<br />

opgraderes og omsætningen dette år steg<br />

til over 400 mio. kroner.<br />

2001 – Mange ældre maskiner bliver<br />

skiftet ud med nyere og Guernsey Bell<br />

bliver opkøbt pga. deres is produkter.<br />

Der bliver satset mere og mere på<br />

produkter der tjenes penge på.<br />

Pladsmangel – udbygning af fabrikken,<br />

hal 4 bliver til, en top moderne<br />

chokoladefabrik<br />

Hal 4 trækker mange ressourcer,<br />

yderligere investeringer bliver udskudt.<br />

1995 – <strong>Carletti</strong> opkøber Brdr.<br />

Christensen. Produktsortimentet<br />

udvides med velindarbejdet varer,<br />

såsom pålægschokolade.<br />

Salgsstyrken vokser og omsætningen<br />

stiger med over 30 mio. kroner. Dog er<br />

der underskud på 5 mio. kroner<br />

1996 – Concorden bliver udvidet med<br />

nye moduler: databasemodul, lønmodul<br />

og edi-modul.<br />

1999 – Brdr. Christensen implementeres<br />

og det ny in<strong>dk</strong>øbte grej køres ind i<br />

produktionen.<br />

2000 – Dansk Chokoladefabrik<br />

indlemmes. En konkurrent mindre.<br />

2001 – AXAPTA bliver implementeret.<br />

Fedt siloen i Skødstrup kan ikke<br />

længere opfylde fabrikkens krav.<br />

2003 – Der bliver satset stort på<br />

pålægschokoladen og det giver pote.<br />

2006 – Bulk-pakker alt pakning tiden<br />

bliver reduceret kraftigt. P-tærte og<br />

skumbananernes 50 års jubilæum.<br />

Side 75 af 75

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!