su13_csharp_tenta_facit

Sida 1/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Tentamen, delkurs C#
Systemutvecklare SU13, Malmö
Facit & rättningsmall
Plats: Tid:
Plushögskolan Malmö
09.00-13.00
Tillåtna hjälpmedel:
Papper, penna, suddgummi.
Ej tillåtna hjälpmedel:
Datorer, telefoner, böcker, anteckningar, kompendier etc.
Max poäng:
120 poäng
Del 1, slutna svar: 50 poäng
Del 2, öppna svar: 50 poäng
Inlämningsuppgift: 20 poäng (avser tidigare gjord gruppinlämningsuppgift
”Tic-Tac-Toe”, som räknas in i poängen enligt följande:
Ej gjord/U = 0 poäng, G = 15 poäng, VG = 20 poäng)
Betygsgränser:
Godkänt
75 poäng
Väl godkänt
95 poäng
Examinator:
Thomas Frank, Nodebite AB
Sida 2/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Del 1, slutna svar, facit
Instruktioner:
Läs igenom frågorna på följande sidor och välj svarsalternativ.
FYLL I DITT NAMN (!) och kryssa i dina svar på denna sida.
(Mer än ett ikryssat svar per fråga ger 0 poäng på frågan.)
Lämna endast in denna sida för del 1.
Namn:
Fråga 1-20 (1 poäng per rätt svar)
Fråga 21-35 (2 poäng per rätt svar)
1
a
b
c x
d
21
a
b x
c
d
2
a x
b
c
d
22
a x
b
c
d
3
a
b
c
d x
23
a
b x
c
d
4
a
b x
c
d
24
a
b
c x
d
5
a
b
c
d x
25
a
b
c
d x
6
a
b
c
d x
26
a
b
c x
d
7
a
b
c
d x
27
a
b x
c
d
8
a x
b
c
d
28
a x
b
c
d
9
a
b
c x
d
29
a
b
c x
d
10
a
b
c
d x
30
a
b
c x
d
11
a
b x
c
d
31
a
b x
c
d
12
a
b x
c
d
32
a
b
c
d x
13
a x
b
c
d
33
a x
b
c
d
14
a
b x
c
d
34
a
b
c
d x
15
a
b
c x
d
35
a
b x
c
d
16
a
b x
c
d
17
a x
b
c
d
18
a x
b
c
d
19
a
b x
c
d
20
a
b
c
d x
Sida 3/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Fråga 1: Agil Metodik & SCRUM
(10 poäng totalt)
a) Beskriv med egna ord anledningen till att agil metodik behövs
och utvecklades.
(2 poäng)
Ett poäng ges för vart och ett av dessa begrepp:
bättre måluppfyllelse, högre kvalitet, snabbare utveckling, mer transparent process,
bättre kundkontakt, premierar kompetensutveckling,
nöjdare kund, flexiblare arbetssätt, bättre arbetsmiljö.
ELLER: Begrepp som motsvarar dessa.
MEN: Bara under förutsättning att begreppens relevans motiveras!
b) Återge de fyra hörnstenarna/nyckelprinciperna i det agila manifestet.
Anknyt varje princip till ett verklighetsnära exempel.
(4 poäng)
Ett poäng ges för vart och ett av dessa begrepp, samt (ganska snällt rättat) exempel på
dem, behöver inte alls vara exakt ordalydelse:
• Individer och interaktioner framför processer och verktyg.
• Fungerande programvara framför omfattande dokumentation.
• Kundsamarbete framför kontraktsförhandling.
• Anpassning till förändring framför att följa en plan.
c) Förklara hur man arbetar med SCRUM-metodik och väv gärna in
följande termer: produkt, produktägare, produkt-backlog, epics, user
stories, tasks, scrum master, sprintplanering & pokerplanning, sprint,
sprint backlog, retrospective-möte, daily standup, burn down chart,
samt spike.
(4 poäng)
En halv poäng ges per korrekt förklarat begrepp bland de som listas ovan.
Sida 4/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Fråga 2: In your arms
(14 poäng totalt)
Du ska skapa en applikation där personer har armar, armarna har händer
och händerna har fingrar. I övrigt ska varje persons ha namn, ålder och
kön.
Man ska kunna be en arm att peka. Armen ska då lyftas, säga till sin hand
att peka, varvid handen ska säga till sitt pekfinger att sträcka ut sig och
övriga fingrar att dra in sig mot handflatan. (Du behöver inte göra något
grafiskt här – det räcker med konsolmeddelanden där armen, handen och
fingrarna meddelar vad de gör.)
a) Hur löser du detta objektorienterat? Vilken/vilka klasser skapar du?
Vilka egenskaper och/eller metoder har klassen/klasserna?
Ange även typ för egenskaper och metoder!
(4p)
class Person (egenskaper: string Name, int Age, string Gender (eller bool Male etc),
List<Arm> Arms, int NumberOfArms, metod: konstruktor)
class Arm (egenskaper: Hand MyHand, metoder: konstruktor, void Point, void Lift)
class Hand (egenskaper: List<Finger> MyFingers, metoder: konstruktor, void Point)
class Finger (metod: void Fold, samt Point om underklass IndexFinger ej används)
class IndexFinger (ärver av Finger, metod: void Point)
En halv poäng per korrekt klass (underklass undantaget), en halv poäng per rimlig listning
av egenskaper och metoder inom en klass, konstruktor behöver ej vara med. Varianter
på typer som fungerar logiskt godkännes.
b) Löser du problemet med arv eller komposition? Eller bådadera?
Förklara och motivera! Visa att du förstår dessa två begrepp och
skillnaden mellan dem. (2p)
En poäng för rätt svar (i detta fall komposition eller arv + komposition).
En poäng för korrekt motivering, t.ex.: Jag löser uppgiften med uteslutande komposition,
då det inte finns några lämpliga arv – inga klasser som är av samma ”grundtyp”, däremot
finns det gott om objekt som behöver andra objekttyper som egenskaper (dvs.
komposition): En person har armar, en arm har en hand, en hand har fingrar.
Eller: Jag löser uppgiften med arv + komposition. Motivering som ovan vad gäller
komposition, samt motivering för arv är fingrar (ett pekfinger är en underklass av finger
etc.)
Sida 5/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
c) Skriv C#-kod eller pseudokod för armens peka-metod, samt de övriga
metoder som kommer att anropas/köras när den körs.
(4 poäng + 1 extrapoäng för helt korrekt C#-kod)
På följande två sidor finns en fungerande kodlistning för hela applikationen.
För att få fyra poäng på denna fråga krävs att man har med korrekt kod/logik
för följande metoder:
Arm.Point()
– rad 39-44
Hand.Point()
– rad 65-75
Finger.Fold()
– rad 80-83
IndexFinger.Point()
– rad 88-91
/ eller Finger.Point() om man inte använder underklasser
Trevligt är även kod för Arm.Lift() – rad 46-50 – och har man med denna metod
uppväger det mindre brister i övriga metoder.
En poäng per korrekt skriven metod. (I vissa fall istället en poäng för bra sammanhang.)
(Hyfsat) korrekt C#-kod istället för pseudokod ger en extra poäng.
d) En person skapas initialt med 2 armar. Skriv C#-kod eller pseudokod
för en setter som gör att man kan ändra antalet armar på en person
efter att han/hon skapats – dock endast till ett lägre värde än initialt
och som lägst till 0 stycken.
(2p + 1 extrapoäng för helt korrekt C#-kod)
På följande två sidor finns en fungerande kodlistning för hela applikationen.
För att få två poäng på denna fråga krävs att man har med kod motsvarande logiken i
rad 20-27, samt någon typ av förklaring av hur det satta värdet samspelar med de
faktiska antalet objektinstanser av armar en person har, t.ex. utgör gettern på rad 16-19
en sådan förklaring.
En poäng per för korrekt skriven setter.
En poäng för visad koppling mellan personens armobjekt och get/setter för
antal armar.
(Hyfsat) korrekt C#-kod istället för pseudokod ger en extra poäng.
Sida 6/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
public class Person
{
public List<Arm> Arms { get; set; }
public Person()
{
Arms = new List<Arm>();
for (var i = 0; i < 2; i++)
{
Arms.Add( new Arm() );
}
}
public int NumberOfArms
{
get
{
return Arms.Count;
}
set
{
while (value < Arms.Count && value >= 0)
{
Arms.RemoveAt( Arms.Count - 1 );
}
}
}
}
public class Arm
{
public Hand MyHand { get; set; }
public Arm()
{
MyHand = new Hand();
}
public void Point()
{
Lift();
Console.WriteLine( "Telling the hand to point.. " );
MyHand.Point();
}
Sida 7/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
public void Lift()
{
Console.WriteLine( "Lifting this arm!" );
}
}
public class Hand
{
public List<Finger> MyFingers { get; set; }
public Hand()
{
MyFingers = new List<Finger>();
for (var i = 0; i < 5; i++)
{
MyFingers.Add( i == 1 ? new IndexFinger() : new Finger() );
}
}
public void Point()
{
Console.WriteLine( "I'm a hand - I tell the fingers what to do!" );
for (var i = 0; i < 5; i++)
{
dynamic f = MyFingers[i];
Console.WriteLine(
f.GetType().Name == "IndexFinger" ? f.Point() : f.Fold()
);
}
}
}
public class Finger
{
public string Fold()
{
return "Folding a finger!";
}
}
public class IndexFinger : Finger
{
public string Point()
{
return "Pointing an index finger!";
}
}
Sida 8/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Fråga 3: Business as usual
(26 poäng totalt)
Du skriver en applikation som ska kunna hantera data om olika företag.
Varje företag har ett namn, ett organisationsnummer, en eller flera ägare
(personer och/eller andra företag), samt noll till flera anställda.
a) Hur löser du detta objektorienterat? Vilken/vilka klasser skapar du?
Vilka egenskaper och/eller metoder har klassen/klasserna?
Ange även typ för egenskaper och metoder!
(6p)
class Company
egenskaper: string Name, string OrgNumber,
List<dynamic> Owners, List<Employee> Employees
metoder: konstruktor, string Ownership
class Person
egenskaper: string Name, string PersonNumber
metod: (ej nödvändig) kontruktor
class Employee (ärver av Person)
Company bör ha en konstruktor som föhindrar att det går att skapa företag utan minst
en ägare, samt kontrollerar att ägaren är ett annat företag eller person.
(Alternativt kan man ha en mellanklass Owner som måste ha ett företag eller person
kopplad till sig – då klarar man sig om man vill utan throw-statements.)
Kommentar: Även long godkännes som datatyp för OrgNumber och PersonNumber.
Dock inte int (som inte rymmer ett så långt nummer). Det är inte nödvändigt att ha med
klassen Employee (i så fall ersätts den ovan i listorna med Person). Det är inte nödvändigt
att ha med PersonNumber.
Ett poäng ges per korrekt klass (dock högst två poäng)
Ett halvt poäng ges per korrekt egenskap (dock högst tre poäng)
Ett poäng ges om man inser och nämner varför Company bör ha en konstruktor.
Varianter på typer som fungerar logiskt godkännes.
Sida 9/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
b) Löser du problemet med arv eller komposition? Eller bådadera?
Förklara och motivera! Visa att du förstår dessa två begrepp och
skillnaden mellan dem.
(3p)
En poäng för rätt svar (i detta fall komposition eller arv + komposition).
Två poäng för korrekt motivering, t.ex.: Jag löser uppgiften med uteslutande komposition,
då det inte finns några lämpliga arv – inga klasser som är av samma ”grundtyp”, däremot
finns det ett objekt som behöver andra objekttyper som egenskaper (dvs. komposition):
Ett företag behöver personer och företag som ägare.
Eller: Jag löser uppgiften med arv + komposition. Motivering som ovan vad gäller
komposition, samt motivering för arv är att en anställd är en underklass till person.
c) Skissa/rita upp ett grafiskt gränssnitt där man kan mata in personer
och företag, samt lägga till och ta bort ägare och anställda. Ange gärna
vilken typer av komponenter du vill
använda dig av. Kan du inte namnen så beskriv hur de fungerar (”fäller
ner en lista” etc.)
(6p)
Det finns många grafiska lösningar på denna fråga. På denna och följande sidor
ges ett förslag.
Grundvy (innan man har markerat person
Poängbedömning enligt
eller företag, se nästa sida för detta):
(en poäng per punkt):
•
Skapa (& gärna radera) personer.
•
Skapa (& gärna radera) företag.
•
Lägga till och ta bort
ägare i företag (flera).
•
Lägga till och ta bort
anställda i företag (flera).
•
Företag kan inte skapas
utan minst en ägare.
•
Beskrivning av komponenter.
Sida 10/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Info-vy när man har markerat en person:
Info-vy när man har markerat ett företag:
OBS: Redigera-vyerna &
Lägg till ny-vyerna är lika
(men Lägg till ny startar
utan uppgifter ifyllda.)
OBS: Man kan INTE spara ett
företag innan det har minst
en ägare. (Spara-knappen är
disablad till dess.)
Redigera-vy för person
Redigera-vy för företag
Rubriker ovanför rutor är labels. Alla boxar med scrolllister är listboxar. Allt som ser ut som knappar
är knappar. I redigera-vyerna är namn, pnr och org.nr-fälten redigerbara textboxar utan border.
Sida 11/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
d) Ge exempel på en JSON-datastruktur som skulle fungera för att lagra
datan mellan körningar. (4p)
Ett exempel på JSON-datastruktur som godkänns är:
{
"persons": [
{
"Name": "Person Name",
"PersonNumber": "XXXXXX-XXXX",
"isEmployee": true
id: "P1"
}
],
"companies": [
{
"Name": "Person Name",
"PersonNumber": "XXXXXX-XXXX",
id: "C1",
"OwnerIDs": ["P1","C2"], "EmployeeIDs": ["P1","P3] ] }
}
Poäng enligt nedan:
• En poäng ges för ett JSON-objekt används för huvudstrukturen och håller de olika
objekttyperna (employees för sig, personer för sig godkänns).
• En poäng till ges om objekttyperna från programmet finns med som JSON-arrayer
(companies, persons, samt eventuellt employees).
• En poäng ges om JSON-objekten är korrekt genomförda med specificerade
egenskaper som motsvarar klassernas egenskaper.
• En poäng för den som löser problemet med att man kan få cirkulära referenser och
objekt som dubbellagras genom att istället för objekt i Owners och Employeesarrayerna använda någon form av id-system för referens.
e) Vilken tillvägagångssätt använder du för att spara datan mellan
körningar. (2p)
Det ger en poäng att beskriva att man kan skapa en settings-variabel via
Application -> Properties -> Settings.settings (med scope User).
Det ger ytterligare en poäng att beskriva att denna kan läsas och skrivas via C#, bör
vara av typen string och att man med hjälp av ett JSON-bibliotek kan
serialisera/deserialisera objektinstanser till JSON och spara i denna settingsvariabel.
Sida 12/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
Inga kodexempel är nödvändiga, men kan fungera som alternativ till ovanstående
förklaringar. Alternativa lösningar som går ut på att explicit be användaren spara och läsa
saker från disk eller använda andra dataformat än JSON godkänns om de är väl
förklarade.
f) Skriv C#-kod eller pseudokod som gör att man om företag äger
företag kan se ägandeskapet i flera led.
(4 poäng + 1 extrapoäng för helt korrekt C#-kod).
På följande två sidor finns en fungerande kodlistning för hela applikationens logiska del
(dvs. ej event handlers eller grafiska kontroller).
Denna delfråga löser man med en rekursiv metod (eventuellt med en icke-rekursiv
”ingångsmetod”). Ett exempel på en sådan lösning hittar du på rad 45-63 i kodlistningen.
En poäng ges för försök till lösning med rekursiv while-sats (vilket inte fungerar
Generellt I detta fall då det inte råder ett ett-till-ett-förhållande från företag till
ägande företag.)
Två till fyra poäng ges för försök till lösning med rekursiv metod.
(Fyra poäng om lösningen är fullt fungerande logiskt sett, tre poäng vid mindre fel..)
(Hyfsat) korrekt C#-kod istället för pseudokod ger en extra poäng.
Kodlistning:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
public class Person
{
public string Name { get; set; }
public string PersonNumber { get; set; }
public Person(string name,string pNo){
Name = name;
PersonNumber = pNo;
}
}
public class Employee : Person
{
public Employee(string name, string pNo) : base(name, pNo) { }
}
Sida 13/14
Tentamen delkurs C#, Systemutvecklare, SU13, Malmö
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
public class Company
{
public string Name { get; set; }
public string OrgNumber { get; set; }
public List<dynamic> Owners {get; set;}
public List<Employee> Employees { get; set; }
public Company(string name, string orgNo, params dynamic[] owners)
{
// Make sure we have at least one owner
if( owners.Length < 1 )
throw new System.ArgumentException(
"Must have at least one owner.", "owners"
);
// Make sure the owners are persons, employees or companies
for(var i = 0; i < owners.Length; i++){
var type = owners[i].GetType().Name;
if ( ",Company,Person,Employee,".IndexOf( "," + type + ",") < 0 )
throw new System.ArgumentException(
"Persons and/or companies", "owners"
);
}
Name = name; OrgNumber = orgNo;
Employees = new List<Employee>();
Owners = new List<dynamic>();
Owners.AddRange(owners);
}
public string Ownership()
{
return Name + " is owned by:\n" + Ownership(this,1);
}
private string Ownership(Company company, int level){
var owners = company.Owners;
var report = "";
for(var i = 0; i < owners.Count; i++){
for (var j = 0; j < level-1; j++) report += "\t";
report += owners[i].Name + "\n";
if (owners[i].GetType().Name == "Company")
{
report += Ownership(owners[i], level+1);
}
}
return report;
}
}