Richtlijnen Specificaties Multiple inheritence H9: Klasse Ontwerp.

Post on 18-Jun-2015

218 views 0 download

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)

wishnu
N2/n2 --> the reverse of the average usage frequency of the words.So, D ~ n1 / freq2

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.