Fondamenti di Informatica T2 Modulo 2 - unibo.it

48
Università di Bologna A.A. 2008/2009 Fondamenti di Informatica T2 Modulo 2 Università degli Studi di Bologna Facoltà di Ingegneria Corso di Laurea in Ingegneria Informatica Anno accademico 2008/2009 2 Veicoli 2 Si desidera realizzare una o più classi che permettano di modellare diverse tipologie di veicolo. Come per il caso della categoria concettuale animale, un veicolo rappresenta una categoria concettuale astratta Non possono esistere istanze di veicolo, perché NON ESISTE UN VEICOLO QUALSIASI Le istanze apparterranno invece alle sue sottoclassi concrete

Transcript of Fondamenti di Informatica T2 Modulo 2 - unibo.it

Page 1: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

Fondamenti di Informatica T2

Modulo 2

Università degli Studi di Bologna

Facoltà di Ingegneria

Corso di Laurea in Ingegneria Informatica

Anno accademico 2008/2009

2

Veicoli

2

• Si desidera realizzare una o più classi che permettano di

modellare diverse tipologie di veicolo.

• Come per il caso della categoria concettuale animale, un

veicolo rappresenta una categoria concettuale astratta

• Non possono esistere istanze di veicolo, perché NON

ESISTE UN VEICOLO QUALSIASI

• Le istanze apparterranno invece alle sue sottoclassi

concrete

Page 2: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

3

Veicoli

3

• L’entità astratta veicolo è caratterizzata da:

– la marca, che rappresenta la casa costruttrice del

veicolo

– il modello, che rappresenta la versione di veicolo

realizzata dalla casa costruttrice

• ed è descritta tramite:

– la tipologia del veicolo

– lo scopo per cui il veicolo viene impiegato (es. trasporto

persone, trasporto merci, etc.)

– il luogo in cui si muove il veicolo (es. terra ferma, aria,

etc.)

– il mezzo tramite cui si muove il veicolo (es. ruote,

superfici alari, etc.)

4

Veicoli

4

• L’entità astratta veicolo verrà quindi modellata tramite la classe astratta Veicolo, caratterizzata da:

– metodi accessor per accedere alla marca e al modello

del veicolo

– un insieme di metodi per accedere alle stringe

descrittive del veicolo; quindi per accedere a:

• la tipologia del veicolo (tipologia)

• lo scopo per cui il veicolo viene impiegato (scopo)

• il luogo in cui si muove il veicolo (doveSiMuove)

• il mezzo tramite cui si muove il veicolo (siMuoveTramite)

– La rappresentazione a stringa di veicolo (toString)

Page 3: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

5

Veicoli

5

• La rappresentazione interna di un veicolo in termini di

marca e modello, è indipendente dallo specifico veicolo

• Una prima rappresentazione a stringa del veicolo (tramite la toString) può essere definita indipendentemente dallo

specifico veicolo, in termini della sua rappresentazione

interna e delle stringhe descrittive

6

Veicoli

6

• Le stringhe descrittive associate all’entità veicolo dipendono

dallo specifico veicolo modellato

→ è impossibile definire in Veicolo i metodi associati alle

stringhe descrittive

→ i metodi associati alle stringhe descrittive devono essere

astratti

toString utilizza i

metodi astratti!

Page 4: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

7

Veicoli

7

• Una possibile classificazione per i veicoli:

Si muove in aria

Si muove sulla terra ferma

• Non è ancora possibile definire i restanti metodi astratti

→VeicoloAereo e VeicoloTerrestre sono entrambe

classi astratte

8

Veicoli

8

• Aereo e Aliante rappresentano due possibili sottoclassi

concrete di VeicoloAereo:

Page 5: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

9

Veicoli

9

• Aereo modella l’entità veicolo aereo

– la cui tipologia è Aereo

– che si muove in aria (eredita da VeicoloAereo)

– tramite superfici alari e organo propulsore

– è adibito al trasporto di persone o merci

è possibile definire i

restanti metodi astratti!

10

Veicoli

10

Un aliante è caratterizzato anche dal numero di posti

disponibili e dalla dimensione dell’apertura

alare (espressa in metri)

vengono aggiungte nuove

informazioni rispetto algenerico veicolo

la toString di Veicolo

viene ridefinita

• Aliante modella l’entità aliante

– la cui tipologia è Aliante

– che si muove in aria (eredita da VeicoloAereo)

– tramite superfici alari, senza alcun organo propulsore

– è adibito solo al trasporto di persone

Page 6: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

11

Veicoli

11

• AereoDiLinea rappresenta una possibile specializzazione

di Aereo:

12

Veicoli

12

Un aereo di linea è caratterizzato anche dal

numero di posti disponibili

aggiunge nuove

informazioni rispetto algenerico veicolo …

• AereoDiLinea modella l’entità aereo di linea

– la cui tipologia è Aereo di Linea

– che si muove in aria (eredita da VeicoloAereo)

– tramite superfici alari e organo propulsore (eredita da Aereo)

– è adibito solo al trasporto di persone (ridefinisce scopo

definito in Aereo)

Page 7: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

13

Veicoli

13

• Autovettura e Autocarro rappresentano due possibili

sottoclassi concrete di VeicoloTerrestre:

14

Veicoli

14

• Autovettura modella l’entità autovettura

– la cui tipologia è Autovettura

– che si muove sulla superficie terrestre (eredita da VeicoloTerrestre)

– tramite ruote

– è adibita solo al trasporto di persone

Un’autovettura è caratterizzata anche dal

numero di posti disponibili

aggiunge nuove

informazioni rispetto algenerico veicolo …

Page 8: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

15

Veicoli

15

Un autocarro è caratterizzato da una capacità massima

di carico (espressa in quintali) e dal tipo di ruote

aggiunge nuove

informazioni rispetto algenerico veicolo …

• Autocarro modella l’entità autocarro

– la cui tipologia è Autocarro

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote

– è adibito solo al trasporto di merce

16

Veicoli

16

• Automobile e Autobus rappresentano due possibili

specializzazioni di Autovettura:

Page 9: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

17

Veicoli

17

Un’automobile è caratterizzata anche dalnumero di porte e dal

numero di volumi

aggiunge nuove

informazioni rispetto allagenerica autovettura …

• Automobile modella l’entità automobile

– la cui tipologia è Automobile

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote (eredita da Autovettura)

– è adibita solo al trasporto di un numero limitato di persone (ridefinisce scopo definito in Autovettura)

18

Veicoli

18

• Autobus modella l’entità autobus

– la cui tipologia è Autobus

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote (eredita da Autovettura) ed

– adibito solo al trasporto di una collettività di persone (ridefinisce scopo definito in Autovettura)

Page 10: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

19

Veicoli

19

• Furgone rappresenta una possibile specializzazione di

Autocarro:

20

Veicoli

20

Un furgone è caratterizzata anche dal

fatto di essere finestrato o meno

aggiunge nuove

informazioni rispetto algenerico autocarro …

• Furgone modella l’entità furgone

– la cui tipologia è Furgone

– che si muove sulla terra ferma (eredita da VeicoloTerrestre)

– tramite ruote (eredita da Autocarro) ed

– adibito solo al trasporto di merce (eredita da Autocarro)

Page 11: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

21

• Si desidera avere la seguente organizzazione dei

package:

Veicoli

veicoli

Veicolo.java

Cartella

di lavoro

Test.java

Furgone.java

22

import veicoli.*;

public class Test

{

public static void main(String args[])

{

Veicolo v[] = {

new Autovettura("Mercedes-Benz", "Berlina", 4),

new Automobile("Fiat", "Panda", 5, 5, 2),

new Autobus("Mercedes-Benz", "O530 Citaro", 28),

new Furgone("Volkswagen", "Caddy", 510,

"singole", false),

new AereoDiLinea("Boeing", "707-300", 250),

new Aliante("Briegleb", "BG 12", 1, 15.24) };

22

È possibile fare ciò perché sono anche oggetti di tipo Veicolo!

Testing

Page 12: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

23

for(int i = 0; i < v.length; i++)

{

System.out.println(v[i]);

}

}

}

23

Testing

• Tramite il polimorfismo verranno richiamati i metodi definiti

dall’oggetto effettivamente referenziato. Ad esempio:

– quando viene stampato l’oggetto v[3], verrà richiamata la

toString definita per gli oggetti della classe Furgone

– la toString di v[0] richiamerà il metodo tipologia

(definito come metodo astratto nella classe Veicolo)

definito per gli oggetti della classe Autovettura

24

Soluzione - Veicoli

package veicoli;

public abstract class Veicolo

{

protected String marca;

protected String modello;

public Veicolo(String marca, String modello)

{

this.marca = marca;

this.modello = modello;

}

}

24

Page 13: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

25

Soluzione - Veicoli…

public String getMarca()

{

return marca;

}

public String getModello()

{

return modello;

}

public String toString()

{

return tipologia() + " " + marca + "/" + modello

+ ": veicolo " + scopo() + ", si muove "

+ doveSiMuove() + " tramite “

+ siMuoveTramite() + ".";

}

… 25

Metodi accessor.Metodi accessor

26

Soluzione - Veicoli

public abstract String tipologia();

public abstract String scopo();

public abstract String doveSiMuove();

public abstract String siMuoveTramite();

26

Metodi astratti

Page 14: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

27

Soluzione - Veicoli

package veicoli;

public abstract class VeicoloAereo extends Veicolo

{

public VeicoloAereo(String marca, String modello)

{

super(marca, modello);

}

public String doveSiMuove()

{

return “in aria”;

}

}

27

28

Soluzione - Veicoli

package veicoli;

public abstract class VeicoloTerrestre extends Veicolo

{

public VeicoloTerrestre(String marca, String modello)

{

super(marca, modello);

}

public String doveSiMuove()

{

return “sulla terra ferma”;

}

}

28

Page 15: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

29

Soluzione - Veicolipackage veicoli;

public class Aliante extends VeicoloAereo

{

private int numeroPosti;

private double aperturaAlare;

public Aereo(String marca, String modello, int

numeroPosti, double aperturaAlare)

{

super(marca, modello);

this.numeroPosti = numeroPosti;

this.aperturaAlare = aperturaAlare;

}

}29

30

Soluzione - Veicoli…

public int getNumeroPosti()

{

return numeroPosti;

}

public double getAperturaAlare()

{

return aperturaAlare;

}

public String tipologia()

{

return “Aliante”;

}

30

Page 16: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

31

Soluzione - Veicoli…

public String scopo()

{

return “adibito al trasporto di persone”;

}

public String siMuoveTramite()

{

return “superfici alari senza organo motopropulsore”;

}

public String toString()

{

return super.toString() + " Il veicolo ha un'apertura

alare di " + getAperturaAlare() + " metri e può

ospitare un massimo di " + getNumeroPosti()

+ (getNumeroPosti() == 1 ? " persona" : "

persone") + ".";

} 31

32

Soluzione - Veicoli

package veicoli;

public class Aereo extends VeicoloAereo

{

public Aereo(String marca, String modello)

{

super(marca, modello);

}

public String tipologia()

{

return “Aereo”;

}

}

32

Page 17: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

33

Soluzione - Veicoli

public String scopo()

{

return “adibito al trasporto di persone o merci”;

}

public String siMuoveTramite()

{

return “superfici alari e organo motopropulsore”;

}

33

34

Soluzione - Veicolipackage veicoli;

public class AereoDiLinea extends Aereo

{

private int numeroPosti;

public AereoDiLinea(String marca, String modello, int

numeroPosti)

{

super(marca, modello);

this.numeroPosti = numeroPosti;

}

public int getNumeroPosti()

{

return numeroPosti;

}

} 34

Page 18: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

35

Soluzione - Veicoli…

public String tipologia()

{

return “Aereo di linea”;

}

public String scopo()

{

return “adibito al trasporto di persone”;

}

public String toString()

{

return super.toString() + " Il veicolo può ospitare un

massimo di " + getNumeroPosti() +

(getNumeroPosti() == 1 ? " persona" : " persone")

+ ".";

}35

36

Soluzione - Veicolipackage veicoli;

public class Autovettura extends VeicoloTerrestre

{

protected int numeroPosti;

public Autovettura(String marca, String modello, int

numeroPosti)

{

super(marca, modello);

this.numeroPosti = numeroPosti;

}

public int getNumeroPosti()

{

return numeroPosti;

}

} 36

Page 19: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

37

Soluzione - Veicoli…

public String tipologia()

{

return “Autovettura”;

}

public String scopo()

{

return “adibito al trasporto di persone”;

}

public String siMuoveTramite()

{

return “ruote”;

}

37

38

Soluzione - Veicoli

public String toString()

{

return super.toString() + " Il veicolo può ospitare un

massimo di " + getNumeroPosti() +

(getNumeroPosti() == 1 ? " passeggero" : "

passeggeri")

+ ".";

}

38

Page 20: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

39

Soluzione - Veicoli

package veicoli;

public class Autocarro extends VeicoloTerrestre

{

protected double capacitàMassima;

protected String tipoRuote;

public Autocarro (String marca, String modello, double

capacitàMassima, String tipoRuote)

{

super(marca, modello);

this.capacitàMassima = capacitàMassima;

this.tipoRuote = tipoRuote;

}

}

39

40

Soluzione - Veicoli…

public String getTipoRuote()

{

return tipoRuote;

}

public double getCapacitàMassima()

{

return capacitàMassima;

}

public String tipologia()

{

return “Autocarro”;

}

40

Page 21: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

41

Soluzione - Veicoli…

public String scopo()

{

return “adibito al trasporto di merci”;

}

public String siMuoveTramite()

{

return “ruote”;

}

public String toString()

{

return super.toString() + " Il veicolo è dotato di

ruote " + getTipoRuote () + " ha una capacità

massima di " + getCapacitàMassima() +

((getCapacitàMassima() == 1) ? " quintale." :

" quintali.");

}41

42

Soluzione - Veicoli

package veicoli;

public class Automobile extends Autovettura

{

private int numeroPorte;

private int numeroVolumi;

public Automobile(String marca, String modello, int

numeroPosti, int numeroPorte, int numeroVolumi)

{

super(marca, modello, numeroPosti);

this.numeroPorte = numeroPorte;

this.numeroVolumi = numeroVolumi;

}

}42

Page 22: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

43

Soluzione - Veicoli…

public int getNumeroPorte()

{

return numeroPorte;

}

public int getNumeroVolumi()

{

return numeroVolumi;

}

public String tipologia()

{

return “Automobile”;

}

43

44

Soluzione - Veicoli…

public String scopo()

{

return “adibito al trasporto di un numero limitato di

persone”;

}

public String toString()

{

String stringaPadre = super.toString();

return stringaPadre.substring(0, stringaPadre.length()

- 1) + ", possiede " + getNumeroPorte() + "

porte, ed è a " + getNumeroVolumi()

+ ((getNumeroVolumi() == 1) ? " volume." :

" volumi.");

} 44

Page 23: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

45

Soluzione - Veicolipackage veicoli;

public class Autobus extends Autovettura

{

public Autobus(String marca, String modello, int

numeroPosti)

{

super(marca, modello, numeroPosti);

}

public String tipologia()

{

return “Autobus”;

}

public String scopo()

{

return “adibito al trasporto collettivo di persone”;

}

}45

46

Soluzione - Veicolipackage veicoli;

public class Furgone extends Autocarro

{

private boolean finestrato;

public Furgone(String marca, String modello, double

capacitàMassima, String tipoRuote, boolean finestrato)

{

super(marca, modello, capacitàMassima, tipoRuote);

this.finestrato = finestrato;

}

public boolean isFinestrato()

{

return finestrato;

}

}46

Page 24: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

47

Soluzione - Veicoli…

public String tipologia()

{

return “Furgone”;

}

public String toString()

{

String stringaPadre = super.toString();

return stringaPadre.substring(0, stringaPadre.length()

- 1) + (isFinestrato() ? " ed è" : " e non è")

+ " finestrato.";

}

47

48

import veicoli.*;

public class Test

{

public static void main(String args[])

{

Veicolo v[] = {

new Autovettura("Mercedes-Benz", "Berlina", 4),

new Automobile("Fiat", "Panda", 5, 5, 2),

new Autobus("Mercedes-Benz", "O530 Citaro", 28),

new Furgone("Volkswagen", "Caddy", 510,

"singole", false),

new AereoDiLinea("Boeing", "707-300", 250),

new Aliante("Briegleb", "BG 12", 1, 15.24) };

48

Soluzione - Veicoli

Page 25: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

49

for(int i = 0; i < v.length; i++)

{

System.out.println(v[i]);

}

}

}

49

Testing

50

Extended Phone Plan

Utilizzando i sorgenti messi a disposizione per Operator e Band, realizzare l’infrastruttura per i

piani tariffari vista in aula, in particolare:

Parte 1

1. Implementare la classe PhonePlan astratta

contenente i servizi base per tutti i PhonePlan

2. Implementare la classe PrecisePlan che realizza

l’algoritmo “preciso” di calcolo dei costi di una chiamata

3. Realizzare i test JUnit necessari alla verifica del corretto funzionamento di PrecisePlan

50

Page 26: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

51

Testing• Evitare di perdere tempo per testare Operator e Band che

sono dati

• Creare Operator e Band di test nel minimo numero

indispensabile

– Un solo Operator

– Due Band:

• Entrambe su tutti i giorni della settimana

• La prima attiva su una parte della giornata, la seconda sulla restante

parte

• Verificare il funzionamento dell’algoritmo di calcolo del

costo della chiamata nel caso in cui la chiamata sia:

– su una sola fascia oraria (un metodo di test)

– a cavallo di due fasce orarie (un altro metodo di test)

51

52

Extended Phone Plan

Parte 1 – Diagramma UML

52

class plans

Precis ePlan

+ getCallCost(Date, Date, String, String) : double

+ PrecisePlan(String, int, int, Operator[])

PhonePlan

- interval: int

- name: String

- operators: Operator ([])

- startCallCost: double

+ getCallCost(Date, Date, String, String) : double

+ getCallCost(Phon eCall) : double

+ getInterval() : int

+ getName() : String

# getOperatorByName(String) : Operator

+ getStartCallCo st() : double

+ isValid() : boolean

# PhonePlan(String, int, int, Operator[])

tlc::Operator

- bands: Band ([])

- name: String

+ getBands() : Band[]

+ getCostPerInterva l(Date) : double

+ getName() : String

+ isValid() : boolean

+ Operator(String, Band[])

- selectBandInDay(DayOfWeekEnum) : Band[]

- validateDay(DayOfWeekEnum) : boolean

tlc::Band

- combinedDays: DayOfWeekEnum ([])

- costPerInterval: double

- endTime: SimpleTime

- startTime: SimpleTime

+ Band(SimpleTime, SimpleTime, DayOfWeekEnum[], double)

+ getCombinedDays() : DayOfWeekEnum[]

+ getCostPerInterval() : double

+ getEndTime() : SimpleTime

+ getStartTime() : SimpleTime

+ isInBand(Date) : boolean

+ isValid() : boolean

+ sortByStartTime(Band[]) : void

-operators

1. .*

-bands 1. .*

Page 27: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

53

Extended Phone Plan

Parte 2

1. Implementare la classe astratta Option

2. Implementare PrecisePhonePlanWithOption

(sottoclasse di PhonePlan)

3. Realizzare i test JUnit necessari alla verifica del

corretto funzionamento di PrecisePhonePlanWithOption:

• Implementare la classe DummyOption che consenta di

verificare il funzionamento:

1. del sistema di override dei parametri del piano – verificare che

il risultato in termini di costi di una chiamata sia quello atteso

2. del sistema di notifica – verificare che il numero di notifiche

effettuate sia quello atteso

53

54

Extended Phone Plan

Parte 2 – Diagramma UML

54

class plans

PhonePlan

- interval: int

- name: String

- operators: Operator ([])

- startCallCost: double

+ getCallCost(Date, Date, String, String) : double

+ getCallCost(Phon eCall) : double

+ getInterval() : int

+ getName() : String

# getOperatorByName(String) : Operator

+ getStartCallCo st() : double

+ isValid() : boolean

# PhonePlan(String, int, int, Operator[])

PrecisePlanWithOptions

- options: Option ([])

- findApplicableOption(Date, Operator, String) : Option

+ getCallCost(Date, Date, String, String) : double

+ getOptions() : Option[]

+ getStartCallCost(Date, Op erator, String) : double

+ PrecisePlanWithOptions(String, int, int, Operator[], Option[])

Option

+ getCostPerInterval() : double

+ getInterval() : int

+ getStartCallCost() : double

+ isApplicable(Date, Operator, String) : boolean

+ notifyIntervalAccounted() : void

+ overridesCostPerInterval() : boolean

+ overridesInterval() : boolean

+ overridesStartCallCost() : boolean

-options

1. .*

Page 28: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

55

EPP - Notifiche

• Domanda

– Come si fa a conoscere il numero di notifiche effettuate all’opzione

(ovvero il numero di volte che l’opzione è stata utilizzata per

contabilizzare)?

• Risposta:

– Nel metodo che consente le notifiche inserire un contatore che deve essere visibile da fuori (getX)

– Si costruisce un nuovo piano (PrecisePhonePlanWithOptions)

passando l’opzione DummyOption di cui occorre mantenere un

riferimento

– Al termine del test verificare che il valore del contatore contenuto nella DummyOption abbia il valore atteso in base alle chiamate di

cui è stato calcolato il costo

55

56

DummyOption - Dettagli• È un’opzione di test e non è detto che debba avere pienamente

senso…

• Risponde sempre true a isApplicable

• Risponde true ai vari overrideX – avere cura di restituire valori

sensati (e semplici) nei corrispondenti metodi getX

• All’invocazione del metodo di notifica (notifyIntervalAccounted –

invocato dal piano che usa l’opzione) viene incrementato un

contatore

• Al termine del test verificare se il contatore ha raggiunto il valore

atteso ovvero se l’opzione è stata usata il numero di volte previsto

56

Page 29: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

57

EPP – Note • Notare che il testing di PrecisePhonePlanWithOptions

è indipendente dal testing delle opzioni concrete

“commerciali”

• È stato inserito in un ambiente artificiale di cui la nuova DummyOption fa parte

• Ed è stato sollecitato per verificare le attese

• Si può fare di meglio?

– Eliminare le altre dipendenze concrete (Operator) – come?

– In fase di test, utilizzare un’implementazione alternativa di Operator (più semplice) che NON coinvolga l’entità Band

57

58

Note generali sul testing

• L’oggetto/componente argomento di test dovrebbe essere

quanto più isolato possibile…

• …ed immerso in un ambiente il più artificiale possibile…

• …in modo da evitare che il funzionamento (o il NON

funzionamento) del componente stesso sia influenzato dal

funzionamento (o NON funzionamento) degli oggetti che

fanno parte del suo ambiente

58

Page 30: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

59

Note generali sul testing

• In termini di design, è necessario che una classe

abbia quante meno dipendenze concrete possibile

– per massimizzare la riusabilità – l’unità riusabile è

composta dall’oggetto più tutte le sue dipendenze

concrete)

– per facilitare il testing – l’oggetto è completamente

isolabile e può essere immerso in un ambiente

completamente artificiale: gli oggetti concreti al contorno

sono appositamente studiati solo per i test

59

60

Opzioni• Implementare l’opzione YouMeAndTheOther

– Due numeri di telefono a tariffa flat (da definire)

– Intervallo di tariffazione a 60 secondi

– Nessuno scatto alla risposta

• Implementare l’opzione FlatTime

– Mette a disposizione un certo numero di minuti “prepagati” (definibili

all’atto della costruzione)

– Intervallo di tariffazione a 30 secondi

– Nessuno scatto alla risposta

• Verificare il corretto funzionamento delle opzioni

implementate (un test JUnit per ogni classe) prima di

utilizzarle all’interno di un piano

60

Page 31: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

61

Soluzione - PhonePlanpublic abstract class PhonePlan

{

private String name;

private int interval;

private double startCallCost;

private Operator[] operators;

protected PhonePlan(String name, int interval, int

startCallCost, Operator[] operators)

{

this.name = name;

this.interval = interval; //in millisecondi

this.startCallCost = startCallCost;

this.operators = operators;

}

} 61

PhonePlan modella un piano

telefonico astratto che

definisce solo ciò che è

indipendente da una specifica

implementazione.

62

Soluzione - PhonePlan…

public String getName()

{

return name;

}

public int getInterval()

{

return interval;

}

public double getStartCallCost()

{

return startCallCost;

}

public abstract double getCallCost(Date callStart, Date

callEnd, String destOperator, String destNumber);

62

getCallCost rappresenta

l’implementazione del calcolo del

costo di una chiamata

getCallCost deve essere

definito come metodo astratto.

Page 32: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

63

Soluzione - PhonePlan…

public double getCallCost(PhoneCall call)

{

return getCallCost(call.getCallStart(),

call.getCallEnd(), call.getDestOperator(),

call.getDestNumber());

}

public boolean isValid()

{

for (Operator operator : operators)

{

if (!operator.isValid())

return false;

}

return true;

}

… 63

64

Soluzione - PhonePlan…

protected Operator getOperatorByName(String operatorName)

{

Operator selected = null;

for (Operator o : operators)

{

if (o.getName().equals(operatorName))

{

selected = o;

break;

}

}

return selected;

}

64

Page 33: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

65

Soluzione - PrecisePlanpublic class PrecisePlan extends PhonePlan

{

public PrecisePlan(String name, int interval, int

startCallCost, Operator[] operators)

{

super(name, interval, startCallCost, operators);

}

@Override

public double getCallCost(Date callStart, Date callEnd,

String destOperator, String destNumber)

{

Operator selected = getOperatorByName(destOperator);

if (selected == null)

return -1;

}

}65

PrecisePlan definisce l’algoritmo “preciso” per il calcolo

del costo di una chiamata.

66

Soluzione – PrecisePlan…

GregorianCalendar cal = new GregorianCalendar();

cal.setTime(callStart);

Date currentDateTime = cal.getTime();

double durationCost = 0;

while (currentDateTime.compareTo(callEnd) < 0)

{

durationCost +=

selected.getCostPerInterval(currentDateTime);

cal.setTime(currentDateTime);

cal.add(GregorianCalendar.MILLISECOND, getInterval());

currentDateTime = cal.getTime();

}

return getStartCallCost() + durationCost;

66

Page 34: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

67

Soluzione - PrecisePlanTestpublic class PrecisePlanTest

{

public static PrecisePlan createPlan()

{

return new PrecisePlan("TIM", 1000, 10, new Operator[]

{OperatorTest.createOperator()});

}

@Test

public void testGetCallCost()

{

PhonePlan plan = createPlan();

GregorianCalendar cal = new GregorianCalendar();

}

}67

68

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 24);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

68

Crea l’inizio chiamata …

Page 35: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

69

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 27);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual =

plan.getCallCost(callStart, callEnd, "TIM", "");

assertEquals(1810, actual);

}69

… crea la fine chiamataappartenente alla stessa

fascia oraria e …

… verifica che il costo della chiamata sia quello

che ci aspettiamo.

70

Soluzione - PrecisePlanTest…

@Test

public void testGetCallCost_CrossBand()

{

PhonePlan plan = createPlan();

GregorianCalendar cal = new GregorianCalendar();

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 18);

cal.set(GregorianCalendar.MINUTE, 28);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

…70

Crea l’inizio chiamata …

Page 36: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

71

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 18);

cal.set(GregorianCalendar.MINUTE, 31);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual = plan.getCallCost(callStart, callEnd,

"TIM", "");

assertEquals(3010, actual);

}

71

… crea la fine chiamataappartenente ad una

fascia oraria diversa e …

… verifica che il costo della chiamata sia quello

che ci aspettiamo.

72

Soluzione - PrecisePlanTest…

@Test

public void testGetCallCost_CrossBand_Dat()

{

PhonePlan plan = createPlan();

GregorianCalendar cal = new GregorianCalendar();

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 23);

cal.set(GregorianCalendar.MINUTE,58);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

…72

Crea l’inizio chiamata …

Page 37: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

73

Soluzione - PrecisePlanTest

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.THURSDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 0);

cal.set(GregorianCalendar.MINUTE, 0);

cal.set(GregorianCalendar.SECOND, 30);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual = plan.getCallCost(callStart, callEnd,

"TIM", "");

assertEquals(1510, actual);

}

73

… crea la fine chiamataappartenente ad una

fascia oraria diversa e …

… verifica che il costo della chiamata sia quello

che ci aspettiamo.

74

Soluzione - Option

public abstract class Option

{

public abstract boolean isApplicable(Date istantTime,

Operator operator, String destNumber);

public abstract boolean overridesCostPerInterval();

public abstract double getCostPerInterval();

public abstract boolean overridesInterval();

public abstract int getInterval();

public abstract boolean overridesStartCallCost();

public abstract double getStartCallCost();

public abstract void notifyIntervalAccounted();

}74

Option modella un’entità che: 1) permette di ridefinire uno o

più parametri del piano tariffario; 2) può avere uno stato che cambia in base al suo utilizzo.

Page 38: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

75

Soluzione - PrecisePlanWithOptionspublic class PrecisePlanWithOptions extends PhonePlan

{

private Option[] options;

public PrecisePlanWithOptions(String name, int interval,

int startCallCost, Operator[] operators,

Option[] options)

{

super(name, interval, startCallCost, operators);

this.options = options;

}

public Option[] getOptions()

{

return options;

}

} 75

Contiene un insieme di opzioni di cui non conosce i dettegli implementativi!

PrecisePlanWithOption

modella un piano con opzioni.

76

@Override

public double getCallCost(Date callStart, Date callEnd,

String destOperator, String destNumber)

{

Operator selected = getOperatorByName(destOperator);

if (selected == null)

return -1;

GregorianCalendar cal = new GregorianCalendar();

cal.setTime(callStart);

Date currentDateTime = cal.getTime();

double startCallCost =

getStartCallCost(currentDateTime, selected,

destNumber);

}

76

Soluzione - PrecisePlanWithOptions

Page 39: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

77

double durationCost = 0;

while (currentDateTime.compareTo(callEnd) < 0)

{

Option option =

findApplicableOption(currentDateTime, selected,

destNumber);

int intervalToAdd = getInterval();

if (option != null)

{

if (option.overridesInterval())

intervalToAdd = option.getInterval();

durationCost += option.getCostPerInterval();

option.notifyIntervalAccounted();

}

… 77

Sfrutta le opzioni nel calcolo del costo di una chiamata.

Sfrutta la prima opzione applicabile nel calcolo del costo di una chiamata.

Soluzione - PrecisePlanWithOptions

78

else

{

durationCost +=

selected.getCostPerInterval(currentDateTime);

}

cal.setTime(currentDateTime);

cal.add(GregorianCalendar.MILLISECOND,

intervalToAdd);

currentDateTime = cal.getTime();

}

return startCallCost() + durationCost;

}

78

Soluzione - PrecisePlanWithOptions

Page 40: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

79

public double getStartCallCost(Date currentTime,

Operator operator, String

destNumber)

{

Option option =

findApplicableOption(currentTime, operator,

destNumber);

return (option != null &&

option.overridesStartCallCost()) ?

option.getStartCallCost() : getStartCallCost();

}

79

Soluzione - PrecisePlanWithOptions

80

private Option findApplicableOption(Date istantTime,

Operator operator, String destNumber)

{

for (Option option : options)

{

if (option.isApplicable(istantTime, operator,

destNumber))

{

return option;

}

}

return null;

}

80

Recupera la prima opzione applicabile.

Soluzione - PrecisePlanWithOptions

Page 41: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

81

Soluzione - DummyOptionpublic class DummyOption extends Option

{

private int notificationCount;

public DummyOption()

{

notificationCount = 0;

}

public int getNotificationCount()

{

return notificationCount;

}

@Override

public double getCostPerInterval()

{

return 2;

}

}81

DummyOption è una classe

realizzata per verificare il corretto funzionamento di

PrecisePhonePlaneWithOption

82

Soluzione - DummyOption…

@Override

public int getInterval()

{

return 30000;

}

@Override

public double getStartCallCost()

{

return 0;

}

@Override

public boolean isApplicable(Date istantTime,

Operator operator, String destNumber)

{

return true;

}82

Page 42: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

83

Soluzione - DummyOption

@Override

public void notifyIntervalAccounted()

{

notificationCount++;

}

@Override

public boolean overridesCostPerInterval()

{

return true;

}

83

84

Soluzione - DummyOption

@Override

public boolean overridesInterval()

{

return true;

}

@Override

public boolean overridesStartCallCost()

{

return true;

}

84

Page 43: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

85

Soluzione - PrecisePlanWOptionsTestpublic class PrecisePlanWOptionsTest

{

public static PrecisePlanWithOptions createPlan()

{

return new PrecisePlanWithOptions("TIM", 1000, 10,

new Operator[] {OperatorTest.createOperator()},

new Option[] {new DummyOption()});

}

public static PrecisePlanWithOptions createPlan(Option[]

options)

{

return new PrecisePlanWithOptions("TIM", 1000, 10,

new Operator[] {OperatorTest.createOperator()},

options);

}

} 85

86

@Test

public void testGetCallCostDateDateStringString()

{

DummyOption1 option = new DummyOption1();

PrecisePlanWithOptions plan = createPlan(new Option[]

{ option });

GregorianCalendar cal = new GregorianCalendar();

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 24);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callStart = cal.getTime();

…86

Soluzione - PrecisePlanWOptionsTest

Page 44: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

87

cal.set(GregorianCalendar.DAY_OF_WEEK,

GregorianCalendar.WEDNESDAY);

cal.set(GregorianCalendar.HOUR_OF_DAY, 22);

cal.set(GregorianCalendar.MINUTE, 27);

cal.set(GregorianCalendar.SECOND, 0);

cal.set(GregorianCalendar.MILLISECOND, 0);

Date callEnd = cal.getTime();

double actual = plan.getCallCost(callStart, callEnd,

"TIM", "");

assertEquals(12, actual);

assertEquals(6, option.getNotificationCount());

}

87

Soluzione - PrecisePlanWOptionsTest

Verifica il sistema di override dei parametri del piano e il sistema di

notifica.

88

@Test

public void testGetStartCallCostDateOperatorString()

{

assertEquals(0.0, createPlan().getStartCallCost(new

Date(), OperatorTest.createOperator(), “MyNumber”));

}

88

Soluzione - PrecisePlanWOptionsTest

Page 45: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

89

public class YouMeAndTheOther extends Option

{

private String destNumber1;

private String destNumber2;

private double costPerInterval;

public YouMeAndTheOther(String destNumber1,

String destNumber2, double costPerInterval)

{

this.destNumber1 = destNumber1;

this.destNumber2 = destNumber2;

this.costPerInterval = costPerInterval;

}

public boolean overridesCostPerInterval()

{

return true;

}

}89

Soluzione - YouMeAndTheOther

Permette l’override del costo relativo all’intervallo di

tariffazione.

90

@Override

public double getCostPerInterval()

{

return costPerInterval;

}

@Override

public boolean isApplicable(Date istantTime,

Operator operator, String

destNumber)

{

return destNumber.equals(destNumber1) ||

destNumber.equals(destNumber2);

}

90

Soluzione - YouMeAndTheOther

L’opzione è applicabile solo se il destinatario della chiamata è

destNumber1 o destNumber2.

Page 46: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

91

@Override

public boolean overridesInterval()

{

return true;

}

@Override

public int getInterval()

{

return 30000;

}

@Override

public boolean overridesStartCallCost()

{

return true;

}

… 91

Soluzione - YouMeAndTheOther

Permette l’override dell’intervallo di tariffazione.

Permette l’override del costo relativo allo scatto alla risposta.

92

@Override

public double getStartCallCost()

{

return 0;

}

@Override

public void notifyIntervalAccounted()

{

}

@Override

public String toString()

{

return "You, Me And The Other - " + destNumber1 + " and

"

+ destNumber2;

} 92

Soluzione - YouMeAndTheOther

Page 47: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

93

public class FlatTime extends Option

{

private int flatPeriod;

public FlatTime(int flatPeriod)

{

this.flatPeriod = flatPeriod;

}

public boolean overridesCostPerInterval()

{

return true;

}

@Override

public double getCostPerInterval()

{

return 0;

}

… 93

Soluzione - FlatTime

Permette l’override del costo relativo all’intervallo di

tariffazione.

94

@Override

public boolean isApplicable(Date istantTime,

Operator operator, String destNumber)

{

return flatPeriod >= getInterval();

}

@Override

public boolean overridesInterval()

{

return true;

}

@Override

public int getInterval()

{

return 30000;

}

… 94

Soluzione - FlatTime

Permette l’override dell’intervallo di tariffazione.

E’ applicabile solo se il numero di minuti

prepagati corrente è maggiore dell’intervallo

di tariffazione.

Page 48: Fondamenti di Informatica T2 Modulo 2 - unibo.it

Università di Bologna – A.A. 2008/2009

95

@Override

public boolean overridesStartCallCost()

{

return true;

}

@Override

public double getStartCallCost()

{

return 0;

}

95

Soluzione - FlatTime

Permette l’override del costo relativo allo scatto alla risposta.

96

@Override

public void notifyIntervalAccounted()

{

flatPeriod -= getInterval();

}

@Override

public String toString()

{

return "It's a Flat Time! - Minutes left: " +

((float)flatPeriod / 60000);

}

96

Soluzione - FlatTime