Richtlijnen Specificaties Multiple inheritence H9: Klasse Ontwerp.
-
Upload
guido-willemsen -
Category
Documents
-
view
218 -
download
0
Transcript of Richtlijnen Specificaties Multiple inheritence H9: Klasse Ontwerp.
Richtlijnen
Specificaties
Multiple inheritence
H9: Klasse Ontwerp
2
SchetsPlus...doe ik het goed ?
Hoe maak ik goede klassen ?
We gaan kijken naar:algemene ontwerp-richtlijnensoftware metric
Complement: style-gidsen, tips, best practices, kookboeken, enz.
Sun’s Java Coding Style Guide
Ambler, the Elements of Java Style
3
Richtlijnen
Structuur is belangrijk, wat je niet wil:complex fouten, onderhoudkoststar
Optimaliseer :encapsulatieinheritencecohesiekoppeling
4
Cohesie
Een “module” is cohesief als het een set van sterk aan elkaar gerelateerd “functionaliteiten” aanbiedt.
5
PersoongetGewicht()getLengte()
PersoongetGewicht()getLengte()
getVrienden()
PersoongetGewicht()getLengte()
addInAdresBoek(aboek)
Koppeling
Er is een koppeling tussen modules A en B als een van de andere afhankelijk is.
Voorbeelden:
datakoppeling
globale-var koppeling
6
f() { ... u.g(x) ... }
• m1,m2 via een static attribuut
•C1, C2 via een package-private attribuut
Koppeling
Pathologisch
in C++ heb je ook friends.
7
Drank- suiker : int- water : int+ zoet() : int
+ roer()
Mixer
if (drank.zoet() > 10) { drank.water++ ; drank.roer() ;}
Koppeling
In OO ook door:Associatie / navigatieVerse objecten in methodeVia inheritence
Vaak spanningveld tussen koppeling en de andere aspecten:maak A subklasse van B koppelingverhoogt cohesie met delegatie koppeling
8
Inheritence koppeling
9
PersoongetKinderen()
Klant
DrankmixMetMelk() // concreet
abstract mix()
Thee
Koffie
Demeter Principe
Ian Holland, 1987
“Zorg dat objecten alleen met vrienden praten.”
Delegeer:
10
VliegtuigbagageGewicht() :
int
Persoonnaam
vervoert*
Tasgewicht
heeft *
VliegtuigbagageGewicht() :
int
Persoonnaam
tassenGewicht()
vervoert * Tasgewicht
heeft *
ten koste van de cohesie van Persoon.
Connascance
Page-Jones, 1992.
Letterlijk: tegelijkertijd geboren.
Page-Jones: Klassen C en D zijn connascent als het mogelijk is om C aan te passen die een aanpassing van D dwingt.
koppeling!
11
Uit project management perspectief
Software metriek complexiteit indicatoren
Om strategisch te beslissen dat bepaalde delen van de software een risico factor zijn, en dat reorganisatie nodig is.
Voor programmeurs ook nuttig als richtlijnen.
12
Voorbeeld
Metriek :
+ Uit te rekenen (en goedkoop) tools!- abstract
Zoals, #regels
Nog meer? Traditionele metrieken HalsteadMcCabeOviedo
OO metriek“de” metriek bestaat niet ze zijn allemaal indicatoren.
13
HalsteadComplexiteit: moeite om code te lezen
E = D * V
14
x = x + x ; x++ x = x + y ; z++
(alleen ter info)
McCabe
Het aantal lineair onafhankelijke paden in je programma.
15
int P() { if (...) return 100 else return 0}
0
12
Control Flow Graph (CFG)
McCabe
16
0
13
2
4
5
Oviedo
Splits programma in sequentiële blokkeninteracties tussen elementen in een blok voegen niets
aan complexiteit.afhankelijkheden tussen blokken wel.
Voorbeeld:
17
P(int x, int y) { if (y>0) x = 0 ; else x = 1 ;
return x}
(y>0) ; x = 0 (~y>0) ; x = 1
return x
DF = 2 DF = 2
DF = 2DF(P) = 6
OO metriek
Voor OO willen we ook indicatie hebben over structurele complexiteit van je klassen.
Chen & Lu, 1993:EncapsulatieKoppeling InheritenceCohesie
18
Encapsulatie (P)
Idee:Methode met minder argumenten is abstracterSimpel vs complex parameters, bijvoorbeeld:
P = som van de complexiteit van de argumenten (van pub. methodes) in C.
19
Type Complexiteit waarde
boolean, int 0
double 2
object 6-9
Koppeling (Cp)
IdeeC gebruikt D 1x koppelingC wordt door D gebruikt 1x koppelingwederzijde koppeling lastig telt als extra
Cp = som van boven.
20
Cohesie Co
Hoe weten we welke methode bij elkaar horen??Idee: methodes met dezelfde type signatuur horen
vaak bij elkaar.
Chen en Lu ook “sub” signatuur.
m1(int,Vervoer) ~ m2(Vervoer,int,Persoon)
21
Vervoer+ versnel(real)+ addPassagier(Persoon)+ swapPassagiers(Persoon, Persoon)+ addPassagiers (Collection<Persoon>)
Co = G / N = 0.75
Inheritence H
Inheritence is goed (code hergebruik), maar je code wordt ook minder expliciet in zekere zin ook fout gevoelig.
H is een meting van inheritence complexiteit. Som van:# methodesinheritence afstand# direct superklassen.# subklassen
22
JHawk
23
Klasse specificatie
Meer kun je niet met klasse diagram uitdrukken...
Een klant is een mj als zijn/haar leeftijd ≤ 18
De klant die voor een mj verantwoordelijk is, is zelf geen mj..
24
KlantNaamLeeftijd
Minderjarigbonus
Videotheek
DVDtitel
leeftijdgrens
*leent
< is verantwoordelijk voor
Klasse invariant
Een klasse invariant van C is een constraint op de attributen van de objecten van C.
Anders zit een object in een verkeerde/onveilig toestand.
Het gaat over de stabiele toestand van een object (dus niet als een operatie nog bezig is met het object).
25
MinderjarigBob10
MinderjarigOcto30
De leeftijd van een mj is 18.
Klasse invariant
Maar indirect gaat het eigenlijk ook over associaties...
Hoe belangrijk? erg belangrijk.26
MinderjarigBob10
DVDSneeuwwit
0+
DVDStar Trek
10+
DVDKill Bill
12+
leent
Hoe druk je dat uit?
Met “predicaten” zoals in Logica :
“Object Constraint Language” (OCL) onderdeel van UML.
27
(forall x : Minderjarig x.leeftijd 18)
context x : Minderjarig inv: x.leeftijd 18
Navigatie in OCL
28
KlantNaamLeeftijd
DVDtitel
leeftijdgrens
*leent >
dvdslener
context dvd : DVD inv: dvd.lener.leeftijd dvd.leeftijdgrens
levert een verzameling terug!
Collecties in OCL
Zoals Set en SequenceOperatoren zoals:
size(), sum(), isEmpty()includes(x)forAll(...), exists(...), select(…)
Eigenaardig syntax:
u isEmpty()u includes(x)
29
Voorbeeld
30
KlantNaam
Leeftijd
DVDtitel
leeftijdgrens
*leent
dvdslener
inv: x.dvds forall (dvd | x.leeftijd dvd.leeftijdgrens)
Filter select operatie
31
KlantNaam
Leeftijd
DVDtitel
premium : boolean
*leent
dvdslener
Je mag slechts één permium DVD lenen.
context x : Klantinv: x.dvds select (dvd | dvd.premium = true) size() ≤ 1
Methode specificeren
32
Klantinschrijf()leen(d)
getLeenLimiet()
forall x : Klant { true } x.inschrijf() { x.dvds = }
context x : Klant:: inschrijf()pre: truepost: x.dvdsisEmpty()
declaratief !
Inschrijf() dient de collectie van gelende dvds op leeg te zetten
Pre/Post spec, pseudo code, geen
OCL.
Mix in specificatie met “query”
33
Klantinschrijf()leen(d)
getLeenLimiet()Je mag niet meer dan je limiet lenen.
context x : Klant:: leen(d)
pre: x.dvds size() + 1 ≤ x.getLeenLimiet()
post: x.dvds = x.dvds@pre insert(d)
markeer als ‘isQuery’, maar alleen als side-effect vrij!
Multiple inheritence
Krachtig !Je kunt makkelijk verschillende features erven.
Talen met MI C++. Eiffel, PythonOm uit te kijken diamantprobleemAls je toch in Java wil implementeren …
34
ProductID
NaamPrijs
Koffie
GroteBestellingkoopGroot(n)
ImportGoedinvoerBelasting()
Feature clash…
Geen echte issue. Eiffel renaming
35
Werknemerwerk()
Muzikant
Artiestwerk()
Welke werk() wordt bedoelt in Muzikant ?
(soms de ene soms de andere)
class Muzikant inherit Werknemer rename werk as werk1 Artiest rename werk as werk2feature…end
Diamantprobleem
Een muzikant kan in principe 2x namen en leeftijden erven.leefdtijd onzinnig merge tot 1xnaam misschien wil je een echte naam en een
artiestnaam.Ambigu compiler kan deze niet zelf beslissen…
36
Werknemer Artiest
Muzikant
PersoonNaamLeeftijd
Inheritence vs associatie
37
ArtiestNaamWerk()
Muzikant Muzikant
ArtiestNaamWerk()
W
MI Delegatie
Feature erven Ja Ja
Is M ook een A ? Ja Nee
Simuleren met assoc + interface
38
ArtiestNaamWerk()
Muzikant
MuzikantArtiestNaamWerk()
W
WArtiest (Interface)
Werk()
Gedoe ..
Als MI essentieel in je ontwerp is, implementeer ook in een MI taal.
Anders haal MI uit je ontwerp.
Andere overweging: persistence.