Afgangsprojekt Datamatiker

2
36506

Det sidste semester på datamatiker uddannelsen er opdelt i en praktikperiode, hvor jeg var i praktik i min egen software-virksomhed. Der er efterfølgende er et afgangsprojekt. .Jeg har valgt at dele rapporten fra mit afgangsprojekt på datamatiker uddannelsen her, så kommende datamatikere kan få noget inspiration til afgangsprojektet. Du kan finde flere afgangsprojekter på datamatiker uddannelsen her.

Dette afgangsprojekt er et gruppeprojekt . Jeg fik 12 for dette afgangsprojekt.

Jeg har fjernet indholdsfortegnelse, kilder, bilag og nogle andre små ting.  Der mangler også nogle diagrammer og code snippets her og der.

Indledning

Affiliate marketing går ud på at markedsfører andre virksomheders produkter og services mod kommission, og det kan fx være i form af en hjemmeside eller en app. Det kan være en yderst lukrativ måde at tjene penge på internettet, da det er passiv indkomst. Det vil sige at du kan tjene penge dag og nat næsten uden røre en finger, når du først har lavet et godt produkt. Der er nemlig ikke er de store omkostninger forbundet med affiliate marketing og mange af arbejdsopgaverne kan automatiseres.Vi vil her vise hvordan man udvikler en prissammenlignings hjemmeside ved hjælp af agile udviklingsmetoder, som promoverer droner hos danske droneforhandlere mod kommission ved hjælp af en web crawler.

Problemformulering

Drone markedet er under stor vækst, hvilket gør at der er store prisændringer, og at der hele tiden kommer nye droner og nye forhandlere på markedet. Hvordan kan en pris aggregator til droner udvikles, som tager højde for at droner markedsføres på mange forskellige hjemmesider og med mange forskellige priser.

Virksomhed

Dette projekt skal ses som et iværksætterprojekt, da vi bruger en enkeltmandsvirksomhed til realisere af projektet. Et webbureau med speciale i affiliate marketing. Virksomheden driver flere forskellige affiliate hjemmesider, som markedsfører andre virksomheder produkter mod kommission.

Afgrænsning

For at afgrænse projektet har vi først beskrevet de forretningsmæssige aspekter i forbindelse med projektet. Det har hjulpet os med at finde frem til et koncept, som giver mening at lave ud fra et virksomhedsmæssigt synspunkt. Efterfølgende har vi så kigget nærmere på hvilke metoder og teknologier, som kan gøre dette koncept til en realitet.

Forretningsmodellen

Produktet i dette projektet er en prissammenlignings hjemmeside, som sammenligner priser på droner fra danske drone forhandlere. Disse prissammenligninger kan forbrugeren af droner bruge til at finde sin nye drone på tværs af forhandlere.

Prissammenlignings hjemmesiden er bygget op omkring en pris aggregator, som henter informationer om produkter, priser og links fra drone forhandlerne. Disse informationer bliver så lagt op på hjemmesiden, så forbrugeren har reelle informationer at gå ud fra, da de passer med de forskellige drone forhandlere.

Der findes mange prissammenlignings hjemmesider på internettet i forvejen, men mange af disse løsninger kan ikke håndtere de hyppige produkt og prisændringer, da de ikke er automatiseret. Her skal de selv ind og ændre priserne og produkterne, og det kræver meget manuelt arbejde, især hvis man sammenligner mange produkter hos mange forhandlere. En pris aggregator automatiserer disse arbejdsopgaver, og det gør at vi ikke skal bruge så meget tid på manuelt arbejde på længere sigt. Det giver os mere tid til at skaffe flere kunder og udvide med flere produkter, og det giver os en stor konkurrencemæssige fordel i forhold til vores konkurrenter.

Vores prissammenlignings hjemmeside er gratis for forbrugeren at bruge, men vi får så kommission pr salg, som vi kan skaffe ved de enkelte forhandlere. Vi har placeret en tracking cookie i de knapper, som sender forbrugeren videre til forhandleren. Disse tracking cookies har en levetid på 30-60 dage, som så registrerer om salgene kommer fra vores hjemmesiden.

Vi kan tage et eksempel, hvor en kunde går ind på vores hjemmeside, og trykker sig videre ind på fx. dronebutikken.dk. Her bliver der så gemt en cookie. Kunden køber så en DJI Phantom 3 Advanced drone til 9.695 kr inkl. moms hos dronebutikken.dk. Det bliver så registreret i det affiliate netværk vi er tilmeldt, da der er en cookie på kunden. Her får vi så 7% af det salg i kommission uden moms ind på vores konto hos det pågældende affiliate netværk drone forhandleren er registreret ved. Kommissionen bliver så udbetalt en gang om måneden, hvor der så bliver pålagt moms, da virksomheden er momsregistreret. Der kan selvfølgelig ske dette, at kunden fortryder købet, og så bliver kommissionen selvfølgelig annulleret, hvis kommissionen ikke er blevet udbetalt.

Eksempel på udregning af kommission

9.695 kr * 0,8 * 0,07 = 542.95 kr uden moms i kommission. Vi får så udbetalt 542.95* 1.25 = 678.68 kr med moms.

Vi vil tjene pengene på helt basal affiliate marketing, da denne forretningsmodel passer rigtig godt sammen med vores produkt. Der er selvfølgelig noget arbejde, som skal laves på forhånd, før at sådan en forretning begynder at tjene gode penge. Når det hele først er kommet godt op at kører, kan vi i princippet lade hjemmeside stå for sig selv uden den store vedligeholdelse. Vi har tænkt automatisering ind fra start, og det er med til at formindske vedligeholdelse af produktet på længere sigt. I takt med at forretningen vokser sig større, kan vi hele tiden udvide med nye indtjenings kanaler. Det kan fx være en e-bog om droner, som vi sælger gennem hjemmesiden.

Markedsføring

Markedsføring er vigtigt for at få en prissammenlignings hjemmeside til at tjene penge. Hvis der ikke kommer noget trafik til hjemmesiden, er der ikke nogle kunder til at købe produkterne. Vi har valgt ikke at smide pengene i projektet til at starte med, og vi har derfor ikke penge til markedsføring i starten.

Vi vil derimod bruge en masse energi på godt indhold til hjemmesiden og søgemaskineoptimering. Det vil på sigt give os gode placeringer på søgemaskinen google, som er den mest brugte søgemaskine i Danmark. Vi har begge store erfaringer med søgemaskineoptimering, og det er også grunden til at vi lægger så stor vægt på denne strategi. Sociale medier er også et godt redskab til at drive trafik med, og vi vil derfor også være synlige på de sociale medier med profiler til dronepris.dk. Email marketing er også meget effektivt, og vi vil derfor gøre det muligt for de besøgende at skrive sig op til et nyhedsbrev.

Alt vores indhold bliver lavet ud fra udvalgte søgeord, som kunderne søger på, når de er på udkig efter en ny drone. Til at udvælge vores søgeord har vi brugt google keywords tool, som er et værktøj søgemaskinen Google stiller til rådighed. Her kan vi se hvor mange gange, der bliver søgt på forskellige ord og sætninger. Derudover har vi lavet analyse af de forskellige drone forhandlere, hvor vi har kigget efter hvilke søgeord de optimerer deres webshop efter. Det kan vi så bruge til at optimere vores egen hjemmeside med.

Indholdet vi laver skal helst give stor værdi til kunden, da det øger sandsynligheden for at kunden deler indholdet på de sociale medier eller sin egen hjemmeside. Hvis indholdet bliver delt på de sociale medier, kan det hurtigt skabe en masse trafik, da rigtig mange bruger sociale medier i dag.

Hvis indholdet bliver delt på en hjemmeside, kan det også skabe trafik på længere sigt. Vi får det første et link, som kan være med til at give os bedre placering i google. Især hvis indholdet bliver delt på en af de store kendte hjemmesider(DR1.dk, Tv2.dk, Bt.dk). Disse hjemmesider har rigtig mange besøgende, og de har mange hjemmesider som linker/peger på deres hjemmeside. De har kort sagt en høj autoritet, og et link fra disse hjemmesider, kan få en ny hjemmeside til at rangerer højt i google på kort tid, da de videregiver meget autoritet igennem deres link. Det er svært at få et link fra disse store medier til at starte med. Det er langt nemmere at starte ud med de mindre hjemmesider, og det også det vi vil holde os til i starten. Små bække gør stor sø. Søgemaskineoptimering er et lidt mere komplekst emne end som så, og det er derfor ikke noget vi vil dykke yderligere ind i.

Kunderne

Størstedelen af de droner som vi sammenligner priser på er hobby droner. Hobby Droner er droner som bruges på hobbyplan. Det kan fx være i weekenden, hvor man lige flyver en tur med sin drone. Det skal siges at de fleste droner gør det muligt at filme og tage billeder fra luften, og det er også en af grundene til at så mange køber en drone. Så man kan fx tage et billede af sin ejendom eller af naturen.

For at kunne lave alle disse ting med droner, kræver det alligevel lidt teknisk snilde, da der typisk medfølger apps, software, fjernbetjening, kameraer osv til droner. Mænd og teknik passer godt sammen, og det er også grunden til at vores primærer kunder er mænd i alderen 20-50 år.

Drone Branchens udviklingsmuligheder

Her ser du en graf for interessen for ordet drone over tid. Grafen er genereret ud fra Google Trends, som er et værktøj Google stiller til rådighed, som kan måle interesse af søgetermer. Denne måling af interesse kan bruges til at finde frem til de trends, som der er i verden. Det er tydeligt at se at droner har været i en opadgående trends de seneste år. Droner er gået fra at være noget kun militæret brugte i krig til næsten hvermandseje. Det er også en af grundene til at vi har valgt at lave dette projekt i denne niche. Vi er selvfølgelig ikke first movers på denne front, men drone nichen er ikke særlig konkurrencepræget i Danmark endnu. Vores hjemmeside vil få en klar fordel i forhold til nye konkurrenter, da vi allerede er ved at etablerer os i markedet.

Vi spår at drone branchen vil vækste yderligere, da der er så stort et potentiale i droner på mange fronter. I og med at computerkraft bliver billigere og billigere, vil også se mere avancerede og mere billige droner i fremtiden. Der er fx mange store firmaer, som arbejder på droner, der kan leverer varer ud. Brandvæsenet og Politiet er også så småt begyndt at bruge droner. Det er især på hobbyplan, at droner er meget populære. Personer der bruger droner på hobbyplan er vores største målgruppe, da det er der droner primært bruges den dag i dag.

Metodevalg

Da vi har konceptet på plads, har vi brug for finde frem til hvilken udviklingsmetode vi vil anvende i projektet. Grunden til at vi anvender en udviklingsmetode, er for at udvikle så effektivt som muligt, så vi kan minimere risikoen for at projektet går galt. Boehm’s projektkort  er et godt teoretisk værktøj, som hjælper med at give struktur på valg af udviklingsmetoder. Det har vi brugt til at argumentere for og imod, hvilke udviklingsmetoder der vil passe os bedst i forbindelse med projektet. Vi har valgt at udvikle efter agile udviklingsmetoder, da det har passet bedst til vores behov.

Boehm’s projektkort

Boehm’s projektkort består af en cirkel med 5 forskellige punkter, som vi gennemgår for at finde frem til, om vi skal arbejde agilt eller plandrevent i forbindelse med projektet.

Personnel

Personnel hjælper med at finde frem til levels(niveauet) på de udviklere, som skal arbejde på projektet. Det er vigtigt at tage stilling til, da udviklingsmetoderne helst skal passe til niveauet på udviklerne. Agile udviklingsmetoder er fx typisk i små teams, hvor der er et højt niveau, meget chaos og en høj dynamik. Det kræver helt grundlæggende dygtige udviklerer, så er derfor vigtige at finde frem til om man har dygtige udviklere til rådighed, hvis man fx ønsker at arbejde agilt. En dygtig og erfaren udvikler kan fx nemmere udvikle i dynamik og chaos, da de har en vis erfaring. En uerfaren udvikler vil ligeledes havde svært ved at udvikle i et miljø med meget dynamik og chaos, da de ikke har så meget erfaring som udvikler.

For at kunne finde frem til vores eget level, har vi lavet en tabel med flere forskellige levels, som har hvert sit karakteristikas. Her har vi så kigget på vores egen erfaring i forhold til disse karakteristikas.

Vi er 2 udviklere i alt på dette projekt, som er på sidste semester af datamatikeruddannelsen. Vi har fået uddannelse og træning på datamatikeruddannelsen de seneste 2.5 år, hvor vi har udviklet efter både plandrevne(vandfaldsmodellen, UP) og agile(SCRUM, XP) udviklingsmetoder. Derudover har vi været i virksomhedspraktik, hvor vi har arbejdet med metoder i erhvervsregi. Vi har prøvet en del som udviklere efterhånden, og vi har derfor vurderet at vi starter på Level 2 i dette projekt. Vi har et niveau, som ligger nærmere midten af cirklen. I teorien har vi et højt nok niveau til at kunne arbejde efter en agil udviklingsmetode.

Level Karakteristikas
3 Personen kan bryde metoderne helt, så de passer til en ny situation.
2 Personen kan skræddersy metoderne så de passer til en ny given situation. Personen kan tilrettelægge plandrevne eller agile udviklingsmetoder.
1A Personen kan efter træning følge avancerede metodiske steps. Personen kan med erfaring blive level 2.
1B Personen kan følge de helt simple metodiske steps.

Personen kan med erfaring blive level 1A.

-1 Personen har tekniske færdigheder, men har ikke viden nok til at følge de simple metodiske steps.

Dynamism

Dynamism kigger nærmere på hvor dynamisk projektet er og i hvor høj en grad der er brug for dynamik. Her kan man kigge på hvor mange ændringer der opstår i løbet af en måned. Hvis der opstå mange ændringer ligger projektet langt inde i cirklen. Hvis der er få ændringer ligger projektet langt ude i cirklen. Vores projekt er i internetbranchen, og det er en branche, som er præget af høj dynamik på mange punkter. Der kommer hele tiden nye konkurrenter og nye teknologier, som gør at man hele tiden skal være omstillingsparat. Google fx opdaterer med jævne mellemrum deres søgemaskine algoritme, og der kommer hele tiden nye smarte apps på de sociale medier. Der er hele tiden nye ting at skulle tage stilling, og det giver en høj dynamik til vores projekt. Vores projekt ligger derfor langt inde i cirklen, da vi hele tiden kan lave nye ændringer. Vi har brug for en udviklingsmetode, som gør det muligt at lave mange hyppige ændringer, og her ville en agil udviklingsmetode passe os godt.

Culture

Culture kigger nærmere på kultur, da det også har en betydning for, hvilken udviklingsmetode man bør vælge. Det er forskelligt hvilken kulturel baggrund man har som person. Er størstedelen af udviklerne personer med vestlige værdier, eller er det udviklere som kommer fra Asien, som har nogle helt andre værdier. Det er derfor meget forskelligt, hvordan personer trives i et arbejdsmiljø. Nogle personer har fx brug for meget orden, hvor der er nogle faste rammer, som man kan arbejde ud fra. Her kunne det være oplagt at anvende en plandreven udviklingsmetode. Så er der andre, som har brug for mere frihed, hvor man kan tage sin egne beslutninger. Her kunne det være oplagt at bruge en agil udviklingsmetode.

I vores projekt er vi 2 personer, hvor vi begge kommer fra Danmark. Vi har arbejdet sammen i tidligere projekter og i praktikperioden. I praktikperioden var vi begge i praktik i et nystartet webbureau, hvor der er meget kaos, da vi arbejdede på mange forskellige hjemmesider projekter. Vi har vurderet at vi ligger langt inde i cirklen kulturelt, da vi kender hinanden godt, og at vi har arbejdet på iværksætterprojekter, hvor der meget kaos.

Size

Boehm’s projektkort går også i dybden med størrelsen af projektet, hvor man kigger på hvor mange udviklere, som der er på projektet. Store projekter med store teams kræver fx en stor mængde koordinering og dokumentation af arbejdet, da der er mange personer, som arbejder på projektet samtidig. Små teams er lige modsat, da de ikke kræver så koordinering og dokumentation. Her kan man arbejde hurtigt og effektivt, da der er få personer på opgaven. I vores tilfælde er vi et lille team på 2 udviklere, og vi ligger derfor tæt på midten i cirklen. Det bakker igen op om påstanden, at en agil udviklingsmetode ville passe godt til vores projekt.

Criticality

Criticality tager stilling til, hvor kritisk softwaren er i projektet. I hvor høj en grad må der opstå fejl i softwaren. Det har stor betydning for hvordan der skal udvikles. Hospital software skal fx være meget sikkert, hvis det har med mennesker at gøre, da en fejl kan koste et menneskeliv. Bank software skal fx også være meget sikkert, da en lille fejl kan resultere i flere fejl i tusinde af transaktioner, som så resulterer i et stort økonomisk tab, da disse fejl skal rettes. Det er 2 eksempler på software, hvor der ikke må opstå fejl. Her ville en plandreven udviklingsmetode være vejen frem, da den giver struktur og en høj grad af dokumentation, og det forebygger fejl. Det kan ses på cirklen under Criticality, hvor Many lives(mange liv på spil) ligger langt ude i kanten af cirklen.

Vi arbejder i vores projekt med et helt nyt hjemmeside projekt, og her der ikke nogle menneskeliv eller store økonomiske tab på spil. Det gør at projektet ligger langt inde i cirklen, da der er en høj komfort. Fejl i vores software kan dog resultere i en lavere konverteringsrate, hvis priserne på hjemmesiden fx ikke passer med drone forhandlernes produkter. Disse fejl kan hurtigt opdages ved brug af google analytics, som kan tracke brugsmønstret på hjemmesiden. Så er der det med at danskerne generelt er gode digitalt, og man får derfor en masse feedback på internettet, hvis der er noget der ikke virker. Vi har derfor vurderet at den agile tilgang ville passe fint til vores projekt, da vi ikke har behov for en høj grad af forebyggelse af fejl.

Teori

Vi har i forbindelse med projektet valgt at arbejde agilt, hvor vi vil anvende praktikker fra XP og SCRUM. Det har vi valgt at gøre, da vi arbejder på et internet projekt, hvor der nemt kan komme nye ændringer i forhold til vores krav. Vi vil gerne holde os så adaptive som muligt, så vi hurtigt kan reagerer på nye problemstillinger, og så undgår vi også en masse ekstraarbejde i forbindelse med ændringer i dokumentation og planer.

XP

Ved at arbejde med XP (Extreme programming) arbejder man med en masse praktikker. Da vi kun er to i gruppen, har vi valgt kun at følge nogle af praktikkerne i xp, da xp normalt er designet til større gruppe (seks personer). Vi har valgt at bruge følgende xp Praktikker:

Kode standard: Dette betyder at man følger en række regler, som man skal overholde under udviklingen. Vi brugte fx Google’s pyton standard og Microsoft’s mvc standard som kode standard.

Kollektiv kode ejerskab: Her skal alle i gruppen ses som ejer af hele projektet samt altid have adgang til den nyeste version.

Fortsat integration: Betyder at folk altid skal bruge den nyeste version af projektet. Når en udvikler har laver en ting færdig, skal han ”commit” det, så de andre også kommer til at have den nyeste version.

Bæredygtigt tempo: Her skal man sørge for at folk ikke arbejder alt for mange timer om ugen. Det skal være en fornuftig grænse, så folk ikke får stress eller brænder ud. Standard xp siger at en udvikler aldrig må arbejde mere end 40 timer om ugen, dette er inklusiv møder osv. Vi har overholdt dette ved at arbejde syv timer dagligt mandag til torsdag, hvor vi så har retrospektive og planlægning af den kommende uge om fredagen.

Iteration planlægning: Er at man udregner holdets hastighed, hvor mange story points man kan lave på et sprint.

Sortering af værdi: Her finder man ud af hvad for nogle opgaver, som er vigtigst. Her giver man opgaverne en af tre kategorier: Kritisk, betydningsfuld eller lækker. Vi har dog bare valgt en rækkefølge, hvor vi udvikler det mest værdifulde først.

Scrum

Scrum er en agil software udviklings metode, som bruges af hold på ca. seks personer til at opnå et fælles mål på en fleksibel måde. De agile miljøer bruges for at bekæmpe eller undgå at komme ud i de mere traditionelle sekvens methode som Unified process eller vandfaldsmodellen. Det gode ved at bruge de agile metoder er at et hold selv kan organiserer sig, ved at finde deres eget sted at mødes. Vi har fx i dette projekt typisk arbejdet hjemme ved os selv, hvor vi har kommunikere over skype.

Et af hovedprincipperne ved scrum er at kunden kan ændre sine krav til projektet, mens man er i gang uden at det har de store konsekvenser. Hvis man derimod havde brugt en mere traditionel metode som v-modellen, kan dette næsten være umuligt, da det medfører at projektet kommer til at tage meget længere tid. Grunden til at scrum kan ændre i udvikling midtvejs er at den bruger imperial fremgang og accepterer at det problem ikke kan fuldt ud forståes, og fokuserer i stedet på at maximere holdets evne til at levere hurtigt og evnen til at adoptere nye krav.

Sprints

Når man bruger scrum, arbejder man i sprints. Sprints varer som regel en uge til en måned. Vi har valgt at lave vores sprints, så de varer en uge ad gangen. Vi arbejder fra mandag til torsdag, også holder vi retrospektive og planlægning af den kommende uge om fredagen.

Spikes

Hvis holdet har en opgave, som indeholder ny teknologi som de ikke er bekendt med, så sættes tid af i backloggen til at der kan spike. Dette betyder at holdet kan gå ind og undersøge hvordan de arbejder med det nye teknologi. Vi har fx lavet spikes i dette projekt, hvor vi har undersøgt hvordan vi bruger python og mvc.

Daily Scrum

En af de metoder i scrum som vi har brugt meget, er daily Scrum. Det er et kort møde, som vi har afholder hver morgen inden vi er går i gang med dagens arbejde. Her snakker vi om, hvad vi hver især har lavet dagen før, hvad vi har lave i løbet af dag og om der har været nogle problemer eller overraskelser. Det hjælper os med at holde styr på hvor langt vi er, og hvor langt vi har igen. Vi ved derfor hele tiden hvad hinanden laver, og det gør fx at vi ikke sidder og arbejde på de samme arbejde. Da vi kun er to personer, har vi ikke haft en ordfører til møderne, da vi fint har kunne holde styr på dialogen.

Product Backlog

En product backlog er en to do liste, man laver til hvert sprint. Herinde skrives alle de ting, man skal vide omkring sprintet. Vores product backlog indeholder følgende:

  • Navnet på opgaverne.
  • En beskrivelse på opgaverne.
  • Hvor vigtige de er.
  • Hvor lang tid det forventes opgaven tager.
  • Hvordan opgaverne testes
  • Vi har valgt at lave en note felt, hvor vi lige kan skrive en note til opgaverne.

Vi har i vores projekt tilføjet et udsnit af vores product backlog i starten af hver sprint, så man kan få et indblik i hvilke opgaver vi har arbejdet på. Vi har dog mest brugt udvidet product backlog til at holde helt styr på alle opgaverne.

Udvidet product backlog

Vi har lavet en udvidet product backlog, som kan findes i vores bilag. En udvidet produkt backlog er en udvidet udgave af product backloggen, som indeholder nogle flere informationer:

  • Navnet på item
  • Hvor mange story points de er på,
  • Hvilke task(opgaver) der er forbindelse med den item
  • Navnet på ejeren af de task der er.
  • Hvor mange story points de enkelte task er på.
  • Hvor mange story points der blev brugt på de enkelte task.

Retrospektive

Vi har afholdt retrospektive i forbindelse med hver sprint, hvor vi har evalueret vores arbejde og diskuteret om vi kan forbedre den måde vi arbejder på. Vi har helt konkret kigget på hvad der har været godt, og hvad der har været skidt i sprinten. På den måde har vi så kunne finde frem til hvad vi skal gøre bedre til næste sprint.

Burndown

Burndown er en måde man viser, om man overholder sin tidsplan. Dette vises typisk ved at man har et diagram, som viser hvor mange story points samt hvor mange dage der er i sprinten. På et burndown diagram tegner man så en graf som viser hvor man points, man laver hverdag. Hvis ens planlægning holder vil ens graf altid gå i nul på diagrammet efter den sidste arbejdsdag. Her er der et eksempel på en burndown diagram.

Hvis holdet bliver færdig med sprinten for tidligt, er det mulig at insætte flere tasks. Det vises ved at man tegner en lige steg op på ens graf for at indikere, at der nu er kommet flere story points ind. Omvendt kan der også tages ting ud, hvis der ikke er nok tid til alle opgaverne, dette vises ved at man tegner en lige streg ned for at indikere at der er blevet fjernet points.

Sprint 0

For at komme godt i gang med projektet har vi valgt at bruge sprint 0 til at planlægge, så vi kan få styr flere forskellige ting. Vi har især brugt en del tid på at prioritere og estimering, så vi kan nedbringe risikoen for at projektet går galt. Her har vi fx kigget på arbejdstider og hvilke teknologier vi vil anvende. Det giver os en godt fundament, som vi kan arbejde videre på i sprint 1.

Prioritering og estimering

Når man arbejder på et projekt, er det vigtigt at prioritere og estimere, så vi kan finde frem til hvad der er vigtigst, og hvor lang tid det tager at lave. Vi har planer om at arbejde 4 dage i hver sprint, hvor vi så bruger den sidste 1 dag på retrospektive og planlægning af næste sprint. En sprint varer 5 dage i alt.

Mandetid

Noget af det første vi har kigget på, er vores arbejdstid i forbindelse med projektet. Her har vi valgt at programmere hver for sig. Vi er 2 personer i gruppen, og det svarer til 2 par i alt. Her vil vi arbejde fra 8.00-15.00 mandag-torsdag. Vi har valgt at holde små pauser i løbet af dagen, hvor vi har en stor middags pause midt på dagen. Det giver os muligheden for at arbejde i små etaper med pause. Vi har gode erfaringer med arbejde på denne måde, da det hjælper os med at holde produktivitet høj, så vi fx ikke bare arbejder ud i en lang smøre.

Vi er kommet frem til en mandetid på 5 timers arbejde om dagen pr person, og her er pauser, møder, sygdom skåret fra. Vi har 10 mandetimer til rådighed pr dag, og det bliver til 40 mandetimer pr sprint.

Velocity

For at kunne finde frem til hvor mange stort points vi kan lave, har vi har testet hvor mange mandetimer det tager at udvikle en story på 5 story point. Det tog 10 mandetimer at udvikle 5 story points. Vi er kommet frem til at vi kan lave 2.5 story points om dagen per mand. Det giver os en total på 20 story points per uge. Fredag er som sagt ikke regnet med, da vi bruger fredagen til planlægning af det kommende sprint og til retrospective.

Krav

Krav er vigtige, da de hjælper med at danne et godt grundlag for projektet. Hvad skal softwaren/systemet kunne og hvad det ikke skal kunne. Krav hjælper os med at finde frem til hvad der laves, samtidig med at kan vi afgrænse projektet, så vi tager de ting fra, som ikke skal laves.

Funktionelle krav

De funktionelle krav er de mekaniske krav dvs. at det som programmet kan er et funktionelt krav. Her er en liste over de funktionelle krav, som vi holder os til:

  • Skal kunne hente data fra dvs. webshops.
  • Skal kunne liste data fra dvs. webshops.
  • Man skal kunne søge efter dvs. parameter.
  • (Systemet skal kunne gemme data om droner.)

Ikke funktionelle krav

Et ikke funktionelt krav er for at begrænse løsning formålet ved fx at sige programmet skal have en vis performance eller en godt brugervenlighed. Her er en liste over de ikke funktionelle krav vi holder os til:

  • Vi skal hente priser fra mindst 2 drone forhandlere.
  • Priser må maks være 24 timer gamle.

Arkitektur

Vi bruger mvc arkitekturen, som indeholder tre lag M (Model), V (View) og C (Controller). Model laget indeholder data og kun data og er derfor uafhængig af View’et og Controllern. View laget viser alt det grafiske og sender bruger aktioner ned i Controlleren (fx via et klik på en knap). Et View kan faktisk godt bruges som Controller som sender direkte til Modelen, det er dog ikke anbefalet.

Control laget Sender dataen fra Model laget til Viewsne og finder ud af hvad der skal ske når fx en bruger klikker på en knap.

Risikoanalyse

Vi har at lave en risikoanalyse, som vi har udarbejdet en risikoanalyse i form af en tabel. Det har hjulpet os med at finde frem til de risici, som kan opstå i forbindelse med dette projekt. Hvis vi kender vores risici, ved vi nogenlunde hvilke problemer der er ude i fremtiden, og så kan vi på den måde tage højde for eventuelle tidstab og uheld. Vi skal helst arbejde så stabilt og sikkert som muligt, så vi kommer i mål med dette projekt.

Tabellen er opdelt i 5 kolonner. Den første kolonne i tabellen er navnet på risikoen. Anden kolonne er sandsynligheden i procent for at en risiko forekommer. Tredje kolonne viser hvor stort et tidstab det resulterer i. Fjerde kolonne viser det samlede tidstab i forhold til sandsynligheden at risikoen forekommer. Femte kolonne viser en beskrivelse af risikoen.

Risiko Sandsynlighed Tidstab Eksponering Beskrivelse
Python 100% 3 dage 3 dage Vi har ikke arbejdet ret meget med Python, så der vil højst sandsynligt komme nogle tekniske problemer
MVC 100% 3 dage 3 dage Vi har ikke arbejdet ret meget med mvc, så der vil højst sandsynligt komme nogle tekniske problemer
Git 50% 3 timer 1,5 timer Der kan godt opstå konflikter, når vi bruger versionsstyring, og det er værd at tage højde for.
Netværk 20% 30 minutter 6 minutter Problemer med netværk som kommer og går en gang imellem
Sygdom 80% 1 dag 0,8 dag Vi har også valgt at tage sygdom med i risikoanalysen, da vi arbejder på projektet i de vintermånederne, hvor der godt kan forekomme sygdom

Python og MVC er 2 teknologier, som vi ikke har så meget kendskab til, da vi ikke har arbejdet så meget med det før. Vi har derfor vurderet at der med 100% sandsynlighed vil opstå nogle tekniske problemer. Der er især problemer i starten, når man lærer nye teknologier, og det indebærer en risiko for tidstab. Vi har efterhånden prøvet en del gange at lære nye teknologier, så vi forventer ikke at disse 2 teknologier vil volde os store problemer. Det er mere de små tekniske problemer som opsætning og syntax fejl.

Vi bruger github som versionsstyring, og det har vi begge erfaringer med at bruge. Der kan stadig dog opstå konflikter, da vi arbejder meget med web, hvor mange filer bliver ændret hyppigt. Netværksproblemer kan også opstå, da vi har planer om at arbejde hjemmefra den største del af tiden, hvor vi kommunikerer over skype. Hvis nettet ryger hos en af os, kan vi fx ikke snakke sammen, og det kan resultere i tidstab. Vi har også valgt at tage højde for sygdom, da vi arbejder på projektet i vintermånederne. Her er der koldt, og det øger risikoen for sygdom. Det er også værd at få med i risikoanalysen.

Teknologi

Dette afsnit går i dybden med at vores valg af teknologier, hvor vi beskriver teknologierne og hvorfor vi har valgt dem.

Python

Virksomheden har før hjulpet kunder med programmering i python. Vi fandt det naturligt at bruge programmeringssproget python i forbindelse med udvikling af vores price aggregator. Det er fordi at vores web crawler framework, er baseret på python.

Python er et “general purpose” programmeringssprog, hvilket vil sige at python kan bruges til at lave software i mange forskellige applikationer.  For at man kan bruge Python, kræver det at man har installeret python. Her har vi brugt version 2.7, da det er den mest almindelige version at udvikle i, og så at web crawler frameworket scrapy er baseret på version 2.7.

Pycharm

Vi har brugt python udviklingsmiljøet Pycharm, når vi har programmeret i python. Det har gjort, at vi nemt har kunnet hente eksterne biblioteker til python, og vi har haft intellisense, når vi har programmeret i python.

Console

Under dette projekt har vi brugt en del python console. Det har været i forbindelse med scrapy, når vi har kørt web crawleren. For at man kan bruge den på en windows maskine, bliver man nødt til at lave pathing til python i ens Environment Variables. Dette gøres ved at man går ind i ens Environment Variables, hvor man finder stien til hvor python er installeret (typisk “C:\python27\python.exe”).

MVC

Vi har brugt frameworket MVC til asp.net, som står for Model View Controller til at udvikle vores hjemmeside. Vi har valgt at bruge dette fordi det er det nyeste og mest aktuelle form for udvikling i asp.net universet. Her har vi brugt visual studio som udviklingsmiljø.

Github

Vi har valgt at bruge Github til versionsstyring i forbindelse med alt vores programmering. Der er Github extensions til både Pycharm og Visual Studio, som gør det nemt at implementere og bruge Github versionsstyring. Vi har to repositories på github. Et til vores prissammenlings hjemmeside og et til webcrawler scriptet.

Scrapy

I forbindelse med web crawler har vi brugt et python web crawling framework, som hedder scrapy. Det indeholder en en masse web crawling funktionalitet, som vi vil bruge i forbindelse med dette projekt. Vi vil så bygge videre på denne funktionalitet, så det passer til vores behov. Det synes gav mest meniFng fremfor at bygge et web crawling framework helt fra bunden. På den måde kan vi hurtigere få en simpel prototype på benene, som vi så kan arbejde videre med.

Scrapy består af mange små komponenter som hjælper hinanden, så scrapy fx kan scrape data fra internettet. Her vil vi kort gennemgå de forskellige komponenter, som får scrapy til at virke. Der er et diagram af scrapy’s arkitektur længere nede, hvor vi også har beskrevet data flowet i scrapy. Her har vi gennemgået hvad skal der sker med scrapy webcrawleren fra start til slut, når den crawler på internettet.

Scrapy Engine

Scrapy Engine er det centrale komponent, som står for kontrol af data flowet, som der er mellem de forskellige komponenter.

Scheduler

Scheduleren får anmodninger fra Scrapy Enginen, hvor scheduleren så sætter disse anmodninger i kø.

Downloader

Downloaderen henter alt dataen fra internettet, som så bliver sendt videre Scrapy Engine.

Spiders

Spiders står for at udtrække dataen, som downloaderen har hentet fra internettet. Spiders udtrækker det data som skal bruges, som så bliver sendt videre til Item Pipeline.

Item Pipeline

Item Pipeline renser, validerer og gemmer dataen til en fil eller database. Vi har fx lavet et ord filter, som fjerner bestemte droner, som bliver crawlet.

Data flow i Scrapy

Her er der en gennemgang af data flowet i scrapy, som beskriver hvad scrapy gør i steps, når den crawler på internettet.

  1. Scrapy Engine åbner et domæne, og finder den spider, som håndterer det udvalgte domæne. Scrapy Enginen spørger så spideren om den første url som skal crawles.
  2. Scrapy Engine sender den første url videre til Scheduleren, som sætter urlen i kø.
  3. Scrapy Enginen spørger Scheduler om den næste url som skal crawles.
  4. Scheduleren sender den url som står forest i køen til Scrapy Engine, som så sender bliver sendt til downloaderen.
  5. Downloaderen downloader dataen fra hjemmesiden, og denne data bliver så sendt til Scrapy Engine.
  6. Scrapy Engine sender dataen fra downloaderen til den spideren, som passer med url’en som downloaderen har data fra.
  7. Spideren udplukker det data som skal bruges, som så bliver sendt til tilbage til Scrapy Enginen.
  8. Scrapy Enginen sender det udplukkede data videre til item pipelinen og Scheduleren får besked om at den første url nu har været igennem system.
  9. Denne process fortsætter indtil der ikke er flere url som venter i scheduleren.

Kvalitetssikring

Når man arbejder på et IT projekt, er det en god skik at forebygge fejl og defekter så meget som muligt. Det koster tid og penge at rette fejl i software, og denne pris stiger desto længere hen man kommer, da kompleksiteten i software typisk stiger. Kompleksiteten stiger fordi der kommer flere features og flere linjer kode. Det er vigtigt at man kommer godt fra start, og her har vi brugt flere forskellige metoder og principper, så vi kan holde en høj kvalitet i vores udvikling af software.

Versionsstyring

Vi har valgt at bruge Github til at holde vores styr på vores udgivelser. Dette har vi gjort pga. det er en de mest brugte version styringssystemer der findes. Google tilbyder ikke længere deres repository service Google Code, så blev vi nødt til at finde et alternativ.

Test af kode

Vi har brugt en del tid i sprint 2 på at undersøge test først i forbindelse med mvc, men vi vurderede at det ville være for tidskrævende at implementere i dette projekt. Vi har i stedet valgt at fokusere mere på implementering af funktionalitet. Da vi ikke bruger test først, har vi brugt ekstra tid på manuelle test og debuggingen for at mindske fejl i koden.

Kodestandard

Vi har valgt at bruge Googles python kodestandard, den kan findes her:

https://google.github.io/styleguide/pyguide.html

Til mvc delen har vi valgt at bruge Msdn’s egen ”Best Practices for ASP.NET MVC” Den kan findes her:

http://blogs.msdn.com/b/aspnetue/archive/2010/09/17/second_2d00_post.aspx

Sprint 1

Målet for sprinten

Vi fik så styr på alt planlægningen i sprint 0, og var vi nu klar til at gå i gang med det reelle arbejde i sprint 1. Her var målet for sprint 1 at få lavet en simpel prototype af vores software, så vi kunne få vores koncept på benene hurtigst muligt. Her skulle den første del af vores web crawler scriptet laves, så web crawleren kunne scrape data fra en drone forhandler, som så efterfølgende kunne blive gemt. Dataen fra crawleren skulle så udskrives på en hjemmeside. På hjemmesiden skulle det være muligt at sorterer i dataen.

Her er vores produkt backlog for sprint 1 med en oversigt af vores items, som står i prioriteret rækkefølge. Vi har tilføjet en ekstra item, som i vores tilfælde er item 5, og den kunne vi gå i gang med, hvis vi blev færdige før tid. Det er svært at estimere items i starten, når vi ikke har så meget erfaring med den teknologi, som vi skal til at anvende. Vi ville hellere være på den sikre side, så vi ikke skulle bruge ekstra tid på planlægning.

ID Navn Beskrivelse Importans Estimater Hvordan det testes Noter
1 Gem data Der skal gemmes data, som vi henter fra crawleren 1 5 Vi kan se om der blevet gemt en fil med det korrekte data
2 Hent data Vi skal kunne udskrives data fra crawleren til hjemmesiden 1 5 Vi kan se om der er blevet udskrevet korrekt data på hjemmesiden
3 Filtrering Kunden skal kunne filtrere i dronerne fx. vælge fabrikant eller pris 2 5 Manuel test af filtering funktionalitet
4 Søgning Kunden skal kunne søge efter en bestemt drone 3 5 Manuel test af søgeord
5 Opsætning af hjemmeside Hjemmesiden skal struktureres 4 6 Manuel test af hele siden Bliver nok kun arbejdet på hvis der bliver ekstra tid

Burn down sprint 1

Det gik rigtig godt med sprint 1, og vi blev færdige en dag før med de opgaver, som vi havde planlagt at lave. Det kan ses ved at vores burn down graf rammer nul om torsdagen. Vi tog den sidste opgave ind, så der blev tilført 6 ekstra story points til sprint 1. Det er grunden til at grafen går op på 6 story points den sidste dag.

Web scraping

For at kunne hente informationer om droner fra de forskellige drone forhandlere på internettet, har vi brugt web scraping teknologi. Det var den første og højst prioriterede opgave. Web scraping er noget software, som gør det muligt at udtrække og gemme data fra hjemmesider rigtig hurtigt. Her har vi bygget vores pris aggregator op omkring et open source web scraping framework, som hedder Scrapy. Det er baseret på programmeringssproget python, som mange andre web scraping og web crawling teknologier også er baseret på. Vi synes at det gav mere mening at bruge et eksisterende web crawling framework fremfor at bygge et helt fra bunden. Det ville give os mere tid til andre opgave, så vi hurtigere kunne nå i mål og få udgivet vores projekt.

Scrapy spider

Det første vi begyndte at kode, var vores scrapy spider. Her har vi en spider til hver drone forhandler, og her er et eksempel på vores scrapy spider til dronebutikken.dk. Den er bygget op omkring en klasse Spider2, som indeholder 3 fields og en parse metode.  Alle vores spiders har 3 fields: name, allowed_domains og starts_urls.

name

Name er selve navnet på spideren. Navnet bruger vi, når vi sætter crawleren i gang. Da vi har mange forskellige spiders, er det også godt at de hver især har et navn, så vi udviklere nemmere kan kommunikere med hinanden, når vi arbejder på vores spiders.

For at starte crawleren kalder vi følgende metode i command prompt.

scrapy crawl droneCrawler

Så begynder crawleren at gå igennem alle de urls, som er i star_urls.

allowed_domains

Allowed_domains sørger for at web crawleren holder sig indenfor et specifikt domæne. Det sørger at web crawleren ikke løber løbsk og crawler store dele internettet, hvis den fx først crawler et link, hvor den så crawler alle links inde i det link osv.

starts_urls

Starts_urls er en liste med urls, som crawleren kører igennem. Dronebutikken har ikke en url på deres hjemmeside, hvor alle droner bliver listet på en gang. Derfor er vi nødt til at gå igennem alle drone kategorierne, så vi kan få alle droner med på dronebutikken.dk.

XPath

Vi har brugt XPath selector, når vi har scrappet drone forhandlernes hjemmesider med Scrapy. XPath bliver normalt brugt til at udvælge noder i XML, men det kan fint også bruges til HTML. De fleste internetbrowsere har i dag et inspector vindue, som gør det muligt at se kildekoden på hjemmesider på internettet. Her er det faktisk også muligt at kopiere XPath stien direkte ved hjælp af et nogle få kliks. Det gør arbejdet med XPath en del nemmere, da der er stor forskel på webshopsystemernes måde at opbygge HTML’en på.

Vi har så en parse metode specifikt til hver spider, da der er stor forskel på HTML’en på drone forhandlernes hjemmesider. Parse metoden har et parameter response, som er det HTML downloaderen har hentet ned fra en specifik url. Parse metoden indeholder først hxs, som er et local variable, der bliver tildelt HtmlXPathSelector, som tager html responsen som parameter. Local variablet titles får så tildelt det stykke html, som vi gerne vil scrappe data fra. I dette tilfælde er alle divs med class der hedder col-sm-6 col-md-4, og det er der hvor dronebutikken har deres produkter på deres hjemmeside.

Vi har så et for loop der kører igennem alle divs, som vi har udvalgt. Inde i for loopet laver vi objekter, som indeholder AffiliateLink, title og Pris ved at bruge en ny selector på hver. Her kalder vi så en extract() metode, som tager teksten som vi skal bruge. Objekterne gemmer vi til sidst i en liste items, som så bliver returneret. Vi kunne også godt have brugt CSS selectors til finde det HTML, som vi skulle bruge, men vi synes XPath var mest logisk.

Item

Vi fandt hurtigt ud af at det er vigtigt at holde god struktur på vores data, da vi crawler flere forskellige drone forhandlere, og her kan det hurtigt blive noget rod, hvis der er tastefejl og lignende. Vi har lavet en Item klasse i vores scrapy webscraper, som hjælper med at holde en god struktur på det data, som bliver scrapet fra drone forhandlerne. Item objekterne er simple containere, som indeholder title, Affiliate Link og Pris.

Scrapy til CSV

Vi fik så lavet vores spider og item klasse, og vi var nu klar til at starte vores web crawler. Her har vi har valgt at gøre sådan, at vi tager det data vi har fået gennem crawleren, som så bliver skrevet det ud i en .csv fil (comma separated file). På den måde kan vi let uploade data’en til vores database, samt bruge dem til at laver en graf over prisudviklingen i drone priser(sidste stående har vi dog ikke lave).

Hvordan starter man scrapy og hvad sker der.

Når man har installeret scrapy, lavet console pathing og har fået lavet sin crawler, kan man så starte den op. Det gør man inde i konsollen, hvor man navigerer hen til crawlerns position og skriver ” scrapy crawl droneCrawler2”, da crawleren hedder droneCrawler2.

Hvis alt fungere som det skal, begynder scrapy at udvælge data ved hjælp af parse metoden på det godkendte domæne og de urls, som bliver sat i kø i spideren. I vores tilfælde har vi fået scrapy til at hente en masse data på drone forhandlernes droner. Her får vi et link, pris og titel på alle produkterne. Det kan ses i nedenstående konsol, hvor vi lige har kørt web crawleren, så den har crawlet data fra dronebutikken.dk.

Scrapy commando til at lave csv fil.

Scrapy har en indbygget commando, som gennem dataen til en csv fil.

Eksempel: scrapy crawl droneCrawler -o filename.csv

Så laver scrapy en csv fil med alt dataen, som vi har lige crawlet. Det virkede rigtig godt, og vi kunne på den måde hurtigt få lavet en masse csv filer med data fra droneforhandlerne. Det data brugte vi så til at lave nogle sql quries, så vi kunne uploade det til databasen. Det er en stadig en langsom process, og her kom vi på ideen med at få udviklet en csv importer, som kan uploade csv filer direkte til vores database. Det gør at vi ikke selv skal indtaste vores data manuelt eller skrive sql queries til vores data. Csv importeren er først noget vi kan begynde på i næste sprint, da vi har andre opgaver som skal laves i denne sprint.

Views

Vi fik hurtigt lavet en simpel hjemmeside i mvc, som vi fik koblet til en database, og her kunne vi så tilføje det data, som vi fik fra drone crawleren. Vi fik lavet crud funktionalitet til vores views, så vi kunne udskrive noget dataen direkte på hjemmesiden, og så kunne vi samtidig også oprette, opdatere og slette dataen på hjemmesiden.

Index View

Vores index view er forsiden, og her vil man blive præsenteret af en liste af alle vores droner og med hvad priserne går fra, hvis man klikker på en drone vil man blive taget ind på ny side, hvor man kan se alle detaljer omkring dronen, samt en liste over hvem der sælger den og hvor meget det tager for den. Fra forsiden kan man også søge efter en drone på navn, samt vælge et bestemt mærke ud fra en drop down liste.

Create View

Vores create view gør det muligt at oprette nye objekter til databasen. Det er fx en ny drone, som så bliver tilføjet til databasen. Vores view indeholder en masse felter, hvor man så kan skrive information om dronen. Her er der et kode udsnit af vores create view, hvor man kan skrive Drone ID i et tekstfelt. Derudover kan man så også vælge mærkeID og så kan man skrive et drone navn og en drone beskrivelse. Det har vi ikke med i nedenstående kode udsnit, da koden til disse minder meget om nedenstående kode.

Anti-forgery tokenet bruges til at beskytte mod cross-site request forfalskning. For at kunne bruge denne funktion, kalder man AntiForgeryToken methoden ( AntiForgeryToken() ) i sin form og tilføjer [ValidateAntiForgeryToken] atributten til den action, som man gerne vil have beskyttelse på.

GET: Create metode

Når vi så vil oprette en drone, skal vi først ind på brugergrænsefladen, hvor man kan oprette en drone, og her trykker vi på en simpel opret drone knap. Det starter nedenstående Create metode, som så returnerer vores create view, hvor man kan oprette droner. Her bliver der også sendt data med mærkenavne til en dropdown liste, så vi kan vælge mærkenavne, når vi skal oprette en drone.

POST: Create metode

Når man så har oprettet informationer om en drone i vores create view, trykker man på opret drone knappen. Her bliver der så laver et POST request med dataen fra tekst felterne til POST Create metoden, som så gemmer det nye drone objekt til databasen. Her bruges igen ValidateAntiForgeryToken attributen for at undgå forfalskning.

Details View

For at kunne se detaljer om et drone, har vi lavet et details view, hvor informationerne om dronen bliver udskrevet. Her har vi en Details get metode som returnerer vores details view.

GET: Details metode

For at man kan komme ind på details siden, har vi brugt actionlink, som laver et Drone ID request på details siden. Når dette sker, laver vores controller et tjek om man har indtastet et gyldigt ID. Hvis det er godkendt, bliver der sendt et details view, hvor man kan se alle detaljerne på det produkt, som man har requested.

Her er koden for det view, som viser informationerne på details siden. Her bruger vi simple kontroller med linq, som udskriver informationerne på den udvalgte drone.

Delete View

Delete funktionaliteten fungerer ved at bruge en lignende GET function, som vi tidligere har set på i forbindelse med detail view, hvor så bliver vist det rette delete view. Herefter trykker man så slet knappen, og det så sendt et post request med det id der skal slettet, hvor det så bliver slettet i databasen.

GET: Delete metode

Når man kalder Get methode i et delete view, sker der det samme som som på en details side. Den tjekker om man har indtaste et gyldigt ID, og så returnerer den det view med data, som man har requested.

POST: Delete metode

Denne metode modtager et post request med det id der skal slettes, som så går ind i databasen og kalder Remove, som fjerner det ønsket objekt fra databasen og gemmer så efterfølgende.

Dropdown filter

Sortering og søgning af data er en vigtig del af en prissammenlignings hjemmeside. Det hjælper den besøgende med at finde frem til det personen søger. I den forbindelse har vi gjort brug af DropDownList. Den viser i vores tilfælde en liste med mærkenavne, som den besøgende kan bruge til at sortere i hobbydroner og erhversdroner.

Koden til DropDownList er i vores HomeController og i vores Home Index View. I Home controlleren har vi metoden Index, som tager string mærkenavn som parameter. Index har et local variable forhandlerPris, som bliver tildelt en liste med de billigste droner. forhandlerPris bliver returneret til Home Index Viewet, som viser alle dronerne i en tabel. Udover tabellen har vi også vores dropDownListe, og her vi bruger vi Propertien ViewBag i homeController, som gør det muligt at dele værdier mellem controller og view. Vi tildeler ViewBag.MærkeNavn en liste med alle mærkeNavne, så dropDownListen får værdier man kan vælge imellem i Viewet.

DropDownListen i Viewet ligger i et using statement, som sender en get request med en string i url’en til index i controlleren hver gang, der bliver valgt en værdi i dropdownlisten. Index får så mærkeNavn ind som parameter, som så gør at if statementet bliver aktiveret. Der bruger vi en Where clause, som indeholder en lampe expression, som vælger de droner på listen som har samme mærkeNavn, som det mærkeNavn fra DropDownListen. forhandlerPris bliver så returneret til Viewet, hvor der så bliver vist en ny liste med de droner, som indeholder MærkeNavnet.

Routing

Routing var en af de ekstra opgaver, som vi arbejdede med her til sidst i sprint 1. Det gjorde vi for at få en bedre forståelse af hvordan mvc hjemmesider virker.

I almindelig fil baseret web udvikling som fx web forms vil ens urls være relativ sigende, da de vil give dig sidens sti. MVC er ikke filbaseret, da den giver dig stien som var det et action link, som betyder at din url vil blive: domæne/controller/stringName/id (id er der kun hvis det er en side med et id fx et produkt). Her kan Routing bruges til at lave en pænere url. Dette kan gøres ved at, man har en global.asax.cs fil, hvor man får systemet til at ignorer diverse ting fx controller navn, fra din url. Vi har i vores tilfælde en RouteConfig klasse, hvor vi styrer alt vores routing.

Routing er mest af alt en SEO (søgemaskineoptimering) ting, og derfor er noget, man typisk vil lave efter man er færdig med selve siden. Da vi ikke er færdig med alt det funktionelle på siden, har vi vurderet at det er bedre at bruge energi på routing senere i projektet.

Error Pages

Nye hjemmesider har altid nogle små fejl hist og pist, og vi valgte derfor at bruge noget tid på at få lavet error pages. Det har vi gjort både for sikkerhedens og brugervenlighedens skyld. Error pages har vi lavet ved at lave rules i vores web.config fil, som gør at hvis den finder en 404 eller 500 error, vil den redirect indtil den relevante error side.

Vi har valgt at lave til lige de to error, da det er mest dem, som forekommer på et system som vores.

Error 404 forekommer hvis man prøver at åbne en side der ikke findes.

Error 500 forekommer når der opstår en uventet fejl og der ikke findes en bedre meddelelse

Authorize attribute

For at skjule vores crud funktionalitet for besøgende på vores hjemmeside, har vi brugt et Authorize attribute tag. Et [Authorize] tag er noget man bruger i MVC. Det sættes i controlleren for at indikere at man skal være logget ind og have de rigtige rettigheder for at man kan få adgang på de view, som høre under den valgte controller. Hvis man fx ikke er logget ind, bliver der lavet et 401 redirect ind til login siden. På den måde kan vi skjule create, update og delete funktionaliteten på hjemmesiden.

SQL/Html Injection

Når man arbejder med web, er det altid godt at tænke på sikkerhed især overfor sql injection. En af de bedste beskyttelse imod sql injection, er faktisk at bruge .NET. Da vi arbejder med MVC, er vi allerede dækket godt ind, men det er stadig godt at gøre sig nogle tanker omkring sikkerhed som udvikler. Man kan aldrig være helt sikker på, om at man er helt beskyttet, da en person som er dygtig og kreativ med sql, næsten altid vil kunne finde en vej igennem.

Sql/html injection fungerer ved, at man poster en sql query eller en html kode i enten en tekstboks eller direkte i url’en. Ved brug af .NET så blokere man sql/html Post igennem tekstbokse, dette er fx ikke tilfældet ved brug af php.

Sql direkte i url’en er primært noget man skal tænke over, hvis man bruger en open source database som Mysql, og ikke har et login system, da det er ret let at blokere bare ved at kræve at de skal have admin rettigheder, for at besøge diverse hjemmesider.

Less Compiler

Den sidste ting vi fik implementeret i denne sprint var en less compiler. Vi har valgt at bruge Less i stedet for traditionel css, men da en browser ikke kan læse less/scss skal man bruge en måde at konvertere sin less code om til almen css. Vi har valgt at bruge et pluginet “Web Compiler” til visual studio til at gøre det for os. Måden det fungerer på, er at den via en RESTful service konverterer less til json også udskriver den koden til en traditionel css fil, som du så kan kalde i din kode. Vi har valgt at implementerer less allerede nu, da det er noget vi vil bruge på længere sigt. Less har en masse smarte features fx variabler og nesting, som gør arbejdet med css smartere. Less gør det fx muligt at have sine farvekoder samlet i et globalt variable. Det er smart, hvis man fx vil lave en hurtig farveændring.

Retrospektive

Hvad har været godt?

Når vi har stødt ind i et problem har vi altid kunne løse det. Her har vi været gode til at finde frem til hvad vi ikke har kunnet finde ud af, hvor vi så har arbejdet på at blive klogere, så vi kan løse problemstillingerne. Vi er glade for vores arbejdstider. Vi arbejder fra 8.00-15.00 hver dag, hvor vi holder en kort pause en gang i timen. Så holder vi en længere middagspause, hvor vi kan få noget at spise. Det hjælper med at holde vores produktivitet høj, og det er noget vi gerne vil fortsætte med resten af projektet.

Hvad kunne have været bedre?

Vi havde overvurderet opgaverne her i første uge, hvilket medførte at vi tog ekstra opgaver ind. Vi skal være bedre til at estimere vores stories og tasks, så det kommer til at passe bedre med den tid vi reelt bruger. Vi havde også lidt problemer med github, hvor vi fik et par konflikter.

Forslag til forbedringer

Måden vi vil forbedre estimering af opgaverne på, er ved at bruge lidt mere tid på planlægning af næste sprint, så vi kan få endnu bedre styr på vores estimering. Opdeling af stories til flere tasks kan hjælpe her. Et andet forslag er at vi skal være bedre til at aftale hvem der arbejder i hvilke filer, så vi ikke får konflikter. Der skal være en bedre intern kommunikation i fremtiden.

Sprint 2

Målet for sprinten

Målet for sprint 2 er at blive klogere på test først i forhold til mvc. Her vil vi gerne finde ud af hvordan automatisk test fungere med mvc også få lavet et automatisk test system til projektet. Derudover vil vi også lave en manuel test af sites, så vi kan finde frem til eventuelle fejl i det vi fik lavet i forrige uge. Vi vil også gerne have lavet en ny database, hvor vi får styr på alle tabeller og deres kolonnenavne. Det er den anden store opgave i sprint 2.

ID Navn Beskrivelse Importans Estimater Hvordan det testes Noter
6 Test af systemet Automatiske test i Visual Studio og manuel tests af systemet 1 10 Unit Test køres automatisk i Visual Studio, hvor der bliver testet på udvalgte parametre. Vi gennemgår systemet manuel
7 Struktur af database Vi skal have designet en online database som passer sammen med vores model klasser 2 10 Unit Test køres automatisk i Visual Studio, hvor der bliver testet på udvalgte parametre

Sprint 2 burn down

Sprint 2 gik rigtig fint. Vi kom et point bagud den første dag, men vi fik hentet det hjem igen om tirsdagen. Resten af ugen forløb præcis efter planen i forhold til vores estimering.

Unit test

Det første vi kiggede på i sprint 2 var unit test. Unit testing eller automatisk test fungerer ved at man typisk opretter et testprojekt som har en ene funktion at køre tests. Hvis man ikke vil have et ekstern projekt kan man dog godt lave det i samme projekt, dette vil vi dog ikke anbefale. I et testprojekt kan, man lave alle de test du gerne vil have fx test forbindelse til database, test om CRUD funktioner virker osv.

Unit testing er meget brugt da man hurtigt kan finde en masse fejl på den måde. Ved at bruge XP praktikken ”test først” så får man også en meget god sikkerhed da ens kode altid burde kunne køre.

Det var noget af en hurdle at få implementeret i praksis i mvc, så vi valgte ikke at bruge mere tid end de story points, som vi havde givet til opgaven.

Database

Den anden store opgave i sprint 2, var at få lavet en ny database. Her har vi valgt at bruge Mssql databaser, og det har vi gjort af flere grunde. For det første har vi valgt at arbejde i asp.net MVC, og det virker godt sammen med Msssql databaser. Derudover har vi adgang til Microsoft produkter igennem UCN(SQL Server Mangement Studie og Visual Studie).

Vi har valgt også at købe en Mssql database fra start, da det giver os muligheden for at teste vores produkt på en dansk server. Det eneste minus er at en Mssql database, koster noget mere en Myssql database hos de danske webhost. Der er lidt flere økonomiske omkostninger ved at have en Mssql database kørende.

Vi valgte at lave et database diagram, inden vi begyndte at lave databasen. Det gav os bedre udvikling af vores kommende database, så vi nemmere kunne udarbejde den arkitektur i databasen som vi ønskede.

Vi vil kort gennem kort de forskellige tabeller i databasen.

Mærke

Her har vi alle mærkerne på dronerne, den fungere ved at den har en key til Drone tabellen. Derfra kan systemet sætte mærke på dronerne igennem MærkeID.

Drone

Denne tabel indeholder alle vores droner med deres navn, billede osv. vi har lavet det sådan at vi hurtigt kunne sætte andre ting ind her som fx. brugeranmeldelser. Drone har en key til ForhandlerPris så den kan sende data derned.

ForhandlerPris – Composite Pattern

Det er her at selve “aggregator” delen foregår. Det sker ved at vi udregner priserne på dronerne ved at sammenligne data den henter fra Drone igennem DroneID og Forhandler igennem ForhandlerID.

Forhandler

I denne tabel har vi informationen på vores forhandler, (deres navn, adresse og leverings pris osv.) Forhandler har en key til ForhandlerPris så den kan sende data derned.

Lambda Expression

Efter vi havde oprettet databasen valgte vi at læse lidt op på lambda expressions og delegates. En lambda expression er en anonym function som kan bruges til at oprette delegates eller expression tree. Lambda expression er især gode når man skriver LINQ query expressions, og det har vi gjort flere gange i dette projekt.

Når man laver lambda skal man specificere sine input parameters på den venstre side af lambda operatoren ( => ) og dit statement eller expression på den anden side.

Eksempel: x => x * x   

Her ser vi et parameter der hedder x og at den returnere værdien af x^2.

Delegates

En Delegate er en måde man sikkert kan indkapsle en methode, og fortsat holde det objektorienteret. Et delegate object er normalt, bygget ved at man giver den navnet af den metode som man gerne vil indkapsle. De fungere ved at når man kalder delegaten så sender den kaldet videre til metoden, som så returnerer data tilbage til brugeren via delegaten.

Retrospektive

Hvad har været godt?

Vi har arbejdet meget sammen i denne uge, da der har været meget research i forbindelse med test først. Her har vi været gode til at koordinere vores research, så vi har kigget på noget forskelligt. Her har vi så efterfølgende delt den viden med hinanden. Det har været rigtig godt.

Hvad kunne have været bedre?

Vi fik et par konflikter, da vi skulle tage vores nye database i brug. Det bunder ud i at vi ikke fik kommunikeret ordentligt, og vi brugte derfor lidt ekstra tid på at få styr på Github. Vi havde dog allerede fra start, taget hensyn til at der nok ville komme nogle problemer med vores versionsstyring, men det er stadig træls, når vi nemt kunne have været disse fejl foruden.

Forslag til forbedringer

For at undgå konflikter i fremtiden har vi valgt at øge vores kommunikation yderligere internt. Det gør vi ved at sige hvilke kode filer vi arbejder i, så har vi bedre styr på hvilke filer der bliver brugt. Derudover vil vi holde flere skype samtaler og fysiske møder i fremtiden, så vores bliver bedre kommunikation i fremtiden.

Sprint 3

Målet for sprintet

Vi skal have lavet sådan at forsiden viser alle vores droner, men kun en gang og kun med den billigste pris, herfra skal der være links ind på en details side, hvor alle detaljer omkring droner er listet, samt alle de forhandlere der sælger den valgte drone med alle priserne. Derudover skal vi have tilpasset crawleren, så den virker med det nye database design, og vi skal have lavet vores csv importer.

ID Navn Beskrivelse Importans Estimater Hvordan det testes Noter
8 Details Site Lav en side der viser alle detaljer omkring en drone 1 2,5 Tjek om den udskriver det rigtige data
9 Link til details Links der tager dig fra forsiden ind til en specifik drone 2 2,5 Klik på linket og se hvor den tager en hen
10 Vis billigst pris Forsiden skal kun indeholde den billigste pris, der findes på en drone 3 5 Kør hjemmesiden og tjek hvad den returnerer
11 Crawler tilpasning Crawleren skal tilpasses så csv filerne passer med den nye database 4 5 Se om data’en i csv filerne stemmer med den format databasen vil have
12 Csv importer Vi skal have lavet sådan, at vi kan importere data fra en csv fil til databasen 5 5 Upload en csv fil og se om den indsætter data i databasen

Sprint 3 burn down

Sprint 3 startede godt ud, men allerede om tirsdagen begyndte vi at falde en del bagud. Vi fik dog styr på tingene igen, da vi hurtigt fik lavet crawleren og csv importeren. Vi fik lavet alle story points i sprint 3, hvilket er rigtig godt.

Udskrive billigste pris

Når en kunde kommer ind på dronepris.dk, har vi lavet sådan, at der bliver udskrevet en liste med alle de billigste droner. Det giver kunden et godt overblik af de typer af droner der er på markedet, samtidig med at de får et overblik af de billigste priser. Så kan kunden selv klikke sig videre ind på den type drone de ønsker, hvor de så kan klikke sig videre ind på de forhandlere som sælger dronen.

Når kunden ser den billigste pris fra start, er det nemmere for dem at spotte de gode tilbud, da de allerede ved hvad den billigste pris på markedet er. Det gør at kunden ikke bliver snydt på prisen, og det giver en værdi til kunden, da de lige har sparer nogle penge i forhold til hvis de købte en drone, som ikke var på tilbud. Det kan i nogle tilfælde betyde en besparelse på flere tusinde kroner for kunden, da droner ligger i en høj prisklasse, hvor der kan gives store rabatter.

Der kommer hele tiden nye og bedre droner på markedet, og det gør at de gamle drone modeller ikke kan følge med på funktionalitet og performance, og de går dermed ned i pris. For at mindske tabet af forældede droner, er der sikkert nogle drone forhandlere, som sætter disse droner på tilbud, og det er især disse tilbud, som vi gerne vil vise på dronepris.dk.

Vi har brugt SQL til at finde de billigste droner i databasen. Entities frameworket som vi bruger til vores database har en Database klasse med en SQLQuery metode, som gør det muligt at skrive en raw SQL Query, og den metode har vi brugt i vores tilfælde.

Vores SQL Query til at finde de billigste droner ser ud som følgende:

select * from DronePris.dbo.ForhandlerPris Inner Join(Select DroneID, MIN(ForhandlerPris.Pris) Pris From DronePris.dbo.ForhandlerPris Group By DroneID)tbl1 On tbl1.DroneID = ForhandlerPris.DroneID Where tbl1.Pris = ForhandlerPris.Pris

SELECT

SELECT er et SQL statement, som vi bruger til at udvælge data fra vores databasen. Vi bruger fx SELECT i starten af vores SQL Query til at udvælge alt dataen fra ForhandlerPris tabellen i databasen DronePris. Tegnet * bruges til at hente alt dataen. Vi bruger fx også SELECT statementet til at udvælge DroneID’er i vores INNER JOIN i ovenstående SQL QUERY.

FROM

FROM clause bruger vi lige efter vores SELECT statement, og den er med til at producere resultat sættet (tabel strukturen).

INNER JOIN

INNER JOIN laver et helt nyt resultat sæt ved at kombinere to tabeller. I vores tilfælde har vi brugt INNER JOIN til at sammenflette to tabeller til et nyt resultat sæt, så vi får en liste med kun de billigste droner.

MIN

MIN er en funktion, som returnerer den mindste værdi i en kolonne. I vores tilfælde bruger vi MIN til at returnere den drone med den mindste forhandler pris.

WHERE

WHERE clause bruges til at filtrere med, så man kun får data som opfylder nogle bestemte krav. Vi bruges fx WHERE clause til kun at udvælge data i tbl1, hvor tb1.Pris matcher med ForhandlerPris.Pris.

GROUP BY

GROUP BY bruges i et SELECT statement til udvælge data, som så bliver grupperet kolonnevis. Vi bruger fx GROUP BY i vores INNER JOIN til at gruppere dataen på droneID.

AsEnumerable()

AsEnumerable() bruger vi lige efter SQLQuery til at caste vores liste med billigste droner til et generisk interface(IEnumerable interface), så vi kan bruge vores liste i forbindelse med LINQ.

Vi har fx noget filtrering som kan ses i nedenstående kode snippet, hvor vi bruger LINQ til at filtrere de billigste droner på mærkenavn, så kunden kan få et overblik af de droner en specifik forhandler sælger. Hvis vi ikke havde brugt AsEnumerable() på vores liste med billige droner, ville vi få en fejl, da listen ikke ville fungerer med LINQ.

Scrapy pipeline ord filter

Dandrone.dk og dronebutikken sælger også tilbehør til droner, som bliver listet sammen med dronerne på deres webshops. Det gør at tilbehøret også bliver scrapet, som så kommer med i vores data. Da vi kun sammenligner priser af droner til at starte med, har vi valgt at lave et ord filter, som fjerner items fra drone listen som indeholder bestemte ord. Det gør at vi får en liste kun med droner, som er det vi skal bruge.

Vi har lavet en klasse til ord filteret, som hedder FilterWordsPipeline. Den tager så et object som parameter. Inde i FilterWordsPipeline klassen har vi lavet en liste words_to_filter, som indeholder de ord, som vi gerne vil filtrere fra listen.

Metoden process_item tager 3 parametre som input: self, item og spider. Metoden starter med et for loop, som kører igennem alle words_to_filter listen. Inden i for loopet har vi lavet et if else statements. Hvis der er et ord, som matcher title, bliver det ord slettet fra listen. Hvis ordet ikke er i titlen sker der ikke noget i objektet.

Nedenstående billeder viser et eksempel, hvor scrapy lige har crawlet dronebutikken.dk. Her dropper scrapy produktet Phantom 2, ZH3-3D & Video, da det produkt indeholder et ord, som er på listen med forbudte ord. Produktet Inspire 1 Raw Forudbestillingen bliver så ikke droppet fra listen, da det ikke har nogle forbudte ord. Det gør alt i alt at vi får de droner på listen som vi ønsker, og så kan vi selv tilføje flere forbudte ord i fremtiden, hvis der fx kommer nye produkter ind i blandt dronerne.

CSV Importer

Csv filerne som scrapy laver, indeholder en helt masse datasæt om dronerne fra droneforhandler, så det var oplagt at få udviklet et værktøj, som kunne få dataen fra csv filerne ind i vores database. Det ville lette arbejdsbyrden med datahåndtering, da csv importing kan klares med få klik, hvor manuel indtastning af data og sql queries er en mere tidskrævende proces. Vi fik udviklet et csv importer værktøj, som kan importere csv filer direkte til vores database med få klik.

Csv importeren består af 3 forskellige metoder. En fileupload metode som håndterer upload af csv filen. En processCSV metode som laver dataen i csv filen om til et datatable. En metode processBulkCopy som gemmer dataen i datatable til databasen.

Den grafiske del af csv importeren er i vores forhandlerPris view på hjemmesiden, hvor vi bruger en fileUpload input felt og en simpel knap, som vi bruger til at lave et POST request med csv filen til fileupload metoden.

Fileupload

Fileupload methoden har HttpPost attribute, som gør at metoden kun kan blive kaldt i forbindelse med et http POST request. Metoden bliver kaldt i vores tilfælde, når vi submitter en csv fil i vores forhandlerPris view.

For at metoden kan tage imod csv filen, som bliver uploadet på clienten, har metoden et parameter FileUpload af classen HttpPostedFileBase, som giver adgang til filer som er uploadet på clienten.

Inde i metoden har vi først et Datatable dt variable, som vi senere bruger til at opbevare dataen fra csv filen i en tabel in memory. Derefter har vi et if else statement, hvor vi tjekker om der er noget i csv filen, som bliver uploadet. Hvis der er noget data i filen, går den igennem checket. Hvis der ikke er noget i filen, bliver filen kasseret.

Når csv filerne går igennem, har vi et string fileName variable, som får csv filens navn. Her bruger vi Path til at lave operationer på den csv fil der uploades. Path har en metode GetFileName, som returnerer en string med filnavnet på en bestemt position. Her giver vi så parameteret FileUpload, og den indeholder en get metode, som får navnet på filen.

Derefter har vi et string variable path, som får en kombineret string af placeringen/stien hvor den uploadede csv fil skal ligge på serveren, og hvad navnet på filen er. Her bruger vi igen path til at lave operationer, hvor vi i stedet bruger en metode der hedder Combine, som kombinerer to strings til en placering. Her vælger vi så at lave placeringen på serveren i en undermappe ”Uploads” i vores App_Data mappe. hvor filen så får fileName som navn.

Det næste der sker, er at vi har en try catch, hvor vi først starter med at gemme csv filen FileUploade ved hjælp af en SaveAs, som får path som parameter. Hvis det går godt er csv filen gemt på serveren i mappen Uploads. Derefter får det dataen fra csv filen, som er lavet om til et datatable ved hjælp af ProcessCSV metoden, som får csv filens placering som parameter.

Når ProcessCSV metoden er færdig, bliver datatable gemt til vores database ved hjælp af ProcessBulkCopy metoden.

ProcessCSV

ProcessCSV metoden går igennem dataen i CSV filen, som bliver lavet om til Datatable, så dataen senere kan gemmes til databasen. ProcessCSV tager fileName som parameter, og da metoden bliver brugt i metoden med fileupload, får ProcessCSV path string som paramter, og det er placeringen af CSV filen på serveren.

I starten af metoden bliver der laver 4 lokale variabler. Den første variable er line og den bruges senere til at holde en linje af data fra csv filen. strArray er et string Array som bruges til at holde på alle line variablerne efter de er blevet splittet op ved hjælp af regular expression. Lokal variablet Datatable dt bruges igen til at holde på dataen i en tabelform. Datarow row bruges i forbindelse med Datatable til at repræsentere et row. Dataen skal have den rette form, så det passer til databasen. Det er vigtigt.

Regex r er et regular expression variable, som vi bruger til at splitte den kommasepareret csv fil op med. Når der kommer et komma bliver teksten splittet op. Hvis der fx kommer et andet tegn bliver teksten ikke splittet op. Det er vi nødt til at bruge for at computeren for at kan splitte teksten de rette steder, så det senere kan blive gemt rigtigt til databasen.

StreamReader sr variablet bruger vi til at læse hver linje i csv filen, og her bruger vi metoden ReadLine() fra StreamReader. Hver linje bliver gemt i line, som regular expression eftefølgende splitter op, som så bliver gemt i strArray. Derefter har vi et ForEach som laver alle kolonnerne, som bliver tilføjet til et ny DataColumn. Her har vi brugt lambda expression til at udvælge kolonnerne på vores strArray, som så bliver Added til DataColumn.

Derefter har vi et while loop, som kører indtil den har læst linjerne i CSV filen. Inde i while loopet bliver der tilføjet en ny row linje for linje, hvor der efterfølgende bliver fyldt data i hver kolonne i row’et. Regular expression sørger for at splitte dataen i line, så dataen rammer ind i de rigtige kolonner. Derefter bliver row’et tilføjet til datatable, som til sidst bliver returneret, når alle linjer er kørt igennem i CSV filen.

ProcessBulkCopy

ProcessBulkCopy tager et DataTable dt som parameter, og det er i vores tilfælde det DataTable som ProcessCSV har gjort klar. ProcessBulkCopy indeholder 2 lokale variabler. Det ene er en string Feedback, som bruges til giver besked om hvordan det er gået. Den anden er connString, som er connectionstringen til vores database. Vores connectionString hedder DefaultConnection, og den er i webconfig filen, hvor hele connectionStringen til databasen er placeret.

Det næste der sker, er at der bliver lavet et nyt variable conn, som initialiseres til en ny instance af SqlConnection med connString input, så en ny connection til databasen bliver gjort klar.

For at overfører det her Datatable dt til databasen, har vi brugt noget der hedder SQLBulkCopy, som er et godt værktøj til at overføre data fra en enhed over til en anden. Vi laver først et SqlBulkCopy variable copy som vi senere bruger efter at vi har åbent en connection til databasen. copy har en Get, Set Property DestinationTableName, og her får den navnet ForhandlerPris, da det er det table i vores database, som vi gerne vil gemme data til. copy.BatchSize bruger vi til at finde frem til hvor mange rows der skal være i tabellen. Datatable har en rows property, og her bruger vi en Count til at tælle hvor mange rows der er. Når der er styr på dette, er vores Datatable dt klar til at blive overført til vores databasen, og her bruger vi WriteToServer, som så får dt som parameter. WriteToServer kopierer alle rows i vores Datatable dt, som så bliver overført til ForhandlerPris table, som er det table dataen skal gemmes til. Herefter lukkes connectionen til databasen.

Retrospektive

Hvad har været godt?

Vi har været gode til at hjælpe hinanden, og det har hjulpet os meget, da der har været mange svære opgaver i dette sprint. Vi har fx holdt korte møder ca hver time, hvor vi så har prøvet at hjælpe hinanden med de problemstillinger vi har arbejdet med. Det har fungeret rigtig godt, når vi arbejder på de lidt mere komplekse opgaver. Vi har fx fået lavet et ord filter til web crawler, og det har hjulpet os med at frasorterer det data, som vi ikke skal bruge. CSV importeren har også gjort vores arbejde en hel del nemmere, da den kan uploade store mængder data på en gang. Vi har ikke haft nogle konflikter i forbindelse med vores verssionsstyring i denne uge, og det er også meget positivt, da det var noget vi gerne ville forbedre fra sidste uge.

Hvad kunne have været bedre?

Vi kunne godt have været bedre til at par programmere noget mere i denne uge. Der har været mange svære opgaver, og her har vi helt sikkert kunne løse nogle af opgaverne hurtigere, hvis vi sad om samme computer. Så kunne en af os skrive koden, mens den anden ser på og kigger i dokumentation.

Forslag til forbedringer

En klar forbedring er at indfører noget mere par programmering i fremtiden. Det kan vi selvfølgelig gøre de dage vi mødes, og så kan vi bruge skærm deling på skype de dage hvor vi arbejder over skype.

Sprint 4

Målet for sprinten

Vi har to opgaver og to spike opgaver i denne sprint. Vi skal have lavet en pipeline imellem crawleren og databasen. Vi skal også have lavet et view inde på side, hvor vi skal kunne starte crawleren manuelt. Den ene spike er omkring hvordan python og mvc virker sammen, hvor den anden spike er omkring cronjobs, så vi kan få crawleren til at køre automatisk.

ID Navn Beskrivelse Importans Estimater Hvordan det testes Noter
13 Crawler View Lav et view så crawleren kan aktiveres via frontend 1 2 Tjek om der er adgang og se om den udskriver det rigtige data
14 Pipeline til database Lav crawleren så den kan sende data direkte ned i databasen 2 8 Se om der kommer data ind i databasen når vi beder crawleren om at sende
15 Mvc og Python Find ud af hvordan mvc og python kan arbejde sammen 3 5 Dette er kun en spike
16 Cron job automatisering Find ud af hvordan vi kan få crawleren til at køre automatisk med et cron job 4 5 Tjek om crawleren køre på det ønsket tidspunkt

Burn down

Sprint 4 startede ikke så godt ud, da vi kom lidt bagefter i forhold til tidsplanen. Vi havde nogle problemer med at få vores pipeline til at virke, så vi valgte at gå lidt videre med nogle af de andre opgaver. Vi mangler 5 story points og det er vores pipeline opgave, som så kommer med i sprint 5.

Crawler View

Vi har fået lavet en admin side view, hvorfra vi kan starte vores crawler manuelt på en specifik shop, hvis det skulle blive nødvendigt. Alt hvad denne side har lige nu er det grafiske, hvor vi så senere skal lave en ny opgave, hvor crawleren bliver koblet på.

Pipeline til database

For at automatisere vores webcrawler endnu mere i forhold til vores hjemmeside, har vi arbejdet på at få lavet en pipeline, så vores webcrawler kan gemme dataen direkte til en database. Det er en hurtigere og mere effektiv metode end at uploade csv filer manuelt, og det er noget der er nødvendigt, hvis vi går efter at opdatere priserne på hjemmesiden flere gange om dagen.

En pipeline er noget der på sigt, vil kunne spare os begge en masse mandetimer, da en pipeline hjælper med at gøre forretningen mere automatiseret. Der vil højst sandsynligt opstå nogle små fejl i dataen, når pipelinen kommer oppe at køre, men der er få timers rettelse i forhold til det manuelle arbejde vi har lavet tidligere. Den tid vi bruger på at få udviket en pipeline, vil blive tjent hjem igen, da en pipeline i vores tilfælde vil hjælpe os meget. Så kan vi i stedet bruge tiden på at udvikle nye features og indtjenings kanaler på hjemmesiden, som gør forretningen endnu mere indbringende.

Når crawleren er færdig med at køre og den har droppet alle de produkter med forbudte ord, skal dataen gemmes til vores database. Vi har et composite pattern ForhandlerPris i vores database, og her har vi endnu ikke fundet frem til en løsning, så pipelinen gemmer dataen rigtigt i forhold til vores DroneID og ForhandlerID.

Det vi har gjort indtil videre er at have dronerne og forhandlerne i alfabetisk rækkefølge i databasen. Den data vi får fra webcrawleren sorterer vi på titel, så dronerne står i den rigtige rækkefølge i forhold til vores egen database. Herefter giver vi så dronerne et DroneID og et ForhandlerID. ForhandlerID er 1 hvis det er Dronebutikken.dk og 2 hvis det er Dandrone.dk, og det har vi kunne løse med en simpel variabel med 1 eller 2, da vi har en crawler til hver forhandler. Vi mangler at få lavet så DroneID’erne passer, og det er det vi har arbejdet på her i den sidste del af projektet. Når det er løst burde vi princippet kunne gemme dataen til databasen, så det passer med de droner der allerede er.

MVC og Python

Vi har en spike på MVC og Python, som skulle bruges til at undersøge om der var nye smarte teknologier, som kunne få vores arbejde med MVC og Python til at blive lettere. Mvc og python er lavet til to forskellige platforme(Mvc er .net og python er lavet til linux). De kan ikke arbejde sammen, men de kan godt snakke med den samme database, og på den måde arbejde sammen. Vi fandt dog et open-source framework til python, som hedder IronPython, som er lavet til at køre på .Net. Det kunne hjælpe os med at få samlet alt vores kode i visual studio. IronPython fungerede ikke helt efter hensigten, da vi bruger en tidligere version af python. Så vi droppede ideen om at bruge IronPython.

Cron job automatisering

Priserne som vi scraper hos drone forhandlerne skal helst være up to date, da priserne hjælper de besøgende med at danne sig et overblik af priserne på droner. Hvis disse priser ikke passer, kan der let opstå forvirring blandt de personer som bruger vores service, og det skal helst ikke opstå. Derfor er det vigtigt at crawleren scraper priserne med korte mellemrum, så der ikke opstår misforståelser. Det vil dog kræve meget manuelt arbejde fra vores side, hvis vi fx selv skulle køre crawleren flere gange om dagen. For at løse dette problem har vi anvendt et cron job, som gør det muligt at køre crawleren automatisk på bestemte tidspunkter, så vi ikke selv skal starte crawleren hele tiden.

Et eksempel kan fx være at vi laver et cron job, som kører crawleren 2 gange om dagen til at starte med. Det ene tidspunkt kan være om natten klokken 2 og igen klokken 15 om eftermiddagen. Grunden til vi crawler om natten, er at der ikke er så meget belastning på drone forhandlernes servere, da der ikke er så mange mennesker, som handler på internettet om natten. Det er vigtigt at tage højde for at crawleren ikke belaster forhandlernes server. Det ville fx være dumt at køre crawleren 10 gange i timen, hvis det resulterer i at drone forhandlernes servere bukker under, som så resulterer i at deres webshop går ned. Så kan kunderne ikke handle, og det betyder tabt indtjening for alle parter.

Vi fandt så ud af, at vores webhost unoeuro har en cron job service, som vi kunne bruge. Vi går efter at bruge denne service, når projektet er udgivet.

Retrospektive

Hvad har været godt?

Vi er så småt begyndt på rapporten, og her er vi kommet ind i et rigtig godt skrive system. Her brainstormer vi først alle de punkter, vi gerne vil skrive om. Det hjælper os med at finde frem til hvad vi vil skrive om, som gør at vi kan skrive mere effektivt.

Hvad kunne have været bedre?

Vi kunne godt have været bedre til at prioritere og estimere opgaverne for denne uge, så vi kunne have givet mere tid til vores pipeline til database opgave frem for at bruge tid på spikes og andre ting. Pipelinen var klart det vigtigste i denne sprint, men det lagde vi ikke nok vægt på.

Forslag til forbedringer

Vi vil bruge mere tid på planlægning af næste sprint, så vi kan få prioriteret og estimeret vores opgaver bedre. Her kan vi kigge på hvilke opgaver der er vigtigst i forhold til vores mål og forretning, så vi får lavet det vigtigste først.

Sprint 5

Målet for sprinten

Sprint 5 har vi ikke fået lavet endnu, men det kan være at vi når at lave sprinten efter vi har afleveret rapporten. I sprint 5 har vi tænkt os at køre klar til at udgive siden. Her vil vi først arbejde på at få lavet nogle mere venlige urls. Derudover vil vi sætte authorisation på de sider, som kræver admin rettigheder for at gå ind på. Derefter skal vi have lavet den grundlæggende grafiske struktur.  Så skal vi også have lavet en online database, så vi kan få udgivet prissammenlings hjemmesiden.

ID Navn Beskrivelse Importans Estimater Hvordan det testes Noter
17 Friendly Url Lav urls så de er mere brugervenlige 1 2,5 Tjek url’en
18 Authorisation Få aktiveret begrænsning på de sider der kræver rettigheder 2 2,5 Åben siderne og se om de kræver rettigheder
19 Hjemmeside Struktur Få lavet den grafiske struktur 3 5
20 Online database Få lavet en online database 4 5 Importer data fra den gamle database og se hvad der sker
21 Opload af mvc site spike Find ud af hvordan man oploader en mvc hjemmeside 5 5

Konklusion

I vores problemformulering stillede vi dette hovedspørgsmål:

Drone markedet er under stor vækst, hvilket gør at der er store prisændringer, og at der hele tiden kommer nye droner og nye forhandlere på markedet. Hvordan kan en pris aggregator til droner udvikles, som tager højde for at droner markedsføres på mange forskellige hjemmesider og med mange forskellige priser.

Vi lavede først en grundig undersøgelse af drone markedet, hvor vi kiggede på de danske droneforhandlere og hvilke droner de solgte. Her kom vi frem til at størstedelen af de danske droneforhandlere sælger hobbydroner og erhvervsdroner, hvor priserne går fra et par hundrede til flere tusinde kroner. Disse forhandlere er tilmeldt et affiliate program, hvor de tilbyder kommission for hvert salg man kan skaffe til deres forretning. Vi tjekkede op på om der var andre i dronemarkedet, som havde lavet services på internettet, som skaffede salg til danske droneforhandlere. Det var begrænset hvad der var af services, så vi fandt frem til at en prissammenlignings hjemmesider med droner, ville være et fornuftigt koncept, som så kunne skaffe salg til de danske droneforhandlere mod kommission.

For at en prissammenlignings hjemmeside skal kunne virke efter hensigten, skulle vi bruge en form for pris aggregator, som kunne tage højde for de forskellige priser hos de danske droneforhandlere. Vi skulle hente priserne fra droneforhandlerne, og her kom vi frem til at web scraping ville være en fornuftig måde at løse denne problemstilling på. Web scraping gør det muligt at udtrække data fra internettet, som så efterfølgende bliver analyseret og gemt i en databasen. For at komme hurtigst muligt i gang med web scraping, valgte vi at bruge et web scraping framework, som hedder Scrapy.

Det vi udtrækker hos droneforhandlerne er HTML(HyperText Markup Language), da HTML udgør strukturen for de fleste webshops på internettet. Her har vi brugt en HTML Parser, som tager HTML koden og udvælger pris, titel og links på dronerne hos droneforhandlerne. De produkter som vi ikke skal bruge, fjerner vi ved hjælp af et ord filter, som vi fik udviklet. Det data der så er blevet udvalgt, har vi gemt til csv filer, som vi så har uploadet til vores prissammenlings hjemmeside ved hjælp af en csv importer. På hjemmesiden viser vi så produkterne fra droneforhandlerne, hvor vi sammenligner på pris. Vi har så efterfølgende arbejdet på at få lavet en pipeline, som kan gemme dataen fra web crawleren direkte til en database, så vi ikke skal uploade csv filer manuelt. Det hjælper med at opdatere priserne hurtigere og flere gange om dagen, da det hele kommer til at køre mere automatisk. Pipelinen er ikke helt færdige endnu, men er vi stadig godt tilfredse med det vi har fået lavet i projektet. Vi formår at samle information fra flere forskellige droneforhandlerne ved hjælp af web crawling, som vi laver til produkter som markedsføres på vores prissammenlings hjemmeside.

Refleksion

Det har været godt at få lov til at arbejde med web scraping, da det har lært os, hvordan man henter data ned fra internettet, som så efterfølgende kan analyseres og gemmes til videre brug. Web scraping kan bruges i mange forretningssammenhænge, og vi fandt det oplagt at bruge i forbindelse med affiliate marketing, hvor man markedsfører andre virksomheders produkter. Her kan web scraping hjælpe med at hente en helt masse data om produkter, som gør opsætning og markedsføring af produkter hurtigere og nemmere. Det gør at man hurtigere kan opskalere affiliate forretninger, og det giver en konkurrencemæssig fordel i forhold til konkurrenter

Vi arbejder begge med affiliate marketing til dagligt, og derfor fandt vi læring og arbejde om web scraping meget brugbart. Især det med at vi har fået så mange praktiske erfaringer, hvor den teoretiske viden er blevet koblet ovenpå. Vi har fået en masse virkelighedsnært læring, og det er noget vi kan helt sikkert kan bruge i erhvervslivet senere hen.

Perspektivering

Hvis projektet skulle fortsættes, ville det være oplagt at arbejde efter at få hjemmesiden udgivet. Inden vi kan udgive hjemmesiden, skal vi have lavet et godt grafisk design. Det har vi ikke vægtet særlig højt i dette projekt, da vi har fokuseret mere på det tekniske. Vi mangler også at få opsat en online database hos vores web host. Der er en helt masse små opgaver, som vi kan arbejde videre med. Når sitet så kommer op at kører, kan vi arbejde på at optimere vores crawler yderligere. Vi har fx tænkt på at man kunne lave nogle grafer på det data vi crawler, som vi eller andre kan bruge til analyse.

2 KOMMENTARER

  1. Hej!
    Først og fremmest synes jeg det er en rigtig god blog du har.
    Jeg har et spørgsmål i forhold til dit praktikforløb på datamatiker uddannelsen.
    – Har du lagt din praktikrapport op et sted? Jeg kunne godt tænke mig at se din formulering på en sådan rapport.

    Tak på forhånd 🙂

EFTERLAD ET SVAR

Please enter your comment!
Please enter your name here